This repository has been archived by the owner on Oct 3, 2019. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit dffb65e
Showing
5 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Mutable Threads | ||
=============== | ||
|
||
Introduction: | ||
------------- | ||
|
||
> Mutable Threads is an simple implementation of n3356 proposal. | ||
Depends: | ||
-------- | ||
|
||
> Mutable Threads depends on followings. | ||
> | ||
> * [Boost](http://www.boost.org/) 1.49.0 or later | ||
License: | ||
-------- | ||
|
||
Copyright Kohei Takahashi 2012. | ||
Distributed under the Boost Software License, Version 1.0. | ||
(See accompanying file LICENSE_1_0.txt or copy at | ||
http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
Author: | ||
------- | ||
|
||
> * Kohei Takahashi (flast@flast.jp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright Kohei Takahashi 2012. | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// (See accompanying file LICENSE_1_0.txt or copy at | ||
// http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#ifndef MUTABLE_THREAD_DETAIL_EXCEPTION_HPP_ | ||
#define MUTABLE_THREAD_DETAIL_EXCEPTION_HPP_ | ||
|
||
#include <string> | ||
#include <stdexcept> | ||
#include <boost/throw_exception.hpp> | ||
|
||
namespace mutable_threads { namespace detail { | ||
|
||
struct mutable_thread_exception : public std::logic_error | ||
{ | ||
explicit | ||
mutable_thread_exception(const std::string &message) | ||
: std::logic_error(message) | ||
{ | ||
} | ||
}; // struct mutable_thread_exception | ||
|
||
} } // namespace mutable_threads::detail | ||
|
||
#endif // MUTABLE_THREAD_DETAIL_EXCEPTION_HPP_ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
// Copyright Kohei Takahashi 2012. | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// (See accompanying file LICENSE_1_0.txt or copy at | ||
// http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#ifndef MUTABLE_THREAD_DETAIL_N3356_HPP_ | ||
#define MUTABLE_THREAD_DETAIL_N3356_HPP_ | ||
|
||
#include <boost/assert.hpp> | ||
#include <boost/move/move.hpp> | ||
#include <boost/utility/swap.hpp> | ||
|
||
#include <boost/smart_ptr/shared_ptr.hpp> | ||
#include <boost/smart_ptr/make_shared.hpp> | ||
|
||
#include <boost/function.hpp> | ||
#include <boost/thread/thread.hpp> | ||
#include <boost/thread/shared_mutex.hpp> | ||
#include <boost/thread/condition_variable.hpp> | ||
#include <boost/thread/locks.hpp> | ||
#include <boost/thread/barrier.hpp> | ||
|
||
#include <boost/thread/exceptions.hpp> | ||
#include <boost/system/error_code.hpp> | ||
#include <mutable_thread/detail/exception.hpp> | ||
|
||
namespace mutable_threads { namespace n3356 { | ||
|
||
class mutable_thread : private boost::thread | ||
{ | ||
typedef mutable_thread this_type; | ||
typedef boost::thread thread_type; | ||
typedef boost::function<void()> function_type; | ||
|
||
BOOST_MOVABLE_BUT_NOT_COPYABLE(mutable_thread) | ||
|
||
static void | ||
S_thraed_main_(mutable_thread *this_, boost::barrier *barrier) | ||
{ | ||
boost::shared_ptr<bool> term = this_->m_term_; | ||
boost::shared_ptr<boost::mutex> mutex = this_->m_mutex_; | ||
boost::shared_ptr<boost::condition_variable> cond = this_->m_cond_; | ||
boost::shared_ptr<function_type> func = this_->m_func_; | ||
|
||
typedef boost::unique_lock<boost::mutex> lock_type; | ||
|
||
while (true) | ||
{ | ||
lock_type guard(*mutex); | ||
if (barrier) | ||
{ | ||
barrier->wait(); | ||
barrier = NULL; | ||
} | ||
while (func->empty()) | ||
{ | ||
if (*term) { return; } // terminate | ||
cond->wait(guard); | ||
} | ||
|
||
(*func)(); | ||
func->clear(); | ||
} | ||
} | ||
|
||
public: | ||
mutable_thread() | ||
: m_term_(boost::make_shared<bool>(false)) | ||
, m_mutex_(boost::make_shared<boost::mutex>()) | ||
, m_cond_(boost::make_shared<boost::condition_variable>()) | ||
, m_func_(boost::make_shared<function_type>()) | ||
{ | ||
boost::barrier b(2); | ||
thread_type(S_thraed_main_, this, &b).swap(*this); | ||
b.wait(); | ||
} | ||
|
||
mutable_thread(BOOST_RV_REF(mutable_thread) other) BOOST_NOEXCEPT | ||
: thread_type(boost::move(static_cast<thread_type &>(other))) | ||
, m_term_(boost::move(other.m_term_)) | ||
, m_mutex_(boost::move(other.m_mutex_)) | ||
, m_cond_(boost::move(other.m_cond_)) | ||
, m_func_(boost::move(other.m_func_)) | ||
{ | ||
other.m_term_.reset(); | ||
other.m_mutex_.reset(); | ||
other.m_cond_.reset(); | ||
other.m_func_.reset(); | ||
} | ||
|
||
template <typename F> | ||
explicit | ||
mutable_thread(F f) | ||
: m_term_(boost::make_shared<bool>(false)) | ||
, m_mutex_(boost::make_shared<boost::mutex>()) | ||
, m_cond_(boost::make_shared<boost::condition_variable>()) | ||
, m_func_(boost::make_shared<function_type>(f)) | ||
{ | ||
boost::barrier b(2); | ||
thread_type(S_thraed_main_, this, &b).swap(*this); | ||
b.wait(); | ||
} | ||
|
||
mutable_thread & | ||
operator=(BOOST_RV_REF(mutable_thread) other) BOOST_NOEXCEPT | ||
{ | ||
mutable_thread(boost::move(other)).swap(*this); | ||
return *this; | ||
} | ||
|
||
void | ||
join() | ||
{ | ||
if (!joinable()) | ||
{ | ||
BOOST_THROW_EXCEPTION( | ||
detail::mutable_thread_exception("\"!joinable()\" failed")); | ||
} | ||
|
||
typedef boost::unique_lock<boost::mutex> lock_type; | ||
if (lock_type guard = lock_type(*m_mutex_)) | ||
{ | ||
*m_term_ = true; | ||
m_cond_->notify_one(); | ||
|
||
m_mutex_.reset(); | ||
m_cond_.reset(); | ||
m_func_.reset(); | ||
} | ||
thread_type::join(); | ||
m_term_.reset(); | ||
} | ||
|
||
using thread_type::joinable; | ||
|
||
template <typename F> | ||
bool | ||
try_execute(F f) | ||
{ | ||
typedef boost::unique_lock<boost::mutex> lock_type; | ||
|
||
if (is_done() || is_joining()) | ||
{ | ||
BOOST_THROW_EXCEPTION( | ||
boost::lock_error( | ||
boost::system::errc::operation_not_permitted | ||
, "\"!is_done() && !is_joining()\" failed")); | ||
} | ||
|
||
if (lock_type guard = lock_type(*m_mutex_, boost::try_to_lock)) | ||
{ | ||
if (is_done() || is_joining()) { return false; } | ||
|
||
BOOST_ASSERT(m_func_->empty()); | ||
*m_func_ = f; | ||
m_cond_->notify_one(); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
template <typename F> | ||
bool | ||
execute(F f) | ||
{ | ||
typedef boost::unique_lock<boost::mutex> lock_type; | ||
|
||
if (is_done() || is_joining()) | ||
{ | ||
BOOST_THROW_EXCEPTION( | ||
boost::lock_error( | ||
boost::system::errc::operation_not_permitted | ||
, "\"!is_done() && !is_joining()\" failed")); | ||
} | ||
|
||
if (lock_type guard = lock_type(*m_mutex_)) | ||
{ | ||
if (is_done() || is_joining()) { return false; } | ||
|
||
BOOST_ASSERT(m_func_->empty()); | ||
*m_func_ = f; | ||
m_cond_->notify_one(); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
bool | ||
is_joining() const BOOST_NOEXCEPT | ||
{ | ||
return !m_mutex_ && !m_cond_ && !m_func_ && joinable(); | ||
} | ||
|
||
bool | ||
is_done() const BOOST_NOEXCEPT | ||
{ | ||
return !m_mutex_ && !m_cond_ && !m_func_ && !joinable(); | ||
} | ||
|
||
using thread_type::id; | ||
using thread_type::get_id; | ||
using thread_type::native_handle; | ||
|
||
void | ||
swap(mutable_thread &other) BOOST_NOEXCEPT | ||
{ | ||
thread_type::swap(other); | ||
boost::swap(m_term_ , other.m_term_ ); | ||
boost::swap(m_mutex_, other.m_mutex_); | ||
boost::swap(m_cond_ , other.m_cond_ ); | ||
boost::swap(m_func_ , other.m_func_ ); | ||
} | ||
|
||
private: | ||
boost::shared_ptr<bool> m_term_; | ||
boost::shared_ptr<boost::mutex> m_mutex_; | ||
boost::shared_ptr<boost::condition_variable> m_cond_; | ||
boost::shared_ptr<function_type> m_func_; | ||
}; // class mutable_thread | ||
|
||
} } // namespace mutable_threads::n3356 | ||
|
||
#endif // MUTABLE_THREAD_DETAIL_N3356_HPP_ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright Kohei Takahashi 2012. | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// (See accompanying file LICENSE_1_0.txt or copy at | ||
// http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#ifndef MUTABLE_THREAD_MUTABLE_THREAD_HPP_ | ||
#define MUTABLE_THREAD_MUTABLE_THREAD_HPP_ | ||
|
||
#include <mutable_thread/mutable_thread_fwd.hpp> | ||
#include <mutable_thread/detail/n3356.hpp> | ||
|
||
#endif // MUTABLE_THREAD_MUTABLE_THREAD_HPP_ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright Kohei Takahashi 2012. | ||
// Distributed under the Boost Software License, Version 1.0. | ||
// (See accompanying file LICENSE_1_0.txt or copy at | ||
// http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#ifndef MUTABLE_THREAD_MUTABLE_THREAD_FWD_HPP_ | ||
#define MUTABLE_THREAD_MUTABLE_THREAD_FWD_HPP_ | ||
|
||
namespace mutable_threads { | ||
|
||
namespace n3356 { | ||
|
||
class mutable_thread; | ||
|
||
} // namespace mutable_threads::n3356 | ||
|
||
// Use n3356's implementation by default. | ||
using namespace n3356; | ||
|
||
} // namespace mutable_threads | ||
|
||
#endif // MUTABLE_THREAD_MUTABLE_THREAD_FWD_HPP_ | ||
|