Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r51782 - in sandbox/threadpool: boost boost/tp boost/tp/detail libs/tp/doc libs/tp/test
From: oliver.kowalke_at_[hidden]
Date: 2009-03-15 08:42:03


Author: olli
Date: 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
New Revision: 51782
URL: http://svn.boost.org/trac/boost/changeset/51782

Log:
* lockfree_channel added
* atomic operations added (currently only for gcc > 4.0.1)
* unit-test for lockfree_channel
* launch_in_pool() added

Added:
   sandbox/threadpool/boost/tp/detail/atomic.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/launch.hpp (contents, props changed)
   sandbox/threadpool/boost/tp/lockfree_channel.hpp (contents, props changed)
   sandbox/threadpool/libs/tp/test/test_lockfree_queue.cpp (contents, props changed)
Text files modified:
   sandbox/threadpool/boost/tp.hpp | 9 ++++++---
   sandbox/threadpool/boost/tp/task.hpp | 12 ++++++------
   sandbox/threadpool/boost/tp/unbounded_channel.hpp | 2 ++
   sandbox/threadpool/libs/tp/doc/channel.qbk | 12 +++++++++---
   sandbox/threadpool/libs/tp/doc/pool.qbk | 2 ++
   sandbox/threadpool/libs/tp/doc/pool_ref.qbk | 16 ++++++++++++++++
   sandbox/threadpool/libs/tp/test/Jamfile.v2 | 1 +
   sandbox/threadpool/libs/tp/test/test_bounded_queue_fifo.cpp | 8 +-------
   sandbox/threadpool/libs/tp/test/test_bounded_queue_lifo.cpp | 8 +-------
   sandbox/threadpool/libs/tp/test/test_bounded_queue_priority.cpp | 8 +-------
   sandbox/threadpool/libs/tp/test/test_bounded_queue_smart.cpp | 8 +-------
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_fifo.cpp | 7 +------
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_lifo.cpp | 7 +------
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_priority.cpp | 7 +------
   sandbox/threadpool/libs/tp/test/test_unbounded_queue_smart.cpp | 7 +------
   15 files changed, 50 insertions(+), 64 deletions(-)

Modified: sandbox/threadpool/boost/tp.hpp
==============================================================================
--- sandbox/threadpool/boost/tp.hpp (original)
+++ sandbox/threadpool/boost/tp.hpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -2,14 +2,17 @@
 // 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_TP_H
-#define BOOST_TP_H
+#ifndef BOOST_TP_TP_H
+#define BOOST_TP_TP_H
 
 #include <boost/tp/bounded_channel.hpp>
 #include <boost/tp/exceptions.hpp>
+#include <boost/tp/default_pool.hpp>
 #include <boost/tp/fifo.hpp>
 #include <boost/tp/info.hpp>
 #include <boost/tp/lifo.hpp>
+#include <boost/tp/launch.hpp>
+#include <boost/tp/lockfree_channel.hpp>
 #include <boost/tp/pool.hpp>
 #include <boost/tp/poolsize.hpp>
 #include <boost/tp/priority.hpp>
@@ -19,5 +22,5 @@
 #include <boost/tp/unbounded_channel.hpp>
 #include <boost/tp/watermark.hpp>
 
-#endif // BOOST_TP_H
+#endif // BOOST_TP_TP_H
 

Added: sandbox/threadpool/boost/tp/detail/atomic.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/detail/atomic.hpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -0,0 +1,33 @@
+// Copyright (c) 2008 Oliver Kowalke. 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_TP_DETAIL_ATOMIC_H
+#define BOOST_TP_DETAIL_ATOMIC_H
+
+#include <boost/assert.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/utility.hpp>
+
+namespace boost { namespace tp {
+namespace detail
+{
+template< typename A, typename C >
+bool atomic_compare_exchange( volatile A * object, C * expected, C desired)
+{ return __sync_bool_compare_and_swap( object, * expected, desired); }
+
+template< typename A, typename C >
+void atomic_store( volatile A * object, C desired)
+{ __sync_lock_test_and_set ( object, desired); }
+
+template< typename A, typename M >
+A atomic_fetch_add( volatile A * object, M operand)
+{ return __sync_fetch_and_add( object, operand); }
+
+template< typename A, typename M >
+A atomic_fetch_sub( volatile A * object, M operand)
+{ return __sync_fetch_and_sub( object, operand); }
+} } }
+
+#endif // BOOST_TP_DETAIL_ATOMIC_H
+

Added: sandbox/threadpool/boost/tp/launch.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/launch.hpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -0,0 +1,20 @@
+// Copyright (c) 2008 Oliver Kowalke. 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_TP_LAUNCH_H
+#define BOOST_TP_LAUNCH_H
+
+#include <boost/utility/result_of.hpp>
+
+#include <boost/tp/default_pool.hpp>
+#include <boost/tp/task.hpp>
+
+namespace boost { namespace tp
+{
+template< typename Act >
+task< typename result_of< Act() >::type > lauch_in_pool( Act const& act)
+{ return get_default_pool().submit( act); }
+} }
+
+#endif // BOOST_TP_LAUNCH_H

Added: sandbox/threadpool/boost/tp/lockfree_channel.hpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/boost/tp/lockfree_channel.hpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -0,0 +1,310 @@
+#ifndef BOOST_TP_LOCKFREE_CHANNEL_H
+#define BOOST_TP_LOCKFREE_CHANNEL_H
+
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/optional.hpp>
+
+#include <boost/tp/detail/atomic.hpp>
+#include <boost/tp/detail/callable.hpp>
+#include <boost/tp/detail/interrupter.hpp>
+
+namespace boost {
+namespace tp
+{
+
+class lockfree_channel
+{
+public:
+ class item
+ {
+ private:
+ detail::callable ca_;
+ detail::interrupter intr_;
+
+ public:
+ item(
+ detail::callable const& ca,
+ detail::interrupter const& intr)
+ : ca_( ca), intr_( intr)
+ { BOOST_ASSERT( ! ca_.empty() ); }
+
+ const detail::callable ca() const
+ { return ca_; }
+
+ const detail::interrupter intr() const
+ { return intr_; }
+ };
+
+private:
+ enum channel_state
+ {
+ channel_active = 0,
+ channel_deactive = 1,
+ channel_deactive_now = 2
+ };
+
+ struct node_t;
+
+ struct pointer_t
+ {
+ node_t * ptr;
+ unsigned int tag;
+
+ pointer_t()
+ : ptr( 0), tag( 0)
+ {}
+
+ pointer_t( node_t * ptr_)
+ : ptr( ptr_), tag( 0)
+ {}
+
+ pointer_t( node_t * ptr_, unsigned int tag_)
+ : ptr( ptr_), tag( tag_)
+ {}
+
+ pointer_t( pointer_t const& rhs)
+ : ptr( 0), tag( 0)
+ {
+ detail::atomic_store( & ptr, rhs.ptr);
+ detail::atomic_store( & tag, rhs.tag);
+ }
+
+ bool operator==( pointer_t const& rhs)
+ { return ptr == rhs.ptr && tag == rhs.tag; }
+
+ bool operator!=( pointer_t const& rhs)
+ { return ptr != rhs.ptr || tag != rhs.tag; }
+ };
+
+ struct node_t
+ {
+ boost::optional< item > itm;
+ pointer_t next;
+ pointer_t prev;
+
+ node_t()
+ : itm( boost::none), next(), prev()
+ {}
+
+ node_t( item const& itm_)
+ : itm( itm_), next(), prev()
+ {}
+ };
+
+ channel_state state_;
+ unsigned int size_;
+ pointer_t tail_;
+ pointer_t head_;
+
+ bool compare_exchange_( pointer_t & dest, pointer_t & cmp, pointer_t & value)
+ {
+ if ( detail::atomic_compare_exchange( & dest.ptr, & cmp.ptr, value.ptr) )
+ {
+ detail::atomic_store( & dest.tag, value.tag);
+ return true;
+ }
+
+ return false;
+ }
+
+ void fix_list_( pointer_t const& tail, pointer_t const& head)
+ {
+ pointer_t cur( tail), next, prev;
+ while ( head_ == head && cur != head)
+ {
+ next = cur.ptr->next;
+ if ( next.tag != cur.tag) return;
+ prev = next.ptr->prev;
+ pointer_t ncur( cur.ptr, cur.tag - 1);
+ if ( prev != ncur)
+ next.ptr->prev = ncur;
+ cur = pointer_t( next.ptr, cur.tag - 1);
+ }
+ }
+
+ void increment_size_()
+ { detail::atomic_fetch_add( & size_, 1); }
+
+ void decrement_size_()
+ { detail::atomic_fetch_sub( & size_, 1); }
+
+public:
+ lockfree_channel()
+ : state_( channel_active), size_( 0), tail_(), head_()
+ { tail_.ptr = head_.ptr = new node_t; }
+
+ ~lockfree_channel()
+ { clear(); }
+
+ void put( item const& itm)
+ {
+ pointer_t tail;
+ node_t * node( new node_t( itm) );
+ for (;;)
+ {
+ tail = pointer_t( tail_);
+ node->next = pointer_t( tail.ptr, tail.tag + 1);
+ pointer_t ntail( node, tail.tag + 1);
+ if ( compare_exchange_( tail_, tail, ntail) )
+ {
+ tail.ptr->prev = pointer_t( node, tail.tag);
+ increment_size_();
+ break;
+ }
+ }
+ }
+
+ bool take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ {
+ pointer_t head, tail, first;
+ node_t * dummy( 0);
+ while ( ! deactive_now() && ! ( deactive() && empty() ) )
+ {
+ head = head_;
+ tail = tail_;
+ first = head.ptr->prev;
+ boost::optional< item > val( head.ptr->itm);
+ if ( head_ == head)
+ {
+ if ( val)
+ {
+ if ( tail != head)
+ {
+ if ( first.tag != head.tag)
+ {
+ fix_list_( tail, head);
+ continue;
+ }
+ }
+ else
+ {
+ dummy = new node_t;
+ dummy->next = pointer_t( tail.ptr, tail.tag + 1);
+ pointer_t ntail( dummy, tail.tag + 1);
+ if ( compare_exchange_( tail_, tail, ntail) )
+ head.ptr->prev = pointer_t( dummy, tail.tag);
+ else
+ {
+ delete dummy;
+ dummy = 0;
+ }
+ continue;
+ }
+ pointer_t nhead( first.ptr, head.tag + 1);
+ if ( compare_exchange_( head_, head, nhead) )
+ {
+ ca = val->ca();
+ intr = val->intr();
+ delete head.ptr;
+ head.ptr = 0;
+ decrement_size_();
+ return true;
+ }
+ }
+ else
+ {
+ if ( tail.ptr == head.ptr)
+ return false;
+ else
+ {
+ if ( first.tag != head.tag)
+ {
+ fix_list_( tail, head);
+ continue;
+ }
+ pointer_t nhead( first.ptr, head.tag + 1);
+ compare_exchange_( head_, head, nhead);
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ template< typename Duration >
+ bool take(
+ detail::callable & ca,
+ detail::interrupter & intr,
+ Duration const& rel_time)
+ { return take( ca, intr); }
+
+ bool try_take(
+ detail::callable & ca,
+ detail::interrupter & intr)
+ { return take( ca, intr); }
+
+ bool active() const
+ { return state_ == channel_active; }
+
+ bool deactive() const
+ { return state_ == channel_deactive; }
+
+ bool deactive_now() const
+ { return state_ == channel_deactive_now; }
+
+ void activate()
+ { detail::atomic_store( & state_, channel_active); }
+
+ void deactivate()
+ {
+ if ( active() )
+ detail::atomic_store( & state_, channel_deactive);
+
+ BOOST_ASSERT( deactive() );
+ }
+
+ void deactivate_now()
+ {
+ if ( active() )
+ detail::atomic_store( & state_, channel_deactive_now);
+
+ BOOST_ASSERT( deactive_now() );
+ }
+
+ const std::vector< detail::callable > drain()
+ {
+ BOOST_ASSERT( deactive_now() );
+ std::vector< detail::callable > unprocessed;
+ unprocessed.reserve( size() );
+ pointer_t head( head_);
+ while ( head.ptr)
+ {
+ if ( head.ptr->itm)
+ unprocessed.push_back( head.ptr->itm->ca() );
+ head = head.ptr->prev;
+ }
+ clear();
+ BOOST_ASSERT( empty() );
+ return unprocessed;
+ }
+
+ void clear()
+ {
+ while ( head_.ptr)
+ {
+ pointer_t tmp( head_);
+ head_ = tmp.ptr->prev;
+ if ( tmp.ptr->itm)
+ decrement_size_();
+ delete tmp.ptr;
+ tmp.ptr = 0;
+ }
+ }
+
+ bool empty()
+ { return size_ <= 0; }
+
+ bool full()
+ { return false; }
+
+ std::size_t size()
+ { return size_; }
+};
+
+}}
+
+#endif // BOOST_TP_LOCKFREE_CHANNEL_H

Modified: sandbox/threadpool/boost/tp/task.hpp
==============================================================================
--- sandbox/threadpool/boost/tp/task.hpp (original)
+++ sandbox/threadpool/boost/tp/task.hpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -16,8 +16,8 @@
 class task
 {
 private:
- jss::shared_future< R > fut_;
- detail::interrupter intr_;
+ shared_future< R > fut_;
+ detail::interrupter intr_;
 
 public:
         task()
@@ -25,7 +25,7 @@
         {}
 
         task(
- jss::shared_future< R > const& fut,
+ shared_future< R > const& fut,
                 detail::interrupter const& intr)
         :
         fut_( fut),
@@ -75,8 +75,8 @@
 class task< void >
 {
 private:
- jss::shared_future< void > fut_;
- detail::interrupter intr_;
+ shared_future< void > fut_;
+ detail::interrupter intr_;
 
 public:
         task()
@@ -84,7 +84,7 @@
         {}
 
         task(
- jss::shared_future< void > const& fut,
+ shared_future< void > const& fut,
                 detail::interrupter const& intr)
         :
         fut_( fut),

Modified: sandbox/threadpool/boost/tp/unbounded_channel.hpp
==============================================================================
--- sandbox/threadpool/boost/tp/unbounded_channel.hpp (original)
+++ sandbox/threadpool/boost/tp/unbounded_channel.hpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -112,6 +112,8 @@
                 item const& itm,
                 unique_lock< shared_mutex > & lk)
         {
+ if ( ! active_() )
+ throw task_rejected("channel is not active");
                 queue_.push( itm);
                 not_empty_cond_.notify_one();
         }

Modified: sandbox/threadpool/libs/tp/doc/channel.qbk
==============================================================================
--- sandbox/threadpool/libs/tp/doc/channel.qbk (original)
+++ sandbox/threadpool/libs/tp/doc/channel.qbk 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -6,14 +6,20 @@
 ]
 
 [section:channel Channel]
-The channel synchronizes the access between application threads (producer threads) submitting __actions__ to the pool and __worker_threads__ (consumer threads). The scheduling of __actions__ queued into the channel depends on channels the scheduling policy.
+The channel synchronizes the access between application threads (producer threads) submitting __actions__ to the pool and __worker_threads__ (consumer threads). The scheduling of __actions__ queued into the channel depends on channels scheduling policy.
 If the channel becomes empty all __worker_threads__ are set to sleep until a new __action__ is put in.
 
+[heading lockfree channel]
+
+ class lockfree_channel
+
+Uses internaly a lockfree algorithm in order to get a fifo queue.
+
 [heading bounded channel]
 
     template< typename SchedulingPolicy > class bounded_channel
 
-The number of pending __actions__ is limited in order to prevent resource exhaustion. For this purpose a high and low watermark has to be passed at construction.
+Contains a single lock in order to synchronize access to the queue. The number of pending __actions__ is limited in order to prevent resource exhaustion. For this purpose a high and low watermark has to be passed at construction.
 `boost::tp::high_watermark` sets the maximum of pending tasks. If this limited is reached all threads which submit a tasks will be set to sleep (blocked).
 `boost::tp::low_watermark` sets the threshold when blocked threads get woken up.
 If __hwm__ is equal to __lwm__ everytime a sleeping producer thread will be woken up and puts
@@ -25,6 +31,6 @@
 
     template< typename SchedulingPolicy > class unbounded_channel
 
-An unlimited number of __actions__ can be queued into this channel. The insertion of __actions__ will never block. If the channel becomes empty __worker_threads__ will be set to sleep until new __actions__ are inserted into the channel.
+Contains a single lock in order to synchronize access to the queue. An unlimited number of __actions__ can be queued into this channel. The insertion of __actions__ will never block. If the channel becomes empty __worker_threads__ will be set to sleep until new __actions__ are inserted into the channel.
 
 [endsect]

Modified: sandbox/threadpool/libs/tp/doc/pool.qbk
==============================================================================
--- sandbox/threadpool/libs/tp/doc/pool.qbk (original)
+++ sandbox/threadpool/libs/tp/doc/pool.qbk 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -92,6 +92,8 @@
 of type `boost::tp::pool< boost::tp::unbounded_channel< boost::tp::fifo > >` and will contain as many __worker_threads__ as
 `boost::thread::hardware_concurrency()` returns.
 
+[heading Launch in pool]
+The free function `boost::tp::launch_in_pool( Act const& act)` submits the __action__ to the default pool and returns a task object.
 
 [heading Meta functions]
 If the __threadpool__ supports priorities `boost::tp::has_priority< pool_type >` evaluates to `true`. The priority type is determined by `boost::tp::priority_type< pool_type >`.

Modified: sandbox/threadpool/libs/tp/doc/pool_ref.qbk
==============================================================================
--- sandbox/threadpool/libs/tp/doc/pool_ref.qbk (original)
+++ sandbox/threadpool/libs/tp/doc/pool_ref.qbk 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -67,6 +67,9 @@
     };
 
         pool< unbounded_channel< fifo > > & get_default_pool();
+
+ template< typename Act >
+ task< R > launch_in_pool( Act const& act);
 
 [section:constructor_unbounded_channel_hw Constructor (unbounded channel)]
 
@@ -346,4 +349,17 @@
 [endsect]
 
 
+[section:launch_in_pool Non-member function `launch_in_pool( Act const& act)`]
+
+ template< typename Act >
+ task< R > launch_in_pool( Act const& act);
+
+[variablelist
+[[Preconditions:] [has_priority< pool >::value == false && ! ( pool.terminating() || pool.terminated() )]]
+[[Effects:] [Submits an __action__ to the default pool and returns a __task__ object.]]
+[[Throws:] [`boost::tp::task_rejected`]]
+]
+[endsect]
+
+
 [endsect]

Modified: sandbox/threadpool/libs/tp/test/Jamfile.v2
==============================================================================
--- sandbox/threadpool/libs/tp/test/Jamfile.v2 (original)
+++ sandbox/threadpool/libs/tp/test/Jamfile.v2 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -27,6 +27,7 @@
 }
 
 test-suite thread_pool :
+ [ tp-test test_lockfree_queue ]
     [ tp-test test_bounded_queue_fifo ]
     [ tp-test test_bounded_queue_lifo ]
     [ tp-test test_bounded_queue_priority ]

Modified: sandbox/threadpool/libs/tp/test/test_bounded_queue_fifo.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_bounded_queue_fifo.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_fifo.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,13 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/fifo.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/task.hpp>
-#include <boost/tp/watermark.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 

Modified: sandbox/threadpool/libs/tp/test/test_bounded_queue_lifo.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_bounded_queue_lifo.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_lifo.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,13 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/lifo.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/task.hpp>
-#include <boost/tp/watermark.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 

Modified: sandbox/threadpool/libs/tp/test/test_bounded_queue_priority.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_bounded_queue_priority.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_priority.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,13 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/priority.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/task.hpp>
-#include <boost/tp/watermark.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 

Modified: sandbox/threadpool/libs/tp/test/test_bounded_queue_smart.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_bounded_queue_smart.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_bounded_queue_smart.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,13 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/smart.hpp>
-#include <boost/tp/task.hpp>
-#include <boost/tp/watermark.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 

Added: sandbox/threadpool/libs/tp/test/test_lockfree_queue.cpp
==============================================================================
--- (empty file)
+++ sandbox/threadpool/libs/tp/test/test_lockfree_queue.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -0,0 +1,275 @@
+// Copyright (c) 2008 Oliver Kowalke. 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)
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/function.hpp>
+#include <boost/future.hpp>
+#include <boost/ref.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/barrier.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/tp/lockfree_channel.hpp>
+#include <boost/tp/exceptions.hpp>
+#include <boost/tp/fifo.hpp>
+#include <boost/tp/pool.hpp>
+#include <boost/tp/poolsize.hpp>
+#include <boost/tp/task.hpp>
+
+#include "test_functions.hpp"
+
+namespace pt = boost::posix_time;
+namespace tp = boost::tp;
+
+class fixed_unbounded_channel_fifo
+{
+public:
+ // check size, active, idle
+ void test_case_1()
+ {
+ tp::pool<
+ tp::lockfree_channel
+ > pool( tp::poolsize( 3) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 3) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
+ }
+
+ // check submit
+ void test_case_2()
+ {
+ tp::pool<
+ tp::lockfree_channel
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check shutdown
+ void test_case_3()
+ {
+ tp::pool<
+ tp::lockfree_channel
+ > pool( tp::poolsize( 1) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) ) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( t.get(), 55);
+ }
+
+ // check runtime_error throw inside task
+ void test_case_4()
+ {
+ tp::pool<
+ tp::lockfree_channel
+ > pool( tp::poolsize( 1) );
+ tp::task< void > t(
+ pool.submit(
+ boost::bind(
+ throwing_fn) ) );
+ pool.shutdown();
+ bool thrown( false);
+ try
+ { t.get(); }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown with task_rejected exception
+ void test_case_5()
+ {
+ tp::pool<
+ tp::lockfree_channel
+ > pool( tp::poolsize( 1) );
+ pool.shutdown();
+ BOOST_CHECK( pool.terminated() );
+ bool thrown( false);
+ try
+ {
+ pool.submit(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ }
+ catch ( tp::task_rejected const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check shutdown_now with thread_interrupted exception
+ void test_case_6()
+ {
+ tp::pool<
+ tp::lockfree_channel
+ > pool( tp::poolsize( 1) );
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > t(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, pt::time_duration const&) ) delay_fn,
+ fn,
+ pt::millisec( 500) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ pool.shutdown_now();
+ BOOST_CHECK( pool.terminated() );
+ BOOST_CHECK_EQUAL( pool.size(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.idle(), std::size_t( 1) );
+ BOOST_CHECK_EQUAL( pool.active(), std::size_t( 0) );
+ bool thrown( false);
+ try
+ { t.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+
+ // check pending
+ void test_case_7()
+ {
+ typedef tp::pool<
+ tp::lockfree_channel
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ tp::task< int > t1(
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) ) );
+ boost::this_thread::sleep( pt::millisec( 250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ tp::task< int > t2( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 1) );
+ tp::task< int > t3( pool.submit( fn) );
+ boost::this_thread::sleep( pt::millisec(250) );
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 2) );
+ b.wait();
+ BOOST_CHECK_EQUAL( t1.get(), 55);
+ BOOST_CHECK_EQUAL( t2.get(), 55);
+ BOOST_CHECK_EQUAL( t3.get(), 55);
+ BOOST_CHECK_EQUAL( pool.pending(), std::size_t( 0) );
+ }
+
+ // check fifo scheduling
+ void test_case_8()
+ {
+ typedef tp::pool<
+ tp::lockfree_channel
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 55);
+ BOOST_CHECK_EQUAL( buffer[1], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 2) );
+ }
+
+ // check interruptation
+ void test_case_9()
+ {
+ typedef tp::pool<
+ tp::lockfree_channel
+ > pool_type;
+ pool_type pool( tp::poolsize( 1) );
+ boost::barrier b( 2);
+ boost::function< int() > fn(
+ boost::bind(
+ fibonacci_fn,
+ 10) );
+ pool.submit(
+ boost::bind(
+ ( int ( *)( boost::function< int() > const&, boost::barrier &) ) barrier_fn,
+ fn,
+ boost::ref( b) ) );
+ std::vector< int > buffer;
+ tp::task< void > t(
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 10) ) );
+ pool.submit(
+ boost::bind(
+ buffer_fibonacci_fn,
+ boost::ref( buffer),
+ 0) );
+ t.interrupt();
+ b.wait();
+ pool.shutdown();
+ BOOST_CHECK_EQUAL( buffer[0], 0);
+ BOOST_CHECK_EQUAL( buffer.size(), std::size_t( 1) );
+ bool thrown( false);
+ try
+ { t.get(); }
+ catch ( boost::thread_interrupted const&)
+ { thrown = true; }
+ BOOST_CHECK( thrown);
+ }
+};
+
+boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
+{
+ boost::unit_test::test_suite * test( BOOST_TEST_SUITE("Boost.ThreadPool: fixed unbounded_channel< fifo > pool test suite") );
+
+ boost::shared_ptr< fixed_unbounded_channel_fifo > instance( new fixed_unbounded_channel_fifo() );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_1, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_2, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_3, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_4, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_5, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_6, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_7, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_8, instance) );
+ test->add( BOOST_CLASS_TEST_CASE( & fixed_unbounded_channel_fifo::test_case_9, instance) );
+
+ return test;
+}

Modified: sandbox/threadpool/libs/tp/test/test_unbounded_queue_fifo.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_unbounded_queue_fifo.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_fifo.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,12 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/fifo.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/task.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 

Modified: sandbox/threadpool/libs/tp/test/test_unbounded_queue_lifo.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_unbounded_queue_lifo.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_lifo.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,12 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/lifo.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/task.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 

Modified: sandbox/threadpool/libs/tp/test/test_unbounded_queue_priority.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_unbounded_queue_priority.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_priority.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,12 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/priority.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/task.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 

Modified: sandbox/threadpool/libs/tp/test/test_unbounded_queue_smart.cpp
==============================================================================
--- sandbox/threadpool/libs/tp/test/test_unbounded_queue_smart.cpp (original)
+++ sandbox/threadpool/libs/tp/test/test_unbounded_queue_smart.cpp 2009-03-15 08:41:58 EDT (Sun, 15 Mar 2009)
@@ -18,12 +18,7 @@
 #include <boost/thread/barrier.hpp>
 #include <boost/utility.hpp>
 
-#include <boost/tp/bounded_channel.hpp>
-#include <boost/tp/exceptions.hpp>
-#include <boost/tp/pool.hpp>
-#include <boost/tp/poolsize.hpp>
-#include <boost/tp/smart.hpp>
-#include <boost/tp/task.hpp>
+#include <boost/tp.hpp>
 
 #include "test_functions.hpp"
 


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