Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58314 - in sandbox/fiber/boost/fiber: detail spin
From: oliver.kowalke_at_[hidden]
Date: 2009-12-12 04:56:52


Author: olli
Date: 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
New Revision: 58314
URL: http://svn.boost.org/trac/boost/changeset/58314

Log:
pobs svn

Added:
   sandbox/fiber/boost/fiber/detail/future_traits.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/
   sandbox/fiber/boost/fiber/spin/auto_reset_event.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/barrier.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/bounded_fifo.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/condition.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/count_down_event.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/future.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/manual_reset_event.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/mutex.hpp (contents, props changed)
   sandbox/fiber/boost/fiber/spin/unbounded_fifo.hpp (contents, props changed)

Added: sandbox/fiber/boost/fiber/detail/future_traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/detail/future_traits.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,82 @@
+// (C) Copyright 2008-9 Anthony Williams
+//
+// 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 BOOST_FIBERS_DETAIL_FUTURE_TRAITSHPP
+#define BOOST_FIBERS_DETAIL_FUTURE_TRAITSHPP
+
+#include <algorithm>
+#include <list>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/config.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
+
+namespace boost {
+namespace fibers {
+namespace detail {
+
+template<typename T>
+struct future_traits
+{
+ typedef boost::scoped_ptr<T> storage_type;
+#ifdef BOOST_HAS_RVALUE_REFS
+ typedef T const& source_reference_type;
+ struct dummy;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,T&&>::type move_dest_type;
+#else
+ typedef T& source_reference_type;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T const&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T>::type move_dest_type;
+#endif
+
+ static void init(storage_type& storage,source_reference_type t)
+ { storage.reset(new T(t)); }
+
+ static void init(storage_type& storage,rvalue_source_type t)
+ { storage.reset(new T(static_cast<rvalue_source_type>(t))); }
+
+ static void cleanup(storage_type& storage)
+ { storage.reset(); }
+};
+
+template<typename T>
+struct future_traits<T&>
+{
+ typedef T* storage_type;
+ typedef T& source_reference_type;
+ struct rvalue_source_type {};
+ typedef T& move_dest_type;
+
+ static void init(storage_type& storage,T& t)
+ { storage=&t; }
+
+ static void cleanup(storage_type& storage)
+ { storage=0; }
+};
+
+template<>
+struct future_traits<void>
+{
+ typedef bool storage_type;
+ typedef void move_dest_type;
+
+ static void init(storage_type& storage)
+ { storage=true; }
+
+ static void cleanup(storage_type& storage)
+ { storage=false; }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_DETAIL_FUTURE_TRAITS_H

Added: sandbox/fiber/boost/fiber/spin/auto_reset_event.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/auto_reset_event.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,40 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 BOOST_FIBERS_SPIN_AUTO_RESET_EVENT_H
+#define BOOST_FIBERS_SPIN_AUTO_RESET_EVENT_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+class auto_reset_event : private noncopyable
+{
+private:
+ enum state_t
+ {
+ RESET = 0,
+ SET
+ };
+
+ volatile uint32_t state_;
+
+public:
+ explicit auto_reset_event( bool = false);
+
+ void set();
+
+ void wait();
+
+ bool try_wait();
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPIN_AUTO_RESET_EVENT_H

Added: sandbox/fiber/boost/fiber/spin/barrier.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/barrier.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,37 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 BOOST_FIBERS_SPIN_BARRIER_H
+#define BOOST_FIBERS_SPIN_BARRIER_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/spin/condition.hpp>
+#include <boost/fiber/spin/mutex.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+class barrier : private noncopyable
+{
+private:
+ uint32_t initial_;
+ uint32_t current_;
+ bool cycle_;
+ mutex mtx_;
+ condition cond_;
+
+public:
+ barrier( uint32_t);
+
+ bool wait();
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPIN_BARRIER_H

Added: sandbox/fiber/boost/fiber/spin/bounded_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/bounded_fifo.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,295 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 BOOST_FIBERS_SPIN_BOUNDED_FIFO_H
+#define BOOST_FIBERS_SPIN_BOUNDED_FIFO_H
+
+#include <cstddef>
+#include <stdexcept>
+
+#include <boost/cstdint.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/exceptions.hpp>
+#include <boost/fiber/spin/condition.hpp>
+#include <boost/fiber/spin/mutex.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+template< typename T >
+class bounded_fifo
+{
+public:
+ typedef optional< T > value_type;
+
+private:
+ class impl : private noncopyable
+ {
+ private:
+ struct node
+ {
+ typedef intrusive_ptr< node > ptr_t;
+
+ uint32_t use_count;
+ value_type va;
+ ptr_t next;
+
+ node() :
+ use_count( 0),
+ va(),
+ next()
+ {}
+
+ inline friend void intrusive_ptr_add_ref( node * p)
+ { ++p->use_count; }
+
+ inline friend void intrusive_ptr_release( node * p)
+ { if ( --p->use_count == 0) delete p; }
+ };
+
+ volatile uint32_t state_;
+ volatile uint32_t count_;
+ typename node::ptr_t head_;
+ mutex head_mtx_;
+ typename node::ptr_t tail_;
+ mutex tail_mtx_;
+ condition not_empty_cond_;
+ condition not_full_cond_;
+ std::size_t hwm_;
+ std::size_t lwm_;
+ volatile uint32_t use_count_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ uint32_t size_()
+ { return count_; }
+
+ bool empty_()
+ { return head_ == get_tail_(); }
+
+ bool full_()
+ { return size_() >= hwm_; }
+
+ typename node::ptr_t get_tail_()
+ {
+ mutex::scoped_lock lk( tail_mtx_);
+ typename node::ptr_t tmp = tail_;
+ return tmp;
+ }
+
+ typename node::ptr_t pop_head_()
+ {
+ typename node::ptr_t old_head = head_;
+ head_ = old_head->next;
+ detail::atomic_fetch_sub( & count_, 1);
+ return old_head;
+ }
+
+ public:
+ impl(
+ std::size_t const& hwm,
+ std::size_t const& lwm) :
+ state_( 0),
+ count_( 0),
+ head_( new node),
+ head_mtx_(),
+ tail_( head_),
+ tail_mtx_(),
+ not_empty_cond_(),
+ not_full_cond_(),
+ hwm_( hwm),
+ lwm_( lwm),
+ use_count_( 0)
+ {
+ if ( hwm_ < lwm_)
+ throw invalid_watermark();
+ }
+
+ impl( std::size_t const& wm) :
+ state_( 0),
+ count_( 0),
+ head_( new node),
+ head_mtx_(),
+ tail_( head_),
+ tail_mtx_(),
+ not_empty_cond_(),
+ not_full_cond_(),
+ hwm_( wm),
+ lwm_( wm),
+ use_count_( 0)
+ {}
+
+ void upper_bound_( std::size_t hwm)
+ {
+ if ( hwm < lwm_)
+ throw invalid_watermark();
+ std::size_t tmp( hwm_);
+ hwm_ = hwm;
+ if ( hwm_ > tmp) not_full_cond_.notify_one();
+ }
+
+ std::size_t upper_bound()
+ { return hwm_; }
+
+ void lower_bound_( std::size_t lwm)
+ {
+ if ( lwm > hwm_ )
+ throw invalid_watermark();
+ std::size_t tmp( lwm_);
+ lwm_ = lwm;
+ if ( lwm_ > tmp) not_full_cond_.notify_one();
+ }
+
+ std::size_t lower_bound()
+ { return lwm_; }
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ mutex::scoped_lock lk( head_mtx_);
+ return empty_();
+ }
+
+ void put( T const& t)
+ {
+ typename node::ptr_t new_node( new node);
+ {
+ mutex::scoped_lock lk( tail_mtx_);
+
+ if ( full_() )
+ {
+ while ( active_() && full_() )
+ not_full_cond_.wait( lk);
+ }
+ if ( ! active_() )
+ throw std::runtime_error("queue is not active");
+
+ tail_->va = t;
+ tail_->next = new_node;
+ tail_ = new_node;
+ detail::atomic_fetch_add( & count_, 1);
+ }
+ not_empty_cond_.notify_one();
+ }
+
+ bool take( value_type & va)
+ {
+ mutex::scoped_lock lk( head_mtx_);
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ while ( active_() && empty_() )
+ not_empty_cond_.wait( lk);
+ }
+ catch ( fiber_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ swap( va, head_->va);
+ pop_head_();
+ if ( size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // for submiting an action object
+ not_full_cond_.notify_all();
+ }
+ return va;
+ }
+
+ bool try_take( value_type & va)
+ {
+ mutex::scoped_lock lk( head_mtx_);
+ if ( empty_() )
+ return false;
+ swap( va, head_->va);
+ pop_head_();
+ bool valid = va;
+ if ( valid && size_() <= lwm_)
+ {
+ if ( lwm_ == hwm_)
+ not_full_cond_.notify_one();
+ else
+ // more than one producer could be waiting
+ // in order to submit an task
+ not_full_cond_.notify_all();
+ }
+ return valid;
+ }
+
+ friend void intrusive_ptr_add_ref( impl * p)
+ { detail::atomic_fetch_add( & p->use_count_, 1); }
+
+ friend void intrusive_ptr_release( impl * p)
+ { if ( detail::atomic_fetch_sub( & p->use_count_, 1) == 1) delete p; }
+ };
+
+ intrusive_ptr< impl > impl_;
+
+public:
+ bounded_fifo(
+ std::size_t const& hwm,
+ std::size_t const& lwm) :
+ impl_( new impl( hwm, lwm) )
+ {}
+
+ bounded_fifo( std::size_t const& wm) :
+ impl_( new impl( wm) )
+ {}
+
+ void upper_bound( std::size_t hwm)
+ { impl_->upper_bound( hwm); }
+
+ std::size_t upper_bound()
+ { return impl_->upper_bound(); }
+
+ void lower_bound( std::size_t lwm)
+ { impl_->lower_bound( lwm); }
+
+ std::size_t lower_bound()
+ { return impl_->lower_bound(); }
+
+ void deactivate()
+ { impl_->deactivate(); }
+
+ bool empty()
+ { return impl_->empty(); }
+
+ void put( T const& t)
+ { impl_->put( t); }
+
+ bool take( value_type & va)
+ { return impl_->take( va);}
+
+ bool try_take( value_type & va)
+ { return impl_->try_take( va); }
+};
+
+}}}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_FIBERS_SPIN_BOUNDED_FIFO_H

Added: sandbox/fiber/boost/fiber/spin/condition.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/condition.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,131 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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)
+//
+// based on boost::interprocess::sync::interprocess_condition
+
+#ifndef BOOST_FIBERS_SPIN_CONDITION_H
+#define BOOST_FIBERS_SPIN_CONDITION_H
+
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/exceptions.hpp>
+#include <boost/fiber/spin/mutex.hpp>
+#include <boost/fiber/utility.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+class condition : private noncopyable
+{
+private:
+ enum command_t
+ {
+ SLEEPING = 0,
+ NOTIFY_ONE,
+ NOTIFY_ALL
+ };
+
+ volatile uint32_t cmd_;
+ volatile uint32_t waiters_;
+ mutex enter_mtx_;
+ mutex check_mtx_;
+
+ void notify_( uint32_t);
+
+public:
+ condition();
+
+ void notify_one();
+
+ void notify_all();
+
+ void wait( unique_lock< mutex > & lk)
+ {
+ if ( ! lk)
+ throw lock_error();
+ wait( * lk.mutex() );
+ }
+
+ template< typename Pred >
+ void wait( unique_lock< mutex > & lk, Pred pred)
+ {
+ if ( ! lk)
+ throw lock_error();
+
+ while ( ! pred() )
+ wait( * lk.mutex() );
+ }
+
+ template< typename LockType >
+ void wait( LockType & lt)
+ {
+ {
+ mutex::scoped_lock lk( enter_mtx_);
+ BOOST_ASSERT( lk);
+ detail::atomic_fetch_add( & waiters_, 1);
+ lt.unlock();
+ }
+
+ bool unlock_enter_mtx = false;
+ for (;;)
+ {
+ while ( static_cast< uint32_t >( SLEEPING) == detail::atomic_load( & cmd_) )
+ this_fiber::yield();
+
+ mutex::scoped_lock lk( check_mtx_);
+ BOOST_ASSERT( lk);
+
+ uint32_t expected = static_cast< uint32_t >( NOTIFY_ONE);
+ detail::atomic_compare_exchange_strong(
+ & cmd_, & expected,
+ static_cast< uint32_t >( SLEEPING) );
+ if ( static_cast< uint32_t >( SLEEPING) == expected)
+ continue;
+ else if ( static_cast< uint32_t >( NOTIFY_ONE) == expected)
+ {
+ unlock_enter_mtx = true;
+ detail::atomic_fetch_sub( & waiters_, 1);
+ break;
+ }
+ else
+ {
+ unlock_enter_mtx = 1 == detail::atomic_fetch_sub( & waiters_, 1);
+ if ( unlock_enter_mtx)
+ {
+ expected = static_cast< uint32_t >( NOTIFY_ALL);
+ detail::atomic_compare_exchange_strong(
+ & cmd_, & expected,
+ static_cast< uint32_t >( SLEEPING) );
+ }
+ break;
+ }
+ }
+
+ if ( unlock_enter_mtx)
+ enter_mtx_.unlock();
+
+ lt.lock();
+ }
+
+ template<
+ typename LockType,
+ typename Pred
+ >
+ void wait( LockType & lt, Pred pred)
+ {
+ while ( ! pred() )
+ wait( lt);
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPIN_CONDITION_H

Added: sandbox/fiber/boost/fiber/spin/count_down_event.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/count_down_event.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,39 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 BOOST_FIBERS_SPIN_COUNT_DOWN_EVENT_H
+#define BOOST_FIBERS_SPIN_COUNT_DOWN_EVENT_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+class count_down_event : private noncopyable
+{
+private:
+ uint32_t initial_;
+ volatile uint32_t current_;
+
+public:
+ explicit count_down_event( uint32_t);
+
+ uint32_t initial() const;
+
+ uint32_t current() const;
+
+ bool is_set() const;
+
+ void set();
+
+ void wait();
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPIN_COUNT_DOWN_EVENT_H

Added: sandbox/fiber/boost/fiber/spin/future.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/future.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,1197 @@
+// (C) Copyright 2008-9 Anthony Williams
+//
+// 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 BOOST_FIBERS_SPIN_FUTURE_HPP
+#define BOOST_FIBERS_SPIN_FUTURE_HPP
+
+#include <algorithm>
+#include <list>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/config.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/next_prior.hpp>
+#include <boost/ref.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/fiber/detail/future_traits.hpp>
+#include <boost/fiber/spin/condition.hpp>
+#include <boost/fiber/spin/mutex.hpp>
+
+namespace boost {
+namespace fibers {
+
+namespace future_state {
+
+ enum state { uninitialized, waiting, ready, moved };
+
+}
+
+namespace spin {
+namespace detail {
+
+struct future_object_base
+{
+ boost::exception_ptr exception;
+ bool done;
+ mutex mtx;
+ condition waiters;
+ typedef std::list<condition*> waiter_list;
+ waiter_list external_waiters;
+ boost::function<void()> callback;
+
+ future_object_base():
+ done(false)
+ {}
+
+ virtual ~future_object_base()
+ {}
+
+ waiter_list::iterator register_external_waiter(condition& cv)
+ {
+ boost::unique_lock<mutex> lock(mtx);
+ do_callback(lock);
+ return external_waiters.insert(external_waiters.end(),&cv);
+ }
+
+ void remove_external_waiter(waiter_list::iterator it)
+ {
+ boost::lock_guard<mutex> lock(mtx);
+ external_waiters.erase(it);
+ }
+
+ void mark_finished_internal()
+ {
+ done=true;
+ waiters.notify_all();
+ for(waiter_list::const_iterator it=external_waiters.begin(),
+ end=external_waiters.end();it!=end;++it)
+ {
+ (*it)->notify_all();
+ }
+ }
+
+ struct relocker
+ {
+ boost::unique_lock<mutex>& lock;
+
+ relocker(boost::unique_lock<mutex>& lock_):
+ lock(lock_)
+ {
+ lock.unlock();
+ }
+ ~relocker()
+ {
+ lock.lock();
+ }
+ };
+
+ void do_callback(boost::unique_lock<mutex>& lock)
+ {
+ if(callback && !done)
+ {
+ boost::function<void()> local_callback=callback;
+ relocker relock(lock);
+ local_callback();
+ }
+ }
+
+
+ void wait(bool rethrow=true)
+ {
+ boost::unique_lock<mutex> lock(mtx);
+ do_callback(lock);
+ while(!done)
+ {
+ waiters.wait(lock);
+ }
+ if(rethrow && exception)
+ {
+ boost::rethrow_exception(exception);
+ }
+ }
+
+ void mark_exceptional_finish_internal(boost::exception_ptr const& e)
+ {
+ exception=e;
+ mark_finished_internal();
+ }
+ void mark_exceptional_finish()
+ {
+ boost::lock_guard<mutex> lock(mtx);
+ mark_exceptional_finish_internal(boost::current_exception());
+ }
+
+ bool has_value()
+ {
+ boost::lock_guard<mutex> lock(mtx);
+ return done && !exception;
+ }
+ bool has_exception()
+ {
+ boost::lock_guard<mutex> lock(mtx);
+ return done && exception;
+ }
+
+ template<typename F,typename U>
+ void set_wait_callback(F f,U* u)
+ {
+ callback=boost::bind(f,boost::ref(*u));
+ }
+
+private:
+ future_object_base(future_object_base const&);
+ future_object_base& operator=(future_object_base const&);
+};
+
+template<typename T>
+struct future_object: future_object_base
+{
+ typedef typename fibers::detail::future_traits<T>::storage_type storage_type;
+ typedef typename fibers::detail::future_traits<T>::source_reference_type source_reference_type;
+ typedef typename fibers::detail::future_traits<T>::rvalue_source_type rvalue_source_type;
+ typedef typename fibers::detail::future_traits<T>::move_dest_type move_dest_type;
+
+ storage_type result;
+
+ future_object():
+ result(0)
+ {}
+
+ void mark_finished_with_result_internal(source_reference_type result_)
+ {
+ fibers::detail::future_traits<T>::init(result,result_);
+ mark_finished_internal();
+ }
+ void mark_finished_with_result_internal(rvalue_source_type result_)
+ {
+ fibers::detail::future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
+ mark_finished_internal();
+ }
+
+ void mark_finished_with_result(source_reference_type result_)
+ {
+ boost::lock_guard<mutex> lock(mutex);
+ mark_finished_with_result_internal(result_);
+ }
+ void mark_finished_with_result(rvalue_source_type result_)
+ {
+ boost::lock_guard<mutex> lock(mutex);
+ mark_finished_with_result_internal(result_);
+ }
+
+ move_dest_type get()
+ {
+ wait();
+ return *result;
+ }
+
+ future_state::state get_state()
+ {
+ boost::lock_guard<mutex> guard(mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
+ }
+
+private:
+ future_object(future_object const&);
+ future_object& operator=(future_object const&);
+};
+
+template<>
+struct future_object<void>: future_object_base
+{
+ future_object()
+ {}
+
+ void mark_finished_with_result_internal()
+ {
+ mark_finished_internal();
+ }
+
+ void mark_finished_with_result()
+ {
+ boost::lock_guard<mutex> lock(mutex);
+ mark_finished_with_result_internal();
+ }
+
+ void get()
+ {
+ wait();
+ }
+
+ future_state::state get_state()
+ {
+ boost::lock_guard<mutex> guard(mutex);
+ if(!done)
+ {
+ return future_state::waiting;
+ }
+ else
+ {
+ return future_state::ready;
+ }
+ }
+
+private:
+ future_object(future_object const&);
+ future_object& operator=(future_object const&);
+};
+
+class future_waiter
+{
+ struct registered_waiter
+ {
+ boost::shared_ptr<detail::future_object_base> future;
+ detail::future_object_base::waiter_list::iterator wait_iterator;
+ unsigned index;
+
+ registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_,
+ detail::future_object_base::waiter_list::iterator wait_iterator_,
+ unsigned index_):
+ future(future_),wait_iterator(wait_iterator_),index(index_)
+ {}
+
+ };
+
+ struct all_futures_lock
+ {
+ unsigned count;
+ boost::scoped_array<boost::unique_lock<mutex> > locks;
+
+ all_futures_lock(std::vector<registered_waiter>& futures):
+ count(futures.size()),locks(new boost::unique_lock<mutex>[count])
+ {
+ for(unsigned i=0;i<count;++i)
+ {
+ locks[i]=boost::unique_lock<mutex>(futures[i].future->mtx);
+ }
+ }
+
+ void lock()
+ {
+ boost::lock(locks.get(),locks.get()+count);
+ }
+
+ void unlock()
+ {
+ for(unsigned i=0;i<count;++i)
+ {
+ locks[i].unlock();
+ }
+ }
+ };
+
+ condition cv;
+ std::vector<registered_waiter> futures;
+ unsigned future_count;
+
+public:
+ future_waiter():
+ future_count(0)
+ {}
+
+ template<typename F>
+ void add(F& f)
+ {
+ if(f.future)
+ {
+ futures.push_back(registered_waiter(f.future,f.future->register_external_waiter(cv),future_count));
+ }
+ ++future_count;
+ }
+
+ unsigned wait()
+ {
+ all_futures_lock lk(futures);
+ for(;;)
+ {
+ for(unsigned i=0;i<futures.size();++i)
+ {
+ if(futures[i].future->done)
+ {
+ return futures[i].index;
+ }
+ }
+ cv.wait(lk);
+ }
+ }
+
+ ~future_waiter()
+ {
+ for(unsigned i=0;i<futures.size();++i)
+ {
+ futures[i].future->remove_external_waiter(futures[i].wait_iterator);
+ }
+ }
+
+};
+
+}
+
+template <typename R>
+class unique_future;
+
+template <typename R>
+class shared_future;
+
+template<typename T>
+struct is_future_type
+{
+ BOOST_STATIC_CONSTANT(bool, value=false);
+};
+
+template<typename T>
+struct is_future_type<unique_future<T> >
+{
+ BOOST_STATIC_CONSTANT(bool, value=true);
+};
+
+template<typename T>
+struct is_future_type<shared_future<T> >
+{
+ BOOST_STATIC_CONSTANT(bool, value=true);
+};
+
+template<typename Iterator>
+typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
+{
+ for(Iterator current=begin;current!=end;++current)
+ {
+ current->wait();
+ }
+}
+
+template<typename F1,typename F2>
+typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
+{
+ f1.wait();
+ f2.wait();
+}
+
+template<typename F1,typename F2,typename F3>
+void wait_for_all(F1& f1,F2& f2,F3& f3)
+{
+ f1.wait();
+ f2.wait();
+ f3.wait();
+}
+
+template<typename F1,typename F2,typename F3,typename F4>
+void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
+{
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ f4.wait();
+}
+
+template<typename F1,typename F2,typename F3,typename F4,typename F5>
+void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
+{
+ f1.wait();
+ f2.wait();
+ f3.wait();
+ f4.wait();
+ f5.wait();
+}
+
+template<typename Iterator>
+typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
+{
+ detail::future_waiter waiter;
+ for(Iterator current=begin;current!=end;++current)
+ {
+ waiter.add(*current);
+ }
+ return boost::next(begin,waiter.wait());
+}
+
+template<typename F1,typename F2>
+typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
+{
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ return waiter.wait();
+}
+
+template<typename F1,typename F2,typename F3>
+unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
+{
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ return waiter.wait();
+}
+
+template<typename F1,typename F2,typename F3,typename F4>
+unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
+{
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ waiter.add(f4);
+ return waiter.wait();
+}
+
+template<typename F1,typename F2,typename F3,typename F4,typename F5>
+unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
+{
+ detail::future_waiter waiter;
+ waiter.add(f1);
+ waiter.add(f2);
+ waiter.add(f3);
+ waiter.add(f4);
+ waiter.add(f5);
+ return waiter.wait();
+}
+
+template <typename R>
+class promise;
+
+template <typename R>
+class packaged_task;
+
+template <typename R>
+class unique_future
+{
+ unique_future(unique_future & rhs);// = delete;
+ unique_future& operator=(unique_future& rhs);// = delete;
+
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+
+ friend class shared_future<R>;
+ friend class promise<R>;
+ friend class packaged_task<R>;
+ friend class detail::future_waiter;
+
+ typedef typename fibers::detail::future_traits<R>::move_dest_type move_dest_type;
+
+ unique_future(future_ptr future_):
+ future(future_)
+ {}
+
+public:
+ typedef future_state::state state;
+
+ unique_future()
+ {}
+
+ ~unique_future()
+ {}
+
+#ifdef BOOST_HAS_RVALUE_REFS
+ unique_future(unique_future && other)
+ {
+ future.swap(other.future);
+ }
+ unique_future& operator=(unique_future && other)
+ {
+ future=other.future;
+ other.future.reset();
+ return *this;
+ }
+#else
+ unique_future(boost::detail::thread_move_t<unique_future> other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+
+ unique_future& operator=(boost::detail::thread_move_t<unique_future> other)
+ {
+ future=other->future;
+ other->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<unique_future>()
+ {
+ return boost::detail::thread_move_t<unique_future>(*this);
+ }
+#endif
+
+ void swap(unique_future& other)
+ {
+ future.swap(other.future);
+ }
+
+ // retrieving the value
+ move_dest_type get()
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+
+ return future->get();
+ }
+
+ // functions to check state, and wait for ready
+ state get_state() const
+ {
+ if(!future)
+ {
+ return future_state::uninitialized;
+ }
+ return future->get_state();
+ }
+
+
+ bool is_ready() const
+ {
+ return get_state()==future_state::ready;
+ }
+
+ bool has_exception() const
+ {
+ return future && future->has_exception();
+ }
+
+ bool has_value() const
+ {
+ return future && future->has_value();
+ }
+
+ void wait() const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ future->wait(false);
+ }
+};
+
+template <typename R>
+class shared_future
+{
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+
+// shared_future(const unique_future<R>& other);
+// shared_future& operator=(const unique_future<R>& other);
+
+ friend class detail::future_waiter;
+ friend class promise<R>;
+ friend class packaged_task<R>;
+
+ shared_future(future_ptr future_):
+ future(future_)
+ {}
+
+public:
+ shared_future(shared_future const& other):
+ future(other.future)
+ {}
+
+ typedef future_state::state state;
+
+ shared_future()
+ {}
+
+ ~shared_future()
+ {}
+
+ shared_future& operator=(shared_future const& other)
+ {
+ future=other.future;
+ return *this;
+ }
+#ifdef BOOST_HAS_RVALUE_REFS
+ shared_future(shared_future && other)
+ {
+ future.swap(other.future);
+ }
+ shared_future(unique_future<R> && other)
+ {
+ future.swap(other.future);
+ }
+ shared_future& operator=(shared_future && other)
+ {
+ future.swap(other.future);
+ other.future.reset();
+ return *this;
+ }
+ shared_future& operator=(unique_future<R> && other)
+ {
+ future.swap(other.future);
+ other.future.reset();
+ return *this;
+ }
+#else
+ shared_future(boost::detail::thread_move_t<shared_future> other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+// shared_future(const unique_future<R> &) = delete;
+ shared_future(boost::detail::thread_move_t<unique_future<R> > other):
+ future(other->future)
+ {
+ other->future.reset();
+ }
+ shared_future& operator=(boost::detail::thread_move_t<shared_future> other)
+ {
+ future.swap(other->future);
+ other->future.reset();
+ return *this;
+ }
+ shared_future& operator=(boost::detail::thread_move_t<unique_future<R> > other)
+ {
+ future.swap(other->future);
+ other->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<shared_future>()
+ {
+ return boost::detail::thread_move_t<shared_future>(*this);
+ }
+
+#endif
+
+ void swap(shared_future& other)
+ {
+ future.swap(other.future);
+ }
+
+ // retrieving the value
+ R get()
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+
+ return future->get();
+ }
+
+ // functions to check state, and wait for ready
+ state get_state() const
+ {
+ if(!future)
+ {
+ return future_state::uninitialized;
+ }
+ return future->get_state();
+ }
+
+
+ bool is_ready() const
+ {
+ return get_state()==future_state::ready;
+ }
+
+ bool has_exception() const
+ {
+ return future && future->has_exception();
+ }
+
+ bool has_value() const
+ {
+ return future && future->has_value();
+ }
+
+ void wait() const
+ {
+ if(!future)
+ {
+ throw future_uninitialized();
+ }
+ future->wait(false);
+ }
+};
+
+template <typename R>
+class promise
+{
+ typedef boost::shared_ptr<detail::future_object<R> > future_ptr;
+
+ future_ptr future;
+ bool future_obtained;
+
+ promise(promise & rhs);// = delete;
+ promise & operator=(promise & rhs);// = delete;
+
+ void lazy_init()
+ {
+ if(!future)
+ {
+ future_obtained=false;
+ future.reset(new detail::future_object<R>);
+ }
+ }
+
+public:
+// template <class Allocator> explicit promise(Allocator a);
+
+ promise():
+ future(),future_obtained(false)
+ {}
+
+ ~promise()
+ {
+ if(future)
+ {
+ boost::lock_guard<mutex> lock(future->mtx);
+
+ if(!future->done)
+ {
+ future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ }
+ }
+ }
+
+ // Assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ promise(promise && rhs):
+ future_obtained(rhs.future_obtained)
+ {
+ future.swap(rhs.future);
+ }
+ promise & operator=(promise&& rhs)
+ {
+ future.swap(rhs.future);
+ future_obtained=rhs.future_obtained;
+ rhs.future.reset();
+ return *this;
+ }
+#else
+ promise(boost::detail::thread_move_t<promise> rhs):
+ future(rhs->future),future_obtained(rhs->future_obtained)
+ {
+ rhs->future.reset();
+ }
+ promise & operator=(boost::detail::thread_move_t<promise> rhs)
+ {
+ future=rhs->future;
+ future_obtained=rhs->future_obtained;
+ rhs->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<promise>()
+ {
+ return boost::detail::thread_move_t<promise>(*this);
+ }
+#endif
+
+ void swap(promise& other)
+ {
+ future.swap(other.future);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // Result retrieval
+ unique_future<R> get_future()
+ {
+ lazy_init();
+ if(future_obtained)
+ {
+ throw future_already_retrieved();
+ }
+ future_obtained=true;
+ return unique_future<R>(future);
+ }
+
+ void set_value(typename fibers::detail::future_traits<R>::source_reference_type r)
+ {
+ lazy_init();
+ boost::lock_guard<mutex> lock(future->mtx);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal(r);
+ }
+
+// void set_value(R && r);
+ void set_value(typename fibers::detail::future_traits<R>::rvalue_source_type r)
+ {
+ lazy_init();
+ boost::lock_guard<mutex> lock(future->mtx);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal(static_cast<typename fibers::detail::future_traits<R>::rvalue_source_type>(r));
+ }
+
+ void set_exception(boost::exception_ptr p)
+ {
+ lazy_init();
+ boost::lock_guard<mutex> lock(future->mtx);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_exceptional_finish_internal(p);
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future->set_wait_callback(f,this);
+ }
+
+};
+
+template <>
+class promise<void>
+{
+ typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
+
+ future_ptr future;
+ bool future_obtained;
+
+ promise(promise & rhs);// = delete;
+ promise & operator=(promise & rhs);// = delete;
+
+ void lazy_init()
+ {
+ if(!future)
+ {
+ future_obtained=false;
+ future.reset(new detail::future_object<void>);
+ }
+ }
+public:
+// template <class Allocator> explicit promise(Allocator a);
+
+ promise():
+ future(),future_obtained(false)
+ {}
+
+ ~promise()
+ {
+ if(future)
+ {
+ boost::lock_guard<mutex> lock(future->mtx);
+
+ if(!future->done)
+ {
+ future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ }
+ }
+ }
+
+ // Assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ promise(promise && rhs):
+ future_obtained(rhs.future_obtained)
+ {
+ future.swap(rhs.future);
+ }
+ promise & operator=(promise&& rhs)
+ {
+ future.swap(rhs.future);
+ future_obtained=rhs.future_obtained;
+ rhs.future.reset();
+ return *this;
+ }
+#else
+ promise(boost::detail::thread_move_t<promise> rhs):
+ future(rhs->future),future_obtained(rhs->future_obtained)
+ {
+ rhs->future.reset();
+ }
+ promise & operator=(boost::detail::thread_move_t<promise> rhs)
+ {
+ future=rhs->future;
+ future_obtained=rhs->future_obtained;
+ rhs->future.reset();
+ return *this;
+ }
+
+ operator boost::detail::thread_move_t<promise>()
+ {
+ return boost::detail::thread_move_t<promise>(*this);
+ }
+#endif
+
+ void swap(promise& other)
+ {
+ future.swap(other.future);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // Result retrieval
+ unique_future<void> get_future()
+ {
+ lazy_init();
+
+ if(future_obtained)
+ {
+ throw future_already_retrieved();
+ }
+ future_obtained=true;
+ return unique_future<void>(future);
+ }
+
+ void set_value()
+ {
+ lazy_init();
+ boost::lock_guard<mutex> lock(future->mtx);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_finished_with_result_internal();
+ }
+
+ void set_exception(boost::exception_ptr p)
+ {
+ lazy_init();
+ boost::lock_guard<mutex> lock(future->mtx);
+ if(future->done)
+ {
+ throw promise_already_satisfied();
+ }
+ future->mark_exceptional_finish_internal(p);
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ lazy_init();
+ future->set_wait_callback(f,this);
+ }
+};
+
+namespace detail {
+
+template<typename R>
+struct task_base:
+ detail::future_object<R>
+{
+ bool started;
+
+ task_base():
+ started(false)
+ {}
+
+ void run()
+ {
+ {
+ boost::lock_guard<mutex> lk(this->mtx);
+ if(started)
+ {
+ throw task_already_started();
+ }
+ started=true;
+ }
+ do_run();
+ }
+
+ void owner_destroyed()
+ {
+ boost::lock_guard<mutex> lk(this->mtx);
+ if(!started)
+ {
+ started=true;
+ this->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()));
+ }
+ }
+
+
+ virtual void do_run()=0;
+};
+
+
+template<typename R,typename F>
+struct task_object:
+ task_base<R>
+{
+ F f;
+ task_object(F const& f_):
+ f(f_)
+ {}
+ task_object(boost::detail::thread_move_t<F> f_):
+ f(f_)
+ {}
+
+ void do_run()
+ {
+ try
+ {
+ this->mark_finished_with_result(f());
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+};
+
+template<typename F>
+struct task_object<void,F>:
+ task_base<void>
+{
+ F f;
+ task_object(F const& f_):
+ f(f_)
+ {}
+ task_object(boost::detail::thread_move_t<F> f_):
+ f(f_)
+ {}
+
+ void do_run()
+ {
+ try
+ {
+ f();
+ this->mark_finished_with_result();
+ }
+ catch(...)
+ {
+ this->mark_exceptional_finish();
+ }
+ }
+};
+
+}
+
+
+template<typename R>
+class packaged_task
+{
+ boost::shared_ptr<detail::task_base<R> > task;
+ bool future_obtained;
+
+ packaged_task(packaged_task&);// = delete;
+ packaged_task& operator=(packaged_task&);// = delete;
+
+public:
+ packaged_task():
+ future_obtained(false)
+ {}
+
+ // construction and destruction
+ template <class F>
+ explicit packaged_task(F const& f):
+ task(new detail::task_object<R,F>(f)),future_obtained(false)
+ {}
+ explicit packaged_task(R(*f)()):
+ task(new detail::task_object<R,R(*)()>(f)),future_obtained(false)
+ {}
+
+ template <class F>
+ explicit packaged_task(boost::detail::thread_move_t<F> f):
+ task(new detail::task_object<R,F>(f)),future_obtained(false)
+ {}
+
+// template <class F, class Allocator>
+// explicit packaged_task(F const& f, Allocator a);
+// template <class F, class Allocator>
+// explicit packaged_task(F&& f, Allocator a);
+
+
+ ~packaged_task()
+ {
+ if(task)
+ {
+ task->owner_destroyed();
+ }
+ }
+
+ // assignment
+#ifdef BOOST_HAS_RVALUE_REFS
+ packaged_task(packaged_task&& other):
+ future_obtained(other.future_obtained)
+ {
+ task.swap(other.task);
+ other.future_obtained=false;
+ }
+ packaged_task& operator=(packaged_task&& other)
+ {
+ packaged_task temp(static_cast<packaged_task&&>(other));
+ swap(temp);
+ return *this;
+ }
+#else
+ packaged_task(boost::detail::thread_move_t<packaged_task> other):
+ future_obtained(other->future_obtained)
+ {
+ task.swap(other->task);
+ other->future_obtained=false;
+ }
+ packaged_task& operator=(boost::detail::thread_move_t<packaged_task> other)
+ {
+ packaged_task temp(other);
+ swap(temp);
+ return *this;
+ }
+ operator boost::detail::thread_move_t<packaged_task>()
+ {
+ return boost::detail::thread_move_t<packaged_task>(*this);
+ }
+#endif
+
+ void swap(packaged_task& other)
+ {
+ task.swap(other.task);
+ std::swap(future_obtained,other.future_obtained);
+ }
+
+ // result retrieval
+ unique_future<R> get_future()
+ {
+ if(!task)
+ {
+ throw task_moved();
+ }
+ else if(!future_obtained)
+ {
+ future_obtained=true;
+ return unique_future<R>(task);
+ }
+ else
+ {
+ throw future_already_retrieved();
+ }
+ }
+
+
+ // execution
+ void operator()()
+ {
+ if(!task)
+ {
+ throw task_moved();
+ }
+ task->run();
+ }
+
+ template<typename F>
+ void set_wait_callback(F f)
+ {
+ task->set_wait_callback(f,this);
+ }
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPIN_FUTURE_H

Added: sandbox/fiber/boost/fiber/spin/manual_reset_event.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/manual_reset_event.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,46 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 BOOST_FIBERS_SPIN_MANUAL_RESET_EVENT_H
+#define BOOST_FIBERS_SPIN_MANUAL_RESET_EVENT_H
+
+#include <boost/cstdint.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/spin/mutex.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+class manual_reset_event : private noncopyable
+{
+private:
+ enum state_t
+ {
+ RESET = 0,
+ SET
+ };
+
+ volatile uint32_t state_;
+ volatile uint32_t waiters_;
+ mutex enter_mtx_;
+
+public:
+ explicit manual_reset_event( bool = false);
+
+ void set();
+
+ void reset();
+
+ void wait();
+
+ bool try_wait();
+};
+
+}}}
+
+#endif // BOOST_FIBERS_SPIN_MANUAL_RESET_EVENT_H

Added: sandbox/fiber/boost/fiber/spin/mutex.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/mutex.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,41 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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)
+//
+// based on boost::interprocess::sync::interprocess_spin_mutex
+
+#ifndef BOOST_FIBERS_SPIN_MUTEX_H
+#define BOOST_FIBERS_SPIN_MUTEX_H
+
+#include <boost/cstdint.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/utility.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+class mutex : private noncopyable
+{
+private:
+ volatile uint32_t state_;
+
+public:
+ typedef unique_lock< mutex > scoped_lock;
+
+ mutex();
+
+ void lock();
+
+ bool try_lock();
+
+ void unlock();
+};
+
+typedef mutex try_mutex;
+
+}}}
+
+#endif // BOOST_FIBERS_SPIN_MUTEX_H

Added: sandbox/fiber/boost/fiber/spin/unbounded_fifo.hpp
==============================================================================
--- (empty file)
+++ sandbox/fiber/boost/fiber/spin/unbounded_fifo.hpp 2009-12-12 04:56:50 EST (Sat, 12 Dec 2009)
@@ -0,0 +1,192 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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 BOOST_FIBERS_SPIN_UNBOUNDED_FIFO_H
+#define BOOST_FIBERS_SPIN_UNBOUNDED_FIFO_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/fiber/detail/atomic.hpp>
+#include <boost/fiber/exceptions.hpp>
+#include <boost/fiber/spin/condition.hpp>
+#include <boost/fiber/spin/mutex.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost {
+namespace fibers {
+namespace spin {
+
+template< typename T >
+class unbounded_fifo
+{
+public:
+ typedef optional< T > value_type;
+
+private:
+ class impl : private noncopyable
+ {
+ private:
+ struct node
+ {
+ typedef intrusive_ptr< node > ptr_t;
+
+ uint32_t use_count;
+ value_type va;
+ ptr_t next;
+
+ node() :
+ use_count( 0),
+ va(),
+ next()
+ {}
+
+ inline friend void intrusive_ptr_add_ref( node * p)
+ { ++p->use_count; }
+
+ inline friend void intrusive_ptr_release( node * p)
+ { if ( --p->use_count == 0) delete p; }
+ };
+
+ volatile uint32_t state_;
+ typename node::ptr_t head_;
+ mutex head_mtx_;
+ typename node::ptr_t tail_;
+ mutex tail_mtx_;
+ condition not_empty_cond_;
+ uint32_t use_count_;
+
+ bool active_() const
+ { return 0 == state_; }
+
+ void deactivate_()
+ { detail::atomic_fetch_add( & state_, 1); }
+
+ bool empty_()
+ { return head_ == get_tail_(); }
+
+ typename node::ptr_t get_tail_()
+ {
+ mutex::scoped_lock lk( tail_mtx_);
+ typename node::ptr_t tmp = tail_;
+ return tmp;
+ }
+
+ typename node::ptr_t pop_head_()
+ {
+ typename node::ptr_t old_head = head_;
+ head_ = old_head->next;
+ return old_head;
+ }
+
+ public:
+ impl() :
+ state_( 0),
+ head_( new node),
+ head_mtx_(),
+ tail_( head_),
+ tail_mtx_(),
+ not_empty_cond_(),
+ use_count_( 0)
+ {}
+
+ void deactivate()
+ { deactivate_(); }
+
+ bool empty()
+ {
+ mutex::scoped_lock lk( head_mtx_);
+ return empty_();
+ }
+
+ void put( T const& t)
+ {
+ typename node::ptr_t new_node( new node);
+ {
+ mutex::scoped_lock lk( tail_mtx_);
+
+ tail_->va = t;
+ tail_->next = new_node;
+ tail_ = new_node;
+ }
+ not_empty_cond_.notify_one();
+ }
+
+ bool take( value_type & va)
+ {
+ mutex::scoped_lock lk( head_mtx_);
+ bool empty = empty_();
+ if ( ! active_() && empty)
+ return false;
+ if ( empty)
+ {
+ try
+ {
+ while ( active_() && empty_() )
+ not_empty_cond_.wait( lk);
+ }
+ catch ( fiber_interrupted const&)
+ { return false; }
+ }
+ if ( ! active_() && empty_() )
+ return false;
+ swap( va, head_->va);
+ pop_head_();
+ return va;
+ }
+
+ bool try_take( value_type & va)
+ {
+ mutex::scoped_lock lk( head_mtx_);
+ if ( empty_() )
+ return false;
+ swap( va, head_->va);
+ pop_head_();
+ return va;
+ }
+
+ friend void intrusive_ptr_add_ref( impl * p)
+ { detail::atomic_fetch_add( & p->use_count_, 1); }
+
+ friend void intrusive_ptr_release( impl * p)
+ { if ( detail::atomic_fetch_sub( & p->use_count_, 1) == 1) delete p; }
+ };
+
+ intrusive_ptr< impl > impl_;
+
+public:
+ unbounded_fifo() :
+ impl_( new impl() )
+ {}
+
+ void deactivate()
+ { impl_->deactivate(); }
+
+ bool empty()
+ { return impl_->empty(); }
+
+ void put( T const& t)
+ { impl_->put( t); }
+
+ bool take( value_type & va)
+ { return impl_->take( va); }
+
+ bool try_take( value_type & va)
+ { return impl_->try_take( va); }
+};
+
+}}}
+
+#include <boost/config/abi_suffix.hpp>
+
+#endif // BOOST_FIBERS_SPIN_UNBOUNDED_FIFO_H


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk