|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r51114 - sandbox/interthreads/libs/interthreads/doc
From: vicente.botet_at_[hidden]
Date: 2009-02-08 16:28:34
Author: viboes
Date: 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
New Revision: 51114
URL: http://svn.boost.org/trac/boost/changeset/51114
Log:
interthreads version 0.4
* New free functions for all the AsynchronousCompletionToken operations, providing a higher degree of freedom.
* Missing have_all_values(), have_all_exception() and are_all_ready() functions on AsynchronousCompletionToken fusion tuples.
* get_all: getting all the values from a tuple of AsynchronousCompletionToken works now.
* fork_after overloaded for a single dependency
* wait_all overloaded for a single ACT.
* wait_for_all evaluate one of its elements on the current thread
* No need to use wait_and_get() on thread_specific_shared_ptr<> to synchronize with the decoration if the thread is created using a AsynchronousExecutor decorator. In this case the synchro is done before returning the AsynchronousCompletionToken. See the tutorial and the mono_thread_id example.
Text files modified:
sandbox/interthreads/libs/interthreads/doc/Jamfile.v2 | 6
sandbox/interthreads/libs/interthreads/doc/acknowledgements.qbk | 8
sandbox/interthreads/libs/interthreads/doc/appendices.qbk | 201 +
sandbox/interthreads/libs/interthreads/doc/case_studies.qbk | 200 +
sandbox/interthreads/libs/interthreads/doc/changes.qbk | 113
sandbox/interthreads/libs/interthreads/doc/concepts.qbk | 274 ++
sandbox/interthreads/libs/interthreads/doc/getting_started.qbk | 131
sandbox/interthreads/libs/interthreads/doc/implementation.qbk | 30
sandbox/interthreads/libs/interthreads/doc/installation.qbk | 34
sandbox/interthreads/libs/interthreads/doc/interthreads.qbk | 196 -
sandbox/interthreads/libs/interthreads/doc/introduction.qbk | 294 +-
sandbox/interthreads/libs/interthreads/doc/overview.qbk | 70
sandbox/interthreads/libs/interthreads/doc/rationale.qbk | 44
sandbox/interthreads/libs/interthreads/doc/reference.qbk | 3841 ---------------------------------------
sandbox/interthreads/libs/interthreads/doc/tutorial.qbk | 290 +-
sandbox/interthreads/libs/interthreads/doc/users_guide.qbk | 17
16 files changed, 1185 insertions(+), 4564 deletions(-)
Modified: sandbox/interthreads/libs/interthreads/doc/Jamfile.v2
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/Jamfile.v2 (original)
+++ sandbox/interthreads/libs/interthreads/doc/Jamfile.v2 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,7 +1,7 @@
-# (C) Copyright 2008-20009 Vicente J Botet Escriba.
+# (C) Copyright 2008-2009 Vicente J Botet Escriba.
#
-# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# 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)
#path-constant boost-images : ../../../../doc/src/images ;
@@ -32,7 +32,7 @@
<xsl:param>boost.libraries=../../../../libs/libraries.htm
# Use the main Boost stylesheet:
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
-
+
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
#<xsl:param>fop1.extensions=1
Modified: sandbox/interthreads/libs/interthreads/doc/acknowledgements.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/acknowledgements.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/acknowledgements.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -7,8 +7,8 @@
[section:acknowledgements Appendix D: Acknowledgments]
-Part of this library (thread_decorator and thread_specific_shared_ptr) are based on the original implementation of
-[@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming [*threadalert]] written by Roland Schwarz (thread::init and thread_member_ptr). Many Thanks to Roland that allowed me to
+Part of this library (thread_decorator and thread_specific_shared_ptr) are based on the original implementation of
+[@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming [*threadalert]] written by Roland Schwarz (thread::init and thread_member_ptr). Many Thanks to Roland that allowed me to
adapt his implementation.
Thanks also must go to Jochen Heckl for the ideas given respect to the thread_tuple::wait_first implementation.
@@ -16,6 +16,6 @@
The Threader|Joiner design is taken from [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1883.pdf N1833 - Preliminary Threading Library Proposal for TR2]
Many thanks to Kevlin Henney to make evident to me the separation between asynchonous executors, and asynchronous completion tokens.
-You can help me to make this library better! Any feedback is very welcome.
+You can help me to make this library better! Any feedback is very welcome.
[endsect]
Modified: sandbox/interthreads/libs/interthreads/doc/appendices.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/appendices.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/appendices.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,6 +1,5 @@
[/
-[/
- (C) Copyright 2008-20009 Vicente J. Botet Escriba
+ (C) Copyright 2008-2009 Vicente J. Botet Escriba
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).
@@ -12,69 +11,152 @@
[include changes.qbk]
-[include rationale.qbk]
+[/include rationale.qbk]
-[include implementation.qbk]
+[/include implementation.qbk]
[include acknowledgements.qbk]
+[include tests.qbk]
+[include tickets.qbk]
+
[/=====================================]
-[section:todo Appendix E: Future plans]
+[section:todo Appendix G: Future plans]
[/=====================================]
[section Tasks to do before review]
-[variablelist
-[[Solve the bugs] [v0.2#1]]
-[[Add polymorphic act and adapters] []]
+[heading Add an overloading for wait_for_all(ae, f, seq)]
-[[Add more examples] [ae/act framework.]]
+This will be quite useful on recursive algorithms evaluating asynchronously the same function on different parts.
-[[Complete the reference] [ae/act framework, typeof.]]
+ template <
+ typename DirectSolver,
+ typename Composer,
+ typename AsynchronousExecutor,
+ typename Input>
+ void inplace_solve(AsynchronousExecutor& ae, Problem& input) {
+ // if (problem is small)
+ if (size(range) < concurrency_threshold) {
+ // directly solve problem
+ DirectSolver()(input);
+ } else {
+ // split problem into independent parts
+ BOOST_AUTO(partition, partition_view(input));
+ // evaluates asynchronously inplace_solve on each element of the partition
+ // using the asynchronous executor as scheduler
+ wait_for_all(ae, inplace_solve, partition);
+ // compose the result in place from subresults
+ Composer()(partition);
+ }
+ }
-[[Change the rational and implementation sections] []]
-[[Use set_once to implement wait_for_any] [The current implementation uses the Boost.Futures
-wait_for_any to implement this feauture, which add an superflous constraint be able to get a future to all the AE/ACT.
-In adition the wait_for_any has now 0(N) complexity.]]
+[heading Scoped forking]
-[[Complete the tests] [Even if the current release include some test there is yet a long way before been able to review the library.]]
+In [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2802.html N2802: A plea to reconsider detach-on-destruction for thread objects]
+Hans-J. Boehm explain why is detaching on destruction so dangerous and gives two solutions: 1) replace the call to detach by a join, 2) replace by a terminate call
-[[Complete the STM example] [.]]
+The library could provide
-[[Optimize the TSSS maps using intrusive containers] [.]]
+* a RAII scoped_join which will join the assocaited act on the destructor if not already joined,
-[[Add C++0x move semantics on compilers supporting it and use the Boost.Move emulation otherwise] [.]]
+ basic_threader ae;
+ BOOST_AUTO(act,bith::fork(ae, simple_thread));
+ scoped_join<BOOST_TYPEOF(act)> j(act);
-[[Use C++0x variadic templates on compilers supporting it and the Use the preprocesor otherwise] [.]]
+* a RAII scoped_terminate which will call to teminate on the destructor if not already joined,
+
+ basic_threader ae;
+ BOOST_AUTO(act,bith::fork(ae, simple_thread));
+ scoped_terminate<BOOST_TYPEOF(act)> j(act);
+
+* a RAII scoped_fork_join which will fork on construction and join the assocaited act on the destructor if not already joined,
+
+ basic_threader ae;
+ scoped_fork_join<BOOST_TYPEOF(bith::fork(ae, simple_thread)) > act(ae, simple_thread);
+
+* a RAII scoped_fork_terminate which will fork on construction and call to teminate on the destructor if not already joined,
+
+ basic_threader ae;
+ scoped_fork_terminate<BOOST_TYPEOF(bith::fork(ae, simple_thread) > act(ae, simple_thread);
+
+* an __AE__ adapter which will return an __ACT__ that will join the assocaited act on the destructor if not already joined.
+
+ ae_scoped_fork_join<basic_threader> ae;
+ BOOST_AUTO(act,bith::fork(ae, simple_thread));
+
+* an __AE__ adapter ae_scoped_fork_terminate which will return an__ACT__ that will join the assocaited act on the destructor if not already joined.
+
+ ae_scoped_fork_terminate<basic_threader> ae;
+ BOOST_AUTO(act,bith::fork(ae, simple_thread));
+
+
+[heading Add polymorphic act and adapters]
+When we need to chain __ACT__ using the fork_after the nature of the __ACT__ can change over time, an why not change also its
+template parameter. So at least we need to make polymorphic every function used by fork_after.
+
+[heading Use set_once to implement wait_for_any]
+The current implementation uses the Boost.Futures wait_for_any to implement this feauture, which add weigth constraint:
+be able to get a future from all the AE/ACT. As AE/ACT wait_for_any evaluates the function itselfs, he can decorate the
+function and signal the first one.]]
+
+[heading Complete the tests]
+
+Even if the current release include some test there is yet a long way before been able to review the library.]]
+
+* change the test so they take less time using locks; conditions and variables.
+* Complete the test for the AE/ACT framework
+* Add test with functions throwing
+* Formalize the tests for thread_decoratoor
+* Formalize the tests for thread_specific_shared_ptr
+* Add tests for asynchronous_executor_decorator, basic_threader_decorator and threader_decorator
+* Add tests for keep alive mechanism
+
+[heading Add more examples]
+
+* Use of the ae/act framework instead of thread_tuples in the Getting Started section.
+* Complete the STM example.
+* A a parallel sort
+* Change the implementation of the file on the async_ostream.
+
+[heading Complete the reference]
+
+* ae/act framework
+* typeof
+
+[heading Change the rational and implementation sections]
-]
[endsect]
[section For later releases]
-[variablelist
-[
- [Add Message queues] [Messages queue are the next step concerning the communication between threads on the InterThreads library.]
-]
-[
- [Add Rendez-vous]
- [Concurrent components may interact in different ways: they may access the same objects by, for example,
- executing functions of these objects; or they may communicate directly by executing functions of each other.
- These library will provide the so-called rendezvous mechanism for handling direct communication between active objects.]
-]
-[
- [Add a daemon controlling all the keep alive controller threads] [This daemon will send regular keep_alive messages and kill the process when dead]
-]
-[
- [Generalize both specific pointers in a template class basic_thread_specific_ptr] []
-]
-]
+[heading Use Boost.Chrono]
+
+[heading Add C++0x move semantics on compilers supporting it and use the Boost.Move emulation otherwise]
+
+[heading Use C++0x variadic templates on compilers supporting it and use the preprocesor otherwise]
+
+[heading Use C++0x Concepts on compilers supporting them and use the Boost.ConceptCheck or Boost.ConceptTraits otherwise]
+
+[heading Add Message queues]
+Messages queue are the next step concerning the communication between threads on the InterThreads library.]
+[heading Add Rendez-vous]
+Concurrent components may interact in different ways: they may access the same objects by, for example,
+executing functions of these objects; or they may communicate directly by executing functions of each other.
+These library will provide the so-called rendezvous mechanism for handling direct communication between active objects.]
-[section `basic_thread_specific_ptr` Domain Features]
+[heading Add a daemon controlling all the keep alive controller threads]
+This daemon will send regular keep_alive messages and kill the process when dead.
+
+[heading Optimize the TSSS maps using intrusive containers]
+
+[heading Generalize both specific pointers in a template class basic_thread_specific_ptr]
+
+[*Domain Features]
[variablelist
@@ -88,58 +170,57 @@
]
-The current `thread_specific_ptr` is exclusive, has a variable key range and so the key is initialized at construction time and
+The current `thread_specific_ptr` is exclusive, has a variable key range and so the key is initialized at construction time and
explicit context setting by user on the current thread.
typedef basic_thread_specific_ptr<exclusive, variable_key_range<>, eager_context_setting> thread_specific_ptr;
-The current `thread_specific_shared_ptr` is shared, has a variable key range and so the key is initialized at construction time and
+The current `thread_specific_shared_ptr` is shared, has a variable key range and so the key is initialized at construction time and
explicit context setting by user on the current thread.
typedef basic_thread_specific_ptr<exclusive, variable_key_range<>, eager_context_setting> thread_specific_ptr;
[*Design rationale]
-`boost::thread_specific_ptr` uses as key the address of the variable. This has as consequence that
-the mapping from keys to the thread specific context pointer is much less efficient that the direct access provided
-by some implementations. In this concern this library would try to improve the performance to this mapping providing
-direct access keys. As the number of direct access keys must be know at compile time this has a limit on the number
-of thread specific pointers. A mixed approach would be also provided in which the key could be a fixed one or a
-variable one. It is up to the user to give an hint of the key sort.
-When using fixed or mixed keys, there is decision to take related to when the key is created, i.e. eager before the
+`boost::thread_specific_ptr` uses as key the address of the variable. This has as consequence that
+the mapping from keys to the thread specific context pointer is much less efficient that the direct access provided
+by some implementations. In this concern this library would try to improve the performance to this mapping providing
+direct access keys. As the number of direct access keys must be know at compile time this has a limit on the number
+of thread specific pointers. A mixed approach would be also provided in which the key could be a fixed one or a
+variable one. It is up to the user to give an hint of the key sort.
+When using fixed or mixed keys, there is decision to take related to when the key is created, i.e. eager before the
threads starts or lazy when we need it.
Non-portable: The interfaces of POSIX Pthreads, Solaris threads, and Win32 threads are very similar. However,
the semantics of Win32 threads are subtly different since they do not provide a reliable means of cleaning up objects
-allocated in thread-specific storage when a thread exits. Moreover, there is no API to delete a key in Solaris
+allocated in thread-specific storage when a thread exits. Moreover, there is no API to delete a key in Solaris
threads. This makes it hard to write portable code among UNIX and Win32 platforms.
-So we need to implement it on top of the underlying OS. The idea is to take a native thread specific pointer which
-will manage with the fixed, variable and mixed keys. This exactly the approach of `boost::thread_specific_ptr` but
+So we need to implement it on top of the underlying OS. The idea is to take a native thread specific pointer which
+will manage with the fixed, variable and mixed keys. This exactly the approach of `boost::thread_specific_ptr` but
only for variable keys.
-Just to finish, we need to decide when the context is set, two possibilities: the user sets explicitlly the context
-when it considers pertinent or the context is created lazily the first time we try to get it. The first approach has
-the liability that the user needs to ensure that the context is set before get them, but when the context must be set
-before the function thread starts this is a no issue. The second is safe but has as consequence that every access
-include a check. In addition the type must be default constructible.
+Just to finish, we need to decide when the context is set, two possibilities: the user sets explicitlly the context
+when it considers pertinent or the context is created lazily the first time we try to get it. The first approach has
+the liability that the user needs to ensure that the context is set before get them, but when the context must be set
+before the function thread starts this is a no issue. The second is safe but has as consequence that every access
+include a check. In addition the type must be default constructible.
bith::thread_specific_shared_ptr<myclass, lazy_setting> ptr;
The pointer will be initilaized when needed as if we had do
- if (ptr.get()==0) {
+ if (ptr.get()==0) {
ptr.reset( new myclass() );
}
-Between the features:
+Between the features:
-Thread_specific key mapping optimization: Replace the Boost.Thread thread_specific_ptr thread specific key mapping implementation
-by a mix of fixed/variable mapping which will provide efficient access to the fixed keys and scalability with the
+Thread_specific key mapping optimization: Replace the Boost.Thread thread_specific_ptr thread specific key mapping implementation
+by a mix of fixed/variable mapping which will provide efficient access to the fixed keys and scalability with the
others keys.
Configuration the fixed/variable/mixed key range, ordered/unordered map, intrusive/extrusive map, shared/exclusive locking.
-[endsect]
[endsect]
Modified: sandbox/interthreads/libs/interthreads/doc/case_studies.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/case_studies.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/case_studies.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J. Botet Escriba
+ (C) Copyright 2008-2009 Vicente J. Botet Escriba
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).
@@ -11,22 +11,68 @@
This section do includes complete examples using the library.
+
+[/==================================]
+[section Parallel sort]
+[/==================================]
+
+ template <
+ typename DirectSolver,
+ typename Composer,
+ typename AsynchronousExecutor,
+ typename Input>
+ void inplace_solve(AsynchronousExecutor& ae, Problem& input) {
+ // if (problem is small)
+ if (size(range) < concurrency_threshold) {
+ // directly solve problem
+ DirectSolver()(input);
+ } else {
+ // split problem into independent parts
+ BOOST_AUTO(partition, partition_view(input));
+ // evaluates asynchronously inplace_solve on each element of the partition
+ // using the asynchronous executor as scheduler
+ wait_for_all(ae, inplace_solve, partition);
+ // compose the result in place from subresults
+ Composer()(partition);
+ }
+ }
+
+So parallel sort could be
+
+ template <typename Range>
+ void parallel_sort(range& range) {
+ boost::tp::pool<> ae;
+ parallel::inplace_solve<sort, merge>(ae, input);
+ }
+
+
+
+[endsect]
+
+[/==================================]
+[section Transforming a sequential scheduler on a concurrent one]
+[/==================================]
+
+
+
+[endsect]
+
[/==================================]
[section Thread safe deferred traces]
[/==================================]
-When executing on a multi thread environment, the outputs lines on
-std::cout could interleave. We can synchronize these outputs with a
-global mutex
-
+When executing on a multi thread environment, the outputs lines on
+std::cout could interleave. We can synchronize these outputs with a
+global mutex
+
{
boost::lock_guard<boost::mutex> lock(global_cout_mutex);
std::cout << ... << std::endl ;
}
-This mutex could be the bottleneck of the system. Onle one mutex resource for all the user threads.
+This mutex could be the bottleneck of the system. Only one mutex resource for all the user threads.
-[pre
+[pre
U U
\ /
@@ -40,11 +86,11 @@
[/$images/star.png]
-Another approach could be to use a queue of output stream buffers for each thread.
-Each buffer is timestamped with the creation date and there is concentrator that takes one by one the elements ordered by the timestamp.
-Only the current thread can push on this queue because it soecific to the thread.
+Another approach could be to use a queue of output stream buffers for each thread.
+Each buffer is timestamped with the creation date and there is a concentrator that takes one by one the elements ordered by the timestamp.
+Only the current thread can push on this queue because is specific to the thread.
There is a single thread, the concentrator that pops from these queue.
-In this context we can ensure thread safety without locking as far as
+In this context we can ensure thread safety without locking as far as
the queue has at least two messages.
[/$images/fourche.png]
@@ -52,17 +98,17 @@
[pre
U ----- R ------+
- \
+ \
U ----- R ------\ \
\ \
- U ----- R -------- U
+ U ----- R -------- C
/ /
U ----- R ------/ /
/
U ----- R ------+
-]
+]
-This can be encapsulated in an async_ostream class
+This can be encapsulated in an async_ostream class
class async_ostream : public iostreams::stream<detail::async_ostream_sink> {
public:
@@ -72,7 +118,7 @@
async_ostream(std::ostream& os);
void flush();
};
-
+
extern async_ostream cout_;
@@ -80,7 +126,7 @@
cout_ << "Hello World!" << std::endl ;
-All the magic is in the `template class boost::iostreams::stream<>`. The parameter must be a model of a sink (See the Boost.Iostreams library).
+All the magic is in the `template class boost::iostreams::stream<>`. The parameter must be a model of a sink (See [@http://www.boost.org/libs/iostreams/doc/index.html [*Boost.Iostreams]]).
Here it is.
namespace detail {
@@ -89,12 +135,12 @@
typedef boost::iostreams::sink_tag category;
async_ostream_sink(std::ostream& os);
std::streamsize write(const char* s, std::streamsize n);
- void flush();
+ void flush();
private:
friend class async_ostream_concentrator;
friend class async_ostream;
struct impl;
- boost::shared_ptr<impl> impl_;
+ boost::shared_ptr<impl> impl_;
};
}
@@ -128,29 +174,29 @@
std::ostream& os_;
tsss_type tsss_;
priority_queue_type queue_;
- boost::thread thread_;
-
+ boost::thread thread_;
+
std::streamsize write(const char* s, std::streamsize n);
static void terminate(shared_ptr<async_ostream_thread_ctx> that);
static void loop(impl* that);
};
-Of course we need to store a reference to the final ostream.
+Of course we need to store a reference to the final ostream.
The `thread_specific_shared_ptr tsss_` is used to encapsulate the logic specific to each thread.
typedef thread_specific_shared_ptr<async_ostream_thread_ctx> tsss_type;
-A priority queue `queue_` will be used the concentrator thread to order the stringstreams by date.
+A priority queue `queue_` will be used by the concentrator thread to order the stringstreams by date.
template <typename T>
struct detail::timestamped {
system_time date_;
unsigned seq_;
- T value_;
+ T value_;
void reset_date(unsigned seq) {
- date_ = system_time();
+ date_ = system_time();
seq_ = seq;
}
struct ptr_comparator_gt {
@@ -160,26 +206,26 @@
(lhs->date_ == rhs->date_) && (lhs->seq_ > rhs->seq_)? true:false;
}
};
- };
+ };
typedef timestamped<std::stringstream> element_type;
typedef std::priority_queue<queue_type*, std::deque<element_type*>, element_type::ptr_comparator_gt> priority_queue_type;
-In addition to the timestamp `date_` we need a sequence number to order the stringstreams pushed without enough time granularity, e.g. on the same microsecond.
+In addition to the timestamp `date_` we need a sequence number to order the stringstreams pushed without enough time granularity, e.g. on the same microsecond.
To finish the field declaration there is the concentrator thread implemented by the loop function.
- , thread_(boost::bind(loop, this))
+ , thread_(boost::bind(loop, this))
-Comming back to the sink implementation,
-
- async_ostream_sink::impl::impl(std::ostream& os)
+Comming back to the sink implementation,
+
+ async_ostream_sink::impl::impl(std::ostream& os)
: os_(os)
, tsss_(terminate)
- , thread_(boost::bind(loop, this))
+ , thread_(boost::bind(loop, this))
{}
-The terminate cleanup function is used to ensure that the queue is empty before the thread finish.
+The terminate cleanup function is used to ensure that the queue is empty before the thread finish.
To avoid optimizations a non const call inc is done while waitig the queue empties.
void async_ostream_sink::impl::terminate(shared_ptr<async_ostream_thread_ctx> that) {
@@ -188,7 +234,7 @@
}
}
-The central sink function is write. Here instead to lock a mutex the function forwards to
+The central sink function is write. Here instead to lock a mutex the function forwards to
the thread specific shared pointer. We will see above the how `async_ostream_thread_ctx` handles this call.
std::streamsize write(const char* s, std::streamsize n) {
@@ -200,14 +246,14 @@
struct async_ostream_thread_ctx {
async_ostream_thread_ctx();
std::streamsize write(const char* s, std::streamsize n);
- void flush();
+ void flush();
element_type* get();
bool empty() const {return queue_.empty();}
void inc() {++inc_;}
private:
- unsigned seq_;
+ unsigned seq_;
element_type *current_;
- queue_type queue_;
+ queue_type queue_;
boost::mutex mutex_;
std::stringstream& buffer() {return current_->value_;}
};
@@ -219,7 +265,7 @@
return n;
}
-Once the user do a flush the current element is enqueued on the queue. The `sec_` integer is used as monotonic sequence in conjuntion with the timestamp.
+Once the user do a flush the current element is enqueued on the queue. The `sec_` integer is used as monotonic sequence in conjuntion with the timestamp.
void flush() {
current_->reset_date(seq_);
@@ -231,9 +277,9 @@
queue_.push(current_);
}
current_ = new element_type();
- }
+ }
-As stated in the introduction, we don't need to lock the mute if the umber of elements in the queue are enough.
+As stated in the introduction, we don't need to lock the mutex if the number of elements in the queue are enough.
These queue elements will be read by the concentrator using the get function.
element_type* get() {
@@ -277,31 +323,25 @@
that->queue_.pop();
os_ << "["<< e->date_ <<"-" << e->seq_ << "] " << e->value_.str();
delete e;
- }
+ }
}
}
[endsect]
-[endsect]
-
-[/============================]
-[section Case Studies]
-[/============================]
-
-This section do not includes a complete examples using the library, but a case studies that could use in some way the library.
-I'm curently working on the STM case study.
[/========================]
[section:stm STM]
[/========================]
-Transactional memory (TM) is a recent parallel programming concept which reduces challenges found in parallel programming.
+This section do not includes a complete example using the library, but a case study that could use in some way the library. I'm curently working on this.
+
+Transactional memory (TM) is a recent parallel programming concept which reduces challenges found in parallel programming.
TM offers numerous advantages over other synchronization mechanisms.
-This case study contains some thoughts on how I see a boostified version of DracoSTM, a software transactional memory (STM) system.
-DracoSTM is a high performance lock-based C++ STM research library.
-DracoSTM uses only native object-oriented language semantics, increasing its intuitiveness for developers while maintaining
+This case study contains some thoughts on how I see a boostified version of DracoSTM, a software transactional memory (STM) system.
+DracoSTM is a high performance lock-based C++ STM research library.
+DracoSTM uses only native object-oriented language semantics, increasing its intuitiveness for developers while maintaining
high programmability via automatic handling of composition, locks and transaction termination.
The example will show only the part concerning how the different context are stored.
@@ -320,9 +360,9 @@
public:
BankAccount* checkingAcct_;
BankAccount* savingsAcct_;
- AccountManager(BankAccount& checking, BankAccount& savings)
+ AccountManager(BankAccount& checking, BankAccount& savings)
: checkingAcct_(&checking)
- , savingsAcct_(&savings)
+ , savingsAcct_(&savings)
{}
void Checking2Savings(int amount) {
Transfer(checkingAcct_, savingsAcct_, amount);
@@ -330,7 +370,7 @@
};
And here a little programm that emulates an employer and two employeeds behabior
-The employee has requested to its employer to transfer its salary to its checking account every month its salary.
+The employee has requested to its employer to transfer its salary to its checking account every month its salary.
The employer do the transfer the 28th of each month.
Employee do some withdrawals and query its accounts from an ATM.
Some people has requested to the Back automatic periodic transfers from its checking account to its saving account.
@@ -342,7 +382,7 @@
BankAccount *c2;
BankAccount *s1;
AccountManager *am1;
-
+
int employer_th() {
sleep_for(day(28));
for (int i=0;i<2;++i) {
@@ -351,7 +391,7 @@
sleep(month(1));
}
}
-
+
void people_1_th() {
sleep_for(day(1));
c1->Withdraw(100);
@@ -360,7 +400,7 @@
sleep_for(day(4));
c1->Withdraw(200);
}
-
+
void automatic_transfer_th(AccountManager *am, unsigned debit) {
sleep_for(day(3));
for (int i=0;i<2;++i) {
@@ -380,13 +420,13 @@
_.commit();
}
// ...
-
+
};
-How all this works? `stm::this_tread::atomic _;` declares the scope of the variable `_` as an atomic transaction.
+How all this works? `stm::this_tread::atomic _;` declares the scope of the variable `_` as an atomic transaction.
To access this in the current transaction we use `stm::make_transactional_ptr(this)` which return a smart pointer.
-If nothing is said the transaction will be aborted at `_` destruction.
-When everything is ok we need to do a `_.commit()`.
+If nothing is said the transaction will be aborted at `_` destruction.
+When everything is ok we need to do a `_.commit()`.
When there are a lot of uses of this we can write instead
@@ -407,7 +447,7 @@
this_ptr.commit();
}
-The other `BankAccount` functions are coded as expected. Here is the code introducing a `using stm::this_tread;`
+The other `BankAccount` functions are coded as expected. Here is the code introducing a `using stm::this_tread;`
which make it mush more readable.
class BankAccount {
@@ -442,10 +482,10 @@
_.commit();
}
-The core of all this stuff is `stm::this_tread::atomic` and `stm::transactional_ptr<>`.
+The core of all this stuff is `stm::this_tread::atomic` and `stm::transactional_ptr<>`.
`stm::make_transactional_ptr()` and `stm::this_tread::atomic_ptr<>` are defined in terms of them.
-Next follows the interface of the atomic class.
+Next follows the interface of the atomic class.
namespace stm {
namespace this_thread {
@@ -457,8 +497,8 @@
};
} // this_transaction
} // stm
-
-The atomic constructor will construct a
+
+The atomic constructor will construct a
transaction on the current thread and pust it to the stack of nested transactions.
The atomic destructor will rollback the transaction if not commited and pop the stack of nested transactions.
We will see later the transaction class.
@@ -468,7 +508,7 @@
template <typename T>
class transactional_ptr {
public:
-
+
typedef T element_type;
typedef T value_type;
typedef T * pointer;
@@ -479,7 +519,7 @@
transactional_ptr(T* p, writable&tag, transaction* tr=0));
transactional_ptr(T* p, writable&tag, this_thread::atomic& scope);
-
+
transactional_ptr(T* p, is_new&tag, transaction* tr=0));
transactional_ptr(T* p, is_new&tag, this_thread::atomic& scope);
@@ -495,7 +535,7 @@
};
Let me start with the simpler constructor:
-
+
transactional_ptr(T* p);
This creates a smart pointer pointing to a specific transaction memory of the current transaction.
@@ -510,12 +550,12 @@
T& operator*();
T * get();
-By default the `transactional_ptr` points to a read only cache. When we use one of the non const operators,
+By default the `transactional_ptr` points to a read only cache. When we use one of the non const operators,
the pointers points to a upgraded write cache specific to the transaction. In the example
this_ptr->balance_ += amount;
-
-The use of `this_ptr->balance_on` the left hand side of the assignement operator requires a non const access,
+
+The use of `this_ptr->balance_on` the left hand side of the assignement operator requires a non const access,
so the upgrade to writable is done.
When we know a priori that the pointer contents will be modified we can create it as follows:
@@ -531,14 +571,14 @@
The new created objects would be wrapper by a `transactional_ptr<>` initialized like that;
transactional_ptr<BankAccount> this_ptr(new BackAccount(), is_new);
-
+
When we want ot delete a pointer in a transaction we use `transactional_ptr::delete_ptr`
transactional_ptr<BankAccount> p_ptr(p, writable);
// ...
p_ptr.delete_ptr();
-Before to finish with the `transaction` class le me show you the
+Before to finish with the `transaction` class le me show you the
`transactional_object_cache<T>` and its base class `transactional_object_cache_base`.
class transaction {
@@ -546,14 +586,14 @@
bool commit();
void rollback();
void rollback_only();
-
- template <typename T>
+
+ template <typename T>
shared_ptr<transactional_object_cache<T> > read(T* ptr);
- template <typename T>
+ template <typename T>
T* write(T* in);
- template <typename T> void delete_memory(T* in);
+ template <typename T> void delete_memory(T* in);
template <typename T>
shared_ptr<transactional_object_cache<T> > insert_in_new_cache(T* ptr);
Modified: sandbox/interthreads/libs/interthreads/doc/changes.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/changes.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/changes.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -7,26 +7,62 @@
[section:changes Appendix A: History]
+[section [*Version 0.4, January 31, 2009] bug fixes]
+
+[*New Features:]
+
+* New free functions for all the __ACT__ operations, providing a higher degree of freedom.
+* Missing `have_all_values()`, `have_all_exception()` and `are_all_ready()` functions on __ACT__ fusion tuples.
+* `get_all`: getting all the values from a tuple of __ACT__ works now.
+* fork_after overloaded for a single dependency
+* wait_all overloaded for a single ACT.
+* wait_for_all evaluate one of its elements on the current thread
+* No need to use `wait_and_get()` on `thread_specific_shared_ptr<>` to synchronize with the decoration
+if the thread is created using a __AE__ decorator. In this case the synchro is done before returning the __ACT__.
+See the tutorial and the mono_thread_id example.
+
+[*Documentation:]
+
+* New Tickets and test appendices
+
+[*Fixed Bugs:]
+
+[*v0.2#1: `ae::get_all` do not work yet.]
+`get_all()` do not work because fusion transform sequence function can not take non const sequences.
+I have emulated it using `set_all()` and a transformation for a tuple of __ACT_ to a tuple of result_type.
+
+[*v0.3.1#1: keep alive mechanism crash when setting `set_on_dead_thread()` before enabling the mechanism.]
+This was due to the fact that there were no default data for the backup.
+
+[*v0.3.1#2: keep alive mechanism do not detect dead threads.]
+We need to reset the counters only when the period is 0.
+
+[*v0.3.1#3: The `set_on_dead_thread()` setting is not recovered by embeeding kep_alive enablers/disablers.]
+The problem is that the `on_dead()` the function and the thread pointer were stored on the backup. It is enough to store
+them on the `thread_keep_alive_ctx` and make the functions thread_safe.
+
+[endsect]
+
[section [*Version 0.3.1, January 25, 2009] bug fixes]
[*Fixed Bugs:]
-[*v0.3#3: scheduler::do_test_fork_after_wait do not work yet.]
+[*v0.3#3: `scheduler::do_test_fork_after_wait` do not work yet.]
To solve this issue it enough to define boost::move for tp::task
-[*v0.3#2: scheduler::do_test_fork_after_get do not work yet.]
+[*v0.3#2: `scheduler::do_test_fork_after_get` do not work yet.]
To solve this issue it enough to define boost::move for tp::task
-[*v0.3#1: scheduler::do_test_wait_for_any do not work yet.]
+[*v0.3#1: `scheduler::do_test_wait_for_any` do not work yet.]
Not reproductible
-[*v0.2#2: Some trouble with the use of tp::pool directly, use scheduler instead.]
-Four issues.
+[*v0.2#2: Some trouble with the use of `tp::pool` directly, use `scheduler` instead.]
+Four issues.
-* The parameter to fork on tp:pool was a const F& instead of a F.
-* Direct use of fork_all resolved for the other AE by ADL, which could not be the case fro the tp::pool.
-* fork specialization for tp::pool incorrent.
-* use of the default handle instead of asynchronous_completion_token traits class
+* The parameter to fork on `tp:pool` was a `const F&` instead of a `F`.
+* Direct use of `fork_all` resolved for the other __AE__ by ADL, which could not be the case for the `tp::pool`.
+* `fork` specialization for `tp::pool` incorrect.
+* use of the default handle instead of `asynchronous_completion_token` traits class
[endsect]
@@ -34,9 +70,9 @@
[*New Features:]
-* fork_after: request the AE to execute a function asynchronously once each one of ACTs in the dependency tuple parameter are ready.
+* `fork_after`: request the __AE__ to execute a function asynchronously once each one of __ACT__ s in the dependency tuple parameter are ready.
* Add act traits, as value type, is movable, has_future_if, has_thread_if
-
+
[endsect]
[section [*Version 0.2, January 14, 2009] Asynchronous execution and test on more toolsets]
@@ -44,16 +80,16 @@
[*New Features:]
* Asynchronous executors (AE) and asynchronous completion token (ACT) framework
- * fork and fork_all functions
- * wait_for_all, wait_for_any functions
- * set_all, join_all, ...
-* unique/shared threader (AE) and unique/shared joiner(ACT) classes
-* basic_threader(AE) class
-* unique/shared launcher(AE) class
-* scheduler(AE) class (working with tp::pool(AE) and tp::task (ACT))
-* thread_decorator can now decorate a nullary function in addition to a callable function
-* asynchronous_executor_decorator mixin allows to decorate the functions launched by an asynchronous executor
-* Boost.Typeof registration for the ACT classes
+ * `fork` and `fork_all` functions
+ * `wait_for_all`, `wait_for_any` functions
+ * `set_all`, `join_all`, ...
+* `unique/shared_threader` (AE) and `unique/shared_joiner` (ACT) classes
+* `basic_threader` (AE) class
+* `unique/shared_launcher` (AE) class
+* `scheduler` (AE) class (working with `tp::pool`(AE) and `tp::task<>` (ACT))
+* `thread_decorator` can now decorate a nullary function in addition to a callable function
+* `asynchronous_executor_decorator` mixin allows to decorate the functions launched by an asynchronous executor
+* Boost.Typeof registration for the __ACT__ classes
* The AE/ACT framework comes with significant tests
[*Toolsets:]
@@ -64,7 +100,7 @@
[*Fixed Bugs:]
-[*v0.1#1: basic_keep_alive example do not link.]
+[*v0.1#1: basic_keep_alive example do not link.]
[endsect]
@@ -72,23 +108,34 @@
[*Features:]
-* thread setup/cleanup decorator,
-* thread specific shared pointer,
-* thread keep alive mechanism,
+* `thread_decorator` setup/cleanup thread decorator,
+* thread specific shared pointer,
+* thread keep alive mechanism,
* thread tuples, set_once synchonizer, thread_tuple_once and thread_group_once.
[endsect]
-
+
[section [*Bugs]]
[heading [*Open Bugs:]]
-[*v0.2#1: ae::get_all do not work yet, use set_all instead.]
-get_all do not work because fusion transform sequence function can not take non const sequences.
-Maybe we can emulate it using set_all and a mpl a transformation for a tuple of ACT to a tuple of result_type.
+[*v0.4.0#1: wait_for_any.]
[heading [*Fixed Bugs:]]
+[*v0.3.1#1: keep alive mechanism crash when setting set_on_dead_thread before enabling the mechanism.]
+This was due to the fact that there were no default data for the backup.
+
+[*v0.3.1#2: keep alive mechanism do not detect dead threads.]
+We need to reste the counters only when the period is 0.
+
+[*v0.3.1#3: The set_on_dead_thread setting is not recovered by embeeding enablers/disablers.]
+The problem is that the on_dead and th thread pointer were stored on the backup. It is enough to store them on the
+
+[*v0.2#1: ae::get_all do not work yet.]
+get_all do not work because fusion transform sequence function can not take non const sequences.
+I have emulated it using set_all and a transformation for a tuple of ACT to a tuple of result_type.
+
[*v0.3#3: scheduler::do_test_fork_after_wait do not work yet.]
To solve this issue it enough to define boost::move for tp::task
@@ -99,14 +146,14 @@
Not reproductible
[*v0.2#2: Some trouble with the use of tp::pool directly, use scheduler instead.]
-Four issues.
+Four issues.
-* The parameter to fork on tp:pool was a const F& instead of a F.
+* The parameter to fork on tp:pool was a const F& instead of a F.
* Direct use of fork_all resolved for the other AE by ADL, which could not be the case fro the tp::pool.
* fork specialization for tp::pool incorrent.
* use of the default handle instead of asynchronous_completion_token traits class
-[*v0.1#1: basic_keep_alive example do not link.]
+[*v0.1#1: basic_keep_alive example do not link.]
[endsect]
Modified: sandbox/interthreads/libs/interthreads/doc/concepts.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/concepts.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/concepts.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -12,16 +12,22 @@
[/=============================================]
+[section Decorator]
+[/=============================================]
+[endsect]
+
+[/=============================================]
[section Asynchronous Completion Token Concepts]
[/=============================================]
[/==================]
-[section Concept `ACT` ]
+[section:ACT Concept `ACT` ]
[/==================]
[heading Description]
-An __ACT__ allows to to wait for the completion of an asynchronous executed operation.
+An __ACT__ allows to wait for the completion of an asynchronous executed operation.
An __ACT__ should be __Movable__ or __CopyConstructible__.
+The completion of the __ACT__ is undefined at this level. Different models could signal this completion when setting a value or an exception.
[heading Notation]
@@ -34,30 +40,78 @@
]
[heading Expression requirements]
-A type models a __AE__ if, the following expressions are valid:
+A type models a __ACT__ if, the following expressions are valid:
[table
[[Expression] [Return type] [Runtime Complexity]]
- [[`act.wait()`] [void] [Constant]]
- [[`b = act.wait_until(abs_time)`] [bool] [Constant]]
- [[`b = act.wait_for(rel_time)`] [bool] [Constant]]
+ [[`wait(act)`] [void] [Constant]]
+ [[`b = wait_until(act, abs_time)`] [bool] [Constant]]
+ [[`b = wait_for(act, rel_time)`] [bool] [Constant]]
]
[heading Meta Expressions]
[table
- [[Expression] [Type] [Compile Time Complexity]]
- [[`is_movable<ACT>::type`] [MPL boolean] [Constant]]
- [[`has_future_if<ACT>::type`] [MPL boolean] [Constant]]
- [[`has_thread_if<ACT>::type`] [MPL boolean] [Constant]]
+ [[Expression] [Type] [Compile Time Complexity]]
+ [[`act_traits<ACT>::move_dest_type`] [Any] [Constant]]
+ [[`act_traits<ACT>::move_result`] [MPL boolean] [Constant]]
+ [[`is_movable<ACT>::type`] [MPL boolean] [Constant]]
+ [[`has_future_if<ACT>::type`] [MPL boolean] [Constant]]
+ [[`has_thread_if<ACT>::type`] [MPL boolean] [Constant]]
]
+
+
[heading Expression Semantics]
[
table
[[Expression] [Semantics]]
- [[`act.wait()`] [Waits until the `act` completes]]
- [[`b = act.wait_until(abs_time)`] [Waits until the `act` completes until `abs_time` is not reached]]
- [[`b = act.wait_for(rel_time)`] [Waits until the `act` completes for a `rel_time` duration]]
+ [[`wait(act)`] [Blocks until the `act` completes]]
+ [[`b = wait_until(act,abs_time)`] [Blocks until the `act` completes or `abs_time` is reached]]
+ [[`b = wait_for(act,rel_time)`] [Blocks until the `act` completes or `rel_time` has been elapsed]]
+]
+
+
+[heading Expression `wait(act)`]
+[/==========================================================================================]
+
+
+[variablelist
+[[Effects:] [Blocks until the `act` completes.]]
+[[Sychronization:][The completion of `act` happens before wait() returns.]]
+[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
+[[Postconditions:] [is_ready(act) == true.]]
+[[Thread safety:][unsafe]]
+]
+
+[heading Expression `b = wait_until(act,abs_time)`]
+[/==========================================================================================]
+
+ bool wait_until(const system_time& abs_time);
+ template<typename TimeDuration>
+ bool wait_for(TimeDuration const& rel_time);
+
+
+[variablelist
+[[Effects:] [Blocks until the `act` completes or `abs_time` is not reached.]]
+[[Sychronization:][The completion of the `act` happens before wait() returns.]]
+[[Returns:] [true only if the function returns because `act` is ready.]]
+[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
+[[Postconditions:] [is_ready() == true.]]
+[[Thread safety:][unsafe]]
+]
+
+[heading Expression `b = wait_for(act,rel_time)`]
+[/==========================================================================================]
+
+
+
+[variablelist
+[[Effects:] [blocks until the `act` completes or `rel_time` has elapsed.]]
+[[Sychronization:][The completion of the `act` happens before wait() returns.]]
+[[Returns:] [true only if the function returns because `act` is ready.]]
+[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
+[[Postconditions:] [is_ready() == true.]]
+[[Thread safety:][unsafe]]
]
[heading Models]
@@ -72,43 +126,83 @@
[endsect]
[/=============================]
-[section Concept `FutureBasedACT` ]
+[section:FutureBasedACT Concept `FutureBasedACT` ]
[/=============================]
+The completion of the __FutureBasedACT__ is undefined at this level but occurs usualy after a set_calue or set_exception on the associated promise.
+
[heading Description]
+
An __FutureBasedACT__ is a __ACT__ that associates a value expected on the its completion.
[heading Notation]
[variablelist
[[`act`] [An __ACT__]]
+ [[`cact`] [An const __ACT__]]
[[`f`] [A __Nullary__ function with type F]]
[[`abs_time`] [A __system_time__]]
[[`rel_time`] [A __Duration__]]
[[`b`] [A bool]]
- [[`v`] [T]]
+ [[`v`] [`act_traits<typeof(act)>::move_dest_type`]]
]
[heading Expression requirements]
-[heading Description]
A type models an __FutureBasedACT__ if, in adition to being an __ACT__,
the following expressions are valid:
[table
[[Expression] [Return type] [Runtime Complexity]]
- [[`b = act.is_ready()`] [bool] [Constant]]
- [[`b = act.has_exception()`] [bool] [Constant]]
- [[`b = act.has_value()`] [bool] [Constant]]
+ [[`v = get(act)`] [`act_traits<typeof(act)>::move_dest_type`] [Constant]]
+ [[`b = is_ready(cact)`] [bool] [Constant]]
+ [[`b = has_exception(cact)`] [bool] [Constant]]
+ [[`b = has_value(cact)`] [bool] [Constant]]
]
[heading Expression Semantics]
[table
- [[Expression] [Semantics]]
- [[`b = act.is_ready()`] [Is true only if the associated state holds a value or an exception ready for retrieval.]]
- [[`b = act.has_exception()`] [true only if the associated state contains an exception.]]
- [[`b = act.has_value()`] [true only if the associated state contains a value]]
- [[`v = act.get()`] [returns the stored value]]
+ [[Expression] [Semantics]]
+ [[`v = get(act)`] [Blocks until `act` contains a value and returns the stored value]]
+ [[`b = is_ready(cact)`] [Is true only if `cact` holds a value or an exception ready for retrieval.]]
+ [[`b = has_exception(cact)`] [Is true only if `cact` contains an exception.]]
+ [[`b = has_value(cact)`] [Is true only if `cact` contains a value]]
+]
+
+[heading Member Function `get(act)`]
+[/==========================================================================================]
+
+
+[variablelist
+[[Effects:] [Retrieves the value returned by the Nullary function.]]
+[[Sychronization:][The completion of the `act` happens before get() returns.]]
+[[Returns:] [Depending on the nature of the ACT returns a `act_traits<ACT>::move_dest_type`.]]
+[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
+[[Postconditions:] [if `act_traits<ACT>::move_result` is `true` it is unspecified what happens when `get()` is called a second time on the same shared_joiner.]]
+[[Thread safety:][unsafe]]
+]
+
+[heading Expression `b = is_ready(cact)`]
+[/==========================================================================================]
+
+[variablelist
+[[Returns:] [true only if `cact` holds a value or an exception ready for retrieval.]]
+[[Remark:] [if `act_traits<ACT>::move_result` is true the return value could be unspecified after a call to `get(act)`.]]
+]
+
+[heading Expression `b = has_exception(cact)`]
+[/==========================================================================================]
+
+
+[variablelist
+[[Returns:] [true only if `is_ready(cact)` == true and `cact` contains an exception.]]
+]
+
+[heading Expression `b = has_value(cact)`]
+[/==========================================================================================]
+
+[variablelist
+[[Returns:] [true only if `is_ready(cact)` == true and `cact` contains a value.]]
]
[heading Models]
@@ -122,22 +216,26 @@
[endsect]
[/=============================]
-[section Concept `ThreadBasedACT` ]
+[section:ThreadBasedACT Concept `ThreadBasedACT` ]
[/=============================]
+The completion of the __ThreadBasedACT__ is undefined at this level but occurs usualy after a function finish.
+
[heading Description]
-An __ThreadBasedACT__ is a __ACT__ that that provides a thread like interface.
+An __ThreadBasedACT__ is a __ACT__ that provides a thread like interface.
[heading Notation]
[variablelist
[[`act`] [An __ACT__]]
+ [[`cact`] [A const __ACT__]]
+ [[`cact`] [An const __ACT__]]
[[`f`] [A __Nullary__ function with type F]]
[[`abs_time`] [A __system_time__]]
[[`rel_time`] [A __Duration__]]
[[`b`] [A bool]]
- [[`id`] [A thread::id]]
+ [[`id`] [An `act_traits<__ACT__>::id_type`]]
]
[heading Expression requirements]
@@ -145,31 +243,116 @@
the following expressions are valid:
[table
- [[Expression] [Return type] [Runtime Complexity]]
- [[`b = act.joinable()`] [bool] [Constant]]
- [[`act.join()`] [void] [Constant]]
- [[`b = act.join_until(abs_time)`] [bool] [Constant]]
- [[`b = act.join_for(rel_time)`] [bool] [Constant]]
- [[`act.detach()`] [void] [Constant]]
- [[`act.interrupt()`] [void] [Constant]]
- [[`b = act.interruption_requested()`] [bool] [Constant]]
+ [[Expression] [Return type] [Runtime Complexity]]
+ [[`b = joinable(cact)`] [bool] [Constant]]
+ [[`join(act)`] [void] [Constant]]
+ [[`b = join_until(act, abs_time)`] [bool] [Constant]]
+ [[`b = join_for(act, rel_time)`] [bool] [Constant]]
+ [[`detach(act)`] [void] [Constant]]
+ [[`interrupt(act)`] [void] [Constant]]
+ [[`b = interruption_requested(cact)`] [bool] [Constant]]
+ [[`id = get_id(cact)`] [`act_traits<__ACT__>::id_type`] [Constant]]
]
[heading Expression Semantics]
[table
- [[Expression] [Semantics]]
- [[`b = act.joinable()`] [true if *this refers to a thread of execution, false otherwise]]
- [[`act.join()`] [waits for the assoiated thread of execution to complete]]
- [[`b = act.join_until(abs_time)`] [waits for the assoiated thread of execution to complete or the time wait_until has been reach.]]
- [[`b = act.join_for(rel_time)`] [waits for the assoiated thread of execution to complete or the specified duration rel_time has elapsed ]]
- [[`act.detach()`] [the associated thread of execution becomes detached, and no longer has an associated one]]
- [[`act.interrupt()`] [request that the associated thread of execution be interrupted the next time it enters
+ [[Expression] [Semantics]]
+ [[`b = joinable(cact)`] [true if `cact` refers to a 'thread of execution', false otherwise]]
+ [[`join(act)`] [waits for the assoiated 'thread of execution' to complete]]
+ [[`b = join_until(act, abs_time)`] [waits for the assoiated 'thread of execution' to complete or the time `wait_until` has been reach.]]
+ [[`b = join_for(act, rel_time)`] [waits for the assoiated 'thread of execution' to complete or the specified duration `rel_time` has elapsed ]]
+ [[`detach(act)`] [the associated 'thread of execution' becomes detached, and no longer has an associated one]]
+ [[`interrupt(act)`] [request that the associated 'thread of execution' be interrupted the next time it enters
one of the predefined interruption points with interruption enabled, or if it is currently blocked in a call to one of the
predefined interruption points with interruption enabled]]
- [[`b = act.interruption_requested()`] [true if interruption has been requested for the associated thread of execution, false otherwise. ]]
- [[`is = act.get_id()`] [an instance of boost::thread::id that represents the associated thread of execution.]]
+ [[`b = interruption_requested(cact)`] [true if interruption has been requested for the associated 'thread of execution', false otherwise. ]]
+ [[`id = get_id(cact)`] [an instance of `act_traits<__ACT__>::id_type` that represents the associated 'thread of execution'.]]
+]
+
+[heading Expresion `b=joinable(act)`]
+[/==========================================================================================]
+
+[variablelist
+[[Returns:] [true if `act` refers to a 'thread of execution', false otherwise]]
+[[Throws:] [Nothing]]
+]
+
+
+[heading Expresion `join()`]
+[/==========================================================================================]
+
+[variablelist
+[[Preconditions:] [`get_id(act)!=boost::interthreads::get_current_id<ACT>()`]]
+[[Effects:] [If `act` refers to a thread of execution, waits for that 'thread of execution' to complete.]]
+[[Postconditions:] [If `act` refers to a 'thread of execution' on entry, that 'thread of execution' has completed.
+`act` no longer refers to any 'thread of execution'.]]
+[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]
+[[Notes:] [`join()` is one of the predefined __interruption_points__.]]
+]
+
+[heading Expresion `b=join_until(act)|b=join_for(act)`]
+[/==========================================================================================]
+
+ bool join_until(const system_time& wait_until);
+
+ template<typename TimeDuration>
+ bool join_for(TimeDuration const& rel_time);
+
+[variablelist
+[[Preconditions:] [`get_id(act)!=boost::interthreads::get_current_id<ACT>()`]]
+[[Effects:] [If `act` refers to a 'thread of execution', waits for that thread of execution to complete, the time `wait_until` has
+been reach or the specified duration `rel_time` has elapsed. If `act` doesn't refer to a 'thread of execution', returns immediately.]]
+[[Returns:] [`true` if `act` refers to a thread of execution on entry, and that thread of execution has completed before the call
+times out, `false` otherwise.]]
+[[Postconditions:] [If `act` refers to a thread of execution on entry, and `timed_join` returns `true`, that thread of execution
+has completed, and `act` no longer refers to any thread of execution. If this call to `timed_join` returns `false`, `*this` is
+unchanged.]]
+[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]
+[[Notes:] [`join_until()` is one of the predefined __interruption_points__.]]
+]
+
+[heading Expresion `detach(act)`]
+[/==========================================================================================]
+
+[variablelist
+[[Effects:] [If `act` refers to a 'thread of execution', that 'thread of execution' becomes detached, and no longer has an associated thread object.]]
+[[Postconditions:] [`act` no longer refers to any 'thread of execution'.]]
+[[Throws:] [Nothing]]
]
+[heading Expresion `get_id(cact)`]
+[/==========================================================================================]
+
+
+[variablelist
+[[Returns:] [If `act` refers to a 'thread of execution', an instance of `act_traits<__ACT__>::id_type` that represents that __ACT__.
+Otherwise returns a default-constructed `act_traits<__ACT__>::id_type`.]]
+[[Throws:] [Nothing]]
+]
+
+[heading Expresion `interrupt(act)`]
+[/==========================================================================================]
+
+
+[variablelist
+[[Effects:] [If `act` refers to a 'thread of execution', request that the 'thread of execution' will be interrupted the next time it enters one of
+the predefined __interruption_points__ with interruption enabled, or if it is currently __blocked__ in a call to one of the
+predefined __interruption_points__ with interruption enabled .]]
+[[Throws:] [Nothing]]
+]
+
+[heading Expresion `h = native_handle(act)`]
+[/==========================================================================================]
+
+
+[variablelist
+[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
+implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
+[[Throws:] [Nothing.]]
+]
+
+
+
[heading Models]
* __unique_joiner__
@@ -286,6 +469,7 @@
* __scheduler__
+
[endsect]
[endsect]
Modified: sandbox/interthreads/libs/interthreads/doc/getting_started.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/getting_started.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/getting_started.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,6 +1,6 @@
[/
[/
- (C) Copyright 2008-20009 Vicente J. Botet Escriba
+ (C) Copyright 2008-2009 Vicente J. Botet Escriba
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).
@@ -22,7 +22,7 @@
#include <boost/interthreads/thread_decorator.hpp>
#include <boost/thread.hpp>
#include <iostream>
-
+
namespace bith = boost::interthreads;
void my_setup() {
@@ -38,7 +38,7 @@
void my_thread() {
std::cout << "..." << std::endl;
}
-
+
int main() {
boost::thread th(bith::make_decorator(my_thread));
th.join();
@@ -46,8 +46,8 @@
}
When `th` is created with the `bith::thread_decorator` wrapper, it will initialize all the decorations before calling `my_thread`.
-This `my_cleanup` will be registered with the `boost:this_thread::at_thread_exit` if the `my_setup` function succeeds i.e. do not throws.
-Then the thread function `my_thread` is called. At the thread exit, the `my_cleanup` function is called. This results on the following output
+This `my_cleanup` will be registered with the `boost:this_thread::at_thread_exit` if the `my_setup` function succeeds i.e. do not throws.
+Then the thread function `my_thread` is called. At the thread exit, the `my_cleanup` function is called. This results on the following output
[pre
Hello World!
@@ -55,34 +55,43 @@
Bye, Bye!
]
+[/
int main() {
bith::wait_for_all(basic_threader_decorator, my_thread);
return 0;
}
+]
+
[endsect]
[/==========================]
[section Monotonic Thread Id]
[/==========================]
-This example use thread decorator and threas specific pointers to implement a monotonic thread identifier.
+This example use thread decorator and thread specific pointers to implement a monotonic thread identifier.
+
+The monotonic thread identifier is managed by the mono_thread_id class.
+There is a mutex protecting the access to the monotonic counter.
+The main difference between a thread_specific_shared_ptr and thread_specific_ptr is that we can get the specific pointer of another thread (*)
+Whith the help of bith::thread_decoration the setting of the thread specific shared pointer is done transparently as far as the thread
+is created using a thread decorator. This setup function reset the specific pointer with the value of the monotonic counter which will be self increased.
#include <boost/interthreads/thread_decorator.hpp>
#include <boost/interthreads/thread_specific_shared_ptr.hpp>
#include <boost/thread.hpp>
#include <iostream>
-
+
namespace bith = boost::interthreads;
class mono_thread_id {
static bith::thread_decoration decoration_;
typedef bith::thread_specific_shared_ptr<unsigned> tssp_type;
static tssp_type current_;
- static unsigned counter_=0;
+ static unsigned counter_;
static boost::mutex sync_;
-
+
static unsigned create() {
boost::lock_guard<boost::mutex> lock(sync_);
unsigned res = counter_;
@@ -92,12 +101,12 @@
static void setup() {
current_.reset(new unsigned(create());
}
- public:
+ public:
static unsigned id() {
return *current_;
}
static unsigned id(boost::thread::id id) {
- return *current_[id]
+ return *current_[id]; // (*)
}
};
@@ -106,62 +115,41 @@
mono_thread_id::tssp_type mono_thread_id::current_;
unsigned mono_thread_id::counter_=0;
boost::mutex mono_thread_id::sync_;
-
-
-The monotonic thread identifier is managed by the mono_thread_id class.
-There is a mutex protecting the access to the monotonic counter.
-A decoration for the setup function will set the thread specific shared pointer with the value of the monotonic counter which
-will be self increased.
-In this way the applications using the thread_decorator can have access to a monotonic thread id mono_thread_id::id()
+In this way the applications using the thread_decorator can have access to a monotonic thread id mono_thread_id::id()
and this id is accesible to other threads providing the boost::thread::id.
void my_thread() {
std::cout << "mono_thread_id=" << mono_thread_id::id() << std::endl;
sleep(5);
}
-
- int main() {
- boost::thread th1(bith::make_decorator(my_thread));
- boost::thread th2(bith::make_decorator(my_thread));
- sleep(2);
-
- std::cout << "thread::id=" << th1.get_id()
- << " mono_thread_id=" << mono_thread_id::id(th1.get_id())
- << std::endl;
- th1.join();
- th2.join();
- return 0;
- }
-
-This results on the following output
-
-[pre
-mono_thread_id=1
-mono_thread_id=2
-thread::id=xxxx mono_thread_id=1
-thread::id=xxxx mono_thread_id=2
-
-]
struct mono_thread_id_out {
template<typename T>
void operator()(T& t) const {
- std::cout << "thread::id=" << t.get_id()
- << " mono_thread_id=" << mono_thread_id::id(t.get_id())
+ std::cout << "thread::id=" << t.get_id()
+ << " mono_thread_id=" << mono_thread_id::id(t.get_id())
<< std::endl;
}
};
int main() {
- bith::result_of::fork_all<basic_threader_decorator, my_thread, my_thread> handles =
- bith::fork_all(basic_threader_decorator, my_thread, my_thread);
- sleep(2);
+ bith::shared_threader_decorator ae;
+ BOOST_AUTO(handles, bith::fork_all(basic_threader_decorator, my_thread, my_thread));
boost::fusion::for_each(handles, mono_thread_id_out());
bith.join_all();
return 0;
}
+This results on the following output
+
+[pre
+mono_thread_id=1
+mono_thread_id=2
+thread::id=xxxx mono_thread_id=1
+thread::id=xxxx mono_thread_id=2
+
+]
[endsect]
@@ -175,38 +163,29 @@
#include <boost/interthreads/keep_alive.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
-
+
namespace bith = boost::interthreads;
void my_thread() {
bith::this_thread::enable_keep_alive enabler;
for (int i=0; i<5; i++) {
- bith::this_thread::keep_alive_point();
+ bith::this_thread::keep_alive_point();
std::cout << "thread_id=" << boost::this_thread::get_id() << std::endl;
sleep(1);
}
}
-
- int main() {
- bith::shared_threader_decorator ae;
- bith::wait_for_all(ae, my_thread, my_thread);
- return 0;
- }
int main() {
- boost::thread th1(bith::make_decorator(my_thread));
- boost::thread th2(bith::make_decorator(my_thread));
- sleep(2);
+ bith::shared_threader_decorator ae;
+ bith::wait_for_all(ae, my_thread, my_thread, my_thread, my_thread);
- th1.join();
- th2.join();
return 0;
}
-The user creates two threads using the thread_decorator wrapper to be able to use the keep_alive mechanism.
-It uses the default enabler (one keep_alive_point every 2 seconds)
+The user creates 4 threads using the shared_threader_decorator __AE__ to be able to use the keep_alive mechanism.
+It uses the default enabler (one keep_alive_point every 2 seconds).
-This results on the following output
+This results on the following output
[pre
]
@@ -223,29 +202,39 @@
#include <boost/interthreads/typeof/threader.hpp>
#include <boost/interthreads/wait_for_any.hpp>
#include <iostream>
-
+
namespace bith = boost::interthreads;
- void my_thread1() {
+ int my_thread1() {
+ sleep(3);
std::cout << "1 thread_id=" << boost::this_thread::get_id() << std::endl;
- sleep(1);
}
-
- void my_thread2() {
+
+ int my_thread2() {
+ sleep(1);
std::cout << "2 thread_id=" << boost::this_thread::get_id() << std::endl;
- sleep(5);
+ }
+
+ int my_thread3() {
+ sleep(2);
+ std::cout << "3 thread_id=" << boost::this_thread::get_id() << std::endl;
}
int main() {
bith::shared_threader ae;
- BOOST_AUTO(res,bith::wait_for_any(ae, my_thread, my_thread));
- std::cout << "Algotithm " << res.first+1 << " finished the first" << std::endl;
+ BOOST_AUTO(res,bith::wait_for_any(ae, my_thread1, my_thread2, my_thread3));
+ std::cout << "Algotithm " << result.first+1 << " finished the first. result=" << result.second << std::endl;
return 0;
}
-This results on the following output
+This results on the following output
[pre
+3 thread_id=0x9c03f8
+2 thread_id=0x9c0850
+1 thread_id=0x9d0c40
+Algotithm 2 finished the first. result=0
+
]
Modified: sandbox/interthreads/libs/interthreads/doc/implementation.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/implementation.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/implementation.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -26,29 +26,29 @@
[variablelist
[[External versus internal thread storage] [The thread specific data collections can be stored either externally
-to all threads or internally to each thread. The thread_specific_shared_ptr use both ensuring efficiency when the context is
+to all threads or internally to each thread. The thread_specific_shared_ptr use both ensuring efficiency when the context is
requested by the current thread and allowing threads to access thread specific pointer of other threads]]
-[[Fixed- vs. variable-sized thread specific key mapping]
-[This library is based on the the Boost.Thread thread_specific_ptr implementation which use a variable-size map indexed by the
+[[Fixed- vs. variable-sized thread specific key mapping]
+[This library is based on the the Boost.Thread thread_specific_ptr implementation which use a variable-size map indexed by the
address of the object. Future releases will provide fixed and mixed keys.]]
-[[Fixed- vs. variable-sized mapping of thread IDs to thread specific pointers]
-[It may be impractical to have a fixed-size array with an entry for every possible thread ID value.
+[[Fixed- vs. variable-sized mapping of thread IDs to thread specific pointers]
+[It may be impractical to have a fixed-size array with an entry for every possible thread ID value.
Instead, it is more space efficient to have threads use a dynamic data structure to map thread IDs to thread specific pointers.]]
-[[One mapping of thread IDs to thread specific pointers or to thread specific key mapping]
+[[One mapping of thread IDs to thread specific pointers or to thread specific key mapping]
[This library maps thread IDs to thread specific pointers to avoid contention on a single map.]]
-[[Default versus explicit specific context setting]
+[[Default versus explicit specific context setting]
[This library provides explicit setting. In future release will provide explicit/eager and implicit/lazy specific context setting.]]
[[Ordered or unordered map] [The current implementation use an ordered map. Future version will allow the user to configure this.]]
[[Intrusive or not maps] [As the thread specific pointer is stored on only one map the current implementation use the intrusive container.]]
-[[Shared versus exclusive locking] [Locating the right TS pointer requires the use of mutex to prevent race conditions. The library use a a shared_mutex
-because most of the access to the map will be readings by other threads. The problem is that the native conditions can not be used directly with
+[[Shared versus exclusive locking] [Locating the right TS pointer requires the use of mutex to prevent race conditions. The library use a a shared_mutex
+because most of the access to the map will be readings by other threads. The problem is that the native conditions can not be used directly with
shared mutex. Some benchmarks will be needed before decidinf which implementation is the best.]]
]
@@ -59,11 +59,11 @@
[variablelist
-[[Ensuring keep alive manager singleton is initialized and the thread specific shared storage is set before use]
-[The use of the thread preamble ensures that the preables are called before the user thread function is called.
+[[Ensuring keep alive manager singleton is initialized and the thread specific shared storage is set before use]
+[The use of the thread preamble ensures that the preables are called before the user thread function is called.
The keep_alive preable use the call_once to ensure that the keep_alive manager is correctly initialized.]]
-[[backup/restore context] [The real thread specific data is stored directly on the stack of enablers/disablers avoiding heap memory.
+[[backup/restore context] [The real thread specific data is stored directly on the stack of enablers/disablers avoiding heap memory.
On enablers/disablers construction they store a backup pointer to the nesting context. This allows a quick restore.
The keep alive pointer contains just a pointer to this data.]]
@@ -74,8 +74,8 @@
[section Thread Tuple]
[variablelist
-[[Joining the first finishing thread]
-[In order to synchronize the finish of all the threads we use a internal class which store the index of the first
+[[Joining the first finishing thread]
+[In order to synchronize the finish of all the threads we use a internal class which store the index of the first
thread notifying that it is finished. As the user function has no ideaof this index we wrap the user thread functions.
]]
]
Modified: sandbox/interthreads/libs/interthreads/doc/installation.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/installation.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/installation.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J. Botet Escriba
+ (C) Copyright 2008-2009 Vicente J. Botet Escriba
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).
@@ -23,14 +23,17 @@
[heading Building Boost.InterThreads]
[/==================================]
-__Boost_InterThreads__ is not a header only library. There is a need to compile it before use.
+__Boost_InterThreads__ is not a header only library. You need to compile it before use.
+
+ cd libs/interthreads/build
+ bjam
[/=========================]
[heading Build Requirements]
[/=========================]
-[*Boost.InterThreads] depends on Boost. You must use either Boost version 1.37.x
+[*Boost.InterThreads] depends on Boost. You must use either Boost version 1.37.x
or the version in SVN trunk. In particular, __Boost_InterThreads__ depends on:
[variablelist
@@ -59,7 +62,7 @@
[[@http://www.boost.org/libs/smart_ptr [*Boost.SmartPtr]]] [for shared_ptr, ...]
]
[
- [[@http://www.boost.org/libs/thread [*Boost.Threads]]] [for thread, thread_specific_ptr, call_once, mutex, ...]
+ [[@http://www.boost.org/libs/thread [*Boost.Threads]]] [for thread, thread_specific_ptr, call_once, mutex, condition_variable, ...]
]
[
[[@http://www.boost.org/libs/typeof [*Boost.TypeOf]]] [to register the ACT types.]
@@ -72,35 +75,42 @@
]
]
-In addition it depends on the following libraries that are not accepted yet on Boost
+In addition it depends on the following libraries that are not yet accepted on Boost
[variablelist
[
- [[@http://www.boost.org/libs/chrono [*Boost.Chrono]]] [for time and duration]
+ [[@http://www.boost.org/libs/futures [*Boost.Futures]]] [for futures]
]
[
- [[@http://www.boost.org/libs/futures [*Boost.Futures]]] [for futures]
+ [[@http://www.boost.org/libs/tp [*Boost.ThreadPool]]] [Only when using the __AE_ boost::tp::pool and the __ACT__ boost::tp::task]
+]
+]
+
+And also could depend conditionaly on the following libraries that even not submited on Boost.
+[variablelist
+[
+ [[@http://www.boost.org/libs/chrono [*Boost.Chrono]]] [for time and duration]
]
[
[[@http://www.boost.org/libs/move [*Boost.Move]]] [to emulate the move semantic.]
]
[
- [[@http://www.boost.org/libs/tp [*Boost.ThreadPool]]] [for pool and task, whne you use the scheduler class]
+ [[@https://svn.boost.org/trac/boost/wiki/LibrariesUnderConstruction#Boost.SmartPtr.UniquePtr [*Boost.SmartPtr.UniquePtr]]] [for unique_ptr, ...]
]
+
]
[/========================]
[heading Exceptions safety]
[/========================]
-All functions in the library are exception-neutral and provide strong guarantee of exception safety as long as
-the underlying parameters provide it.
+All functions in the library are exception-neutral and provide strong guarantee of exception safety as long as
+the underlying parameters provide it.
[/====================]
[heading Thread safety]
[/====================]
-All functions in the library are exception-safe except:
-To be completed:
+All functions in the library are thread-unsafe except when notes explicitly.
[/=======================]
[heading Tested compilers]
Modified: sandbox/interthreads/libs/interthreads/doc/interthreads.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/interthreads.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/interthreads.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,6 +1,6 @@
+
[/
-[/
- (C) Copyright 2008-20009 Vicente J. Botet Escriba
+ (C) Copyright 2008-2009 Vicente J. Botet Escriba
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).
@@ -9,9 +9,9 @@
[article InterThreads
[quickbook 1.4]
[authors [Botet Escriba, Vicente J.]]
- [copyright 2008-20009 Vicente J. Botet Escriba]
- [purpose C++ Library extending the Boost.Thread library adding some inter threads mechanisms as
- asynchronous executors and asyncronous completion tokes framework with threaders/joiners, launcher.
+ [copyright 2008-2009 Vicente J. Botet Escriba]
+ [purpose C++ Library extending the Boost.Thread library adding some inter threads mechanisms as
+ asynchronous executors and asyncronous completion tokes framework with threaders/joiners, launcher.
thread decorator, specific shared pointers and keep alive mechanism]
[category text]
[license
@@ -21,149 +21,41 @@
]
]
-[template lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.lockable [link_text]]]
-[def __lockable_concept__ [lockable_concept_link `Lockable` concept]]
-[def __lockable_concept_type__ [lockable_concept_link `Lockable`]]
-
-[template timed_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable [link_text]]]
-[def __timed_lockable_concept__ [timed_lockable_concept_link `TimedLockable` concept]]
-[def __timed_lockable_concept_type__ [timed_lockable_concept_link `TimedLockable`]]
-
-[template shared_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable [link_text]]]
-[def __shared_lockable_concept__ [shared_lockable_concept_link `SharedLockable` concept]]
-[def __shared_lockable_concept_type__ [shared_lockable_concept_link `SharedLockable`]]
-
-[template upgrade_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable [link_text]]]
-[def __upgrade_lockable_concept__ [upgrade_lockable_concept_link `UpgradeLockable` concept]]
-[def __upgrade_lockable_concept_type__ [upgrade_lockable_concept_link `UpgradeLockable`]]
-
-
-[template lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.lock [link_text]]]
-[def __lock_ref__ [lock_ref_link `lock()`]]
-
-[template lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.lock_multiple [link_text]]]
-[def __lock_multiple_ref__ [lock_multiple_ref_link `lock()`]]
-
-[template try_lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.try_lock_multiple [link_text]]]
-[def __try_lock_multiple_ref__ [try_lock_multiple_ref_link `try_lock()`]]
-
-[template unlock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.unlock [link_text]]]
-[def __unlock_ref__ [unlock_ref_link `unlock()`]]
-
-[template try_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.try_lock [link_text]]]
-[def __try_lock_ref__ [try_lock_ref_link `try_lock()`]]
-
-[template timed_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock [link_text]]]
-[def __timed_lock_ref__ [timed_lock_ref_link `timed_lock()`]]
-
-[template timed_lock_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock_duration [link_text]]]
-[def __timed_lock_duration_ref__ [timed_lock_duration_ref_link `timed_lock()`]]
-
-[template lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.lock_shared [link_text]]]
-[def __lock_shared_ref__ [lock_shared_ref_link `lock_shared()`]]
-
-[template unlock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.unlock_shared [link_text]]]
-[def __unlock_shared_ref__ [unlock_shared_ref_link `unlock_shared()`]]
-
-[template try_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared [link_text]]]
-[def __try_lock_shared_ref__ [try_lock_shared_ref_link `try_lock_shared()`]]
-
-[template timed_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared [link_text]]]
-[def __timed_lock_shared_ref__ [timed_lock_shared_ref_link `timed_lock_shared()`]]
-
-[template timed_lock_shared_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared_duration [link_text]]]
-[def __timed_lock_shared_duration_ref__ [timed_lock_shared_duration_ref_link `timed_lock_shared()`]]
-
-[template lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.lock_upgrade [link_text]]]
-[def __lock_upgrade_ref__ [lock_upgrade_ref_link `lock_upgrade()`]]
-
-[template unlock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade [link_text]]]
-[def __unlock_upgrade_ref__ [unlock_upgrade_ref_link `unlock_upgrade()`]]
-
-[template unlock_upgrade_and_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock [link_text]]]
-[def __unlock_upgrade_and_lock_ref__ [unlock_upgrade_and_lock_ref_link `unlock_upgrade_and_lock()`]]
-
-[template unlock_and_lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_upgrade [link_text]]]
-[def __unlock_and_lock_upgrade_ref__ [unlock_and_lock_upgrade_ref_link `unlock_and_lock_upgrade()`]]
-
-[template unlock_upgrade_and_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock_shared [link_text]]]
-[def __unlock_upgrade_and_lock_shared_ref__ [unlock_upgrade_and_lock_shared_ref_link `unlock_upgrade_and_lock_shared()`]]
-
-[template owns_lock_ref_link[link_text] [link thread.synchronization.locks.unique_lock.owns_lock [link_text]]]
-[def __owns_lock_ref__ [owns_lock_ref_link `owns_lock()`]]
-
-[template owns_lock_shared_ref_link[link_text] [link thread.synchronization.locks.shared_lock.owns_lock [link_text]]]
-[def __owns_lock_shared_ref__ [owns_lock_shared_ref_link `owns_lock()`]]
-
-[template mutex_func_ref_link[link_text] [link thread.synchronization.locks.unique_lock.mutex [link_text]]]
-[def __mutex_func_ref__ [mutex_func_ref_link `mutex()`]]
[def __boost_thread__ [@http://www.boost.org/libs/thread [*Boost.Threads]]]
[def __boost_interthreads__ [*Boost.InterThreads]]
[def __Boost_InterThreads__ [*Boost.InterThreads]]
[def __not_a_thread__ ['Not-a-Thread]]
-[def __interruption_points__ [link interruption_points ['interruption points]]]
-
-[def __mutex__ [link thread.synchronization.mutex_types.mutex `boost::mutex`]]
-[def __try_mutex__ [link thread.synchronization.mutex_types.try_mutex `boost::try_mutex`]]
-[def __timed_mutex__ [link thread.synchronization.mutex_types.timed_mutex `boost::timed_mutex`]]
-[def __recursive_mutex__ [link thread.synchronization.mutex_types.recursive_mutex `boost::recursive_mutex`]]
-[def __recursive_try_mutex__ [link thread.synchronization.mutex_types.recursive_try_mutex `boost::recursive_try_mutex`]]
-[def __recursive_timed_mutex__ [link thread.synchronization.mutex_types.recursive_timed_mutex `boost::recursive_timed_mutex`]]
-[def __shared_mutex__ [link thread.shronization.mutex_types.shared_mutex `boost::shared_mutex`]]
-
-[template unique_lock_link[link_text] [link thread.synchronization.locks.unique_lock [link_text]]]
-
-[def __lock_guard__ [link thread.synchronization.locks.lock_guard `boost::lock_guard`]]
-[def __unique_lock__ [unique_lock_link `boost::unique_lock`]]
-[def __shared_lock__ [link thread.synchronization.locks.shared_lock `boost::shared_lock`]]
-[def __upgrade_lock__ [link thread.synchronization.locks.upgrade_lock `boost::upgrade_lock`]]
-[def __upgrade_to_unique_lock__ [link thread.synchronization.locks.upgrade_to_unique_lock `boost::upgrade_to_unique_lock`]]
-
+[def __interruption_points__ ['interruption points]]
[def __thread__ `boost::thread`]
[def __thread_id__ `boost::thread::id`]
[template join_link[link_text] [link interthreads.reference.thread_tuple_thread_tuple_hpp.thread_tuple_join_all [link_text]]]
-[def __join__ [join_link `join()`]]
+[def __join__ `join()`]
[template timed_join_link[link_text] [link interthreads.reference.thread_tuple_thread_tuple_hpp.thread_tuple_timed_join_all [link_text]]]
-[def __timed_join__ [timed_join_link `timed_join()`]]
-[def __detach__ [link thread.thread_management.thread.detach `detach()`]]
-[def __interrupt__ [link interthreads.reference.thread_tuple_thread_tuple_hpp.thread_tuple_class.thread_tuple_interrupt_all `interrupt_all()`]]
+[def __timed_join__ `timed_join()`]
+[def __detach__ `detach()`]
+[def __interrupt__ `interrupt_all()`]
+[def __sleep__ `boost::this_thread::sleep()`]
-[def __sleep__ [link thread.thread_management.this_thread.sleep `boost::this_thread::sleep()`]]
-
-[def __interruption_enabled__ [link thread.thread_management.this_thread.interruption_enabled `boost::this_thread::interruption_enabled()`]]
-[def __interruption_requested__ [link interthreads.thread_tuple.reference.thread_tuple_class.thread_tuple_join.interruption_requested `boost::this_thread::interruption_requested()`]]
-[def __interruption_point__ [link thread.thread_management.this_thread.interruption_point `boost::this_thread::interruption_point()`]]
-[def __disable_interruption__ [link thread.thread_management.this_thread.disable_interruption `boost::this_thread::disable_interruption`]]
-[def __restore_interruption__ [link thread.thread_management.this_thread.restore_interruption `boost::this_thread::restore_interruption`]]
[def __thread_resource_error__ `boost::thread_resource_error`]
[def __thread_interrupted__ `boost::thread_interrupted`]
-[def __barrier__ [link thread.synchronization.barriers.barrier `boost::barrier`]]
-
-[template cond_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable.wait [link_text]]]
-[def __cond_wait__ [cond_wait_link `wait()`]]
-[template cond_timed_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable.timed_wait [link_text]]]
-[def __cond_timed_wait__ [cond_timed_wait_link `timed_wait()`]]
-[template cond_any_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable_any.wait [link_text]]]
-[def __cond_any_wait__ [cond_any_wait_link `wait()`]]
-[template cond_any_timed_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable_any.timed_wait [link_text]]]
-[def __cond_any_timed_wait__ [cond_any_timed_wait_link `timed_wait()`]]
+[def __barrier__ `boost::barrier`]
[template thread_decorator_link[link_text] [link interthreads.reference.decorator_thread_decoration_file.thread_decorator [link_text]]]
-[def __thread_decorator__ [thread_decorator_link `thread_decorator`]]
+[def __thread_decorator__ `thread_decorator`]
[template thread_decoration_link[link_text] [link interthreads.reference.decorator_thread_decoration_file.decorator_thread_decoration_class [link_text]]]
-[def __thread_decoration__ [thread_decorator_link `thread_decoration`]]
+[def __thread_decoration__ `thread_decoration`]
[template thread_decorate_link[link_text] [link interthreads.reference.decorator_thread_decoration_file.decorate [link_text]]]
-[def __thread_decorator_decorate__ [thread_decorate_link `decorate()`]]
+[def __thread_decorator_decorate__ `decorate()`]
[def __blocked__ ['blocked]]
@@ -179,15 +71,56 @@
[def __ACT__ `AsynchronousCompletionToken`]
[def __FutureBasedACT__ `FutureBasedACT`]
-[def __Future__ `inherits from unique_future|shared_future`]
+[def __ThreadBasedACT__ `ThreadBasedACT`]
+
+[def __Future__ inherits from `unique_future|shared_future`]
[def __Nullary__ `Nullary`]
[def __Movable__ `Movable`]
[def __CopyConstructible__ `CopyConstructible`]
-[def __system_time__ `system_time`]
+[def __system_time__ `system_time`]
[def __Duration__ `DurationType`]
-[def __fork__ `fork`]
+[def __partial_specialization_workaround__ `partial_specialization_workaround`]
+
+[template fork_link[link_text] [link interthreads.reference.ae_act_framework_reference.ae_operations.fork_hpp.non_member_function [link_text]]]
+
+[def __forkss__ [link interthreads.reference.ae_act_framework_reference.ae_operations.fork_hpp.non_member_function `fork`]
+[def __fork__ [fork_link `fork`]]
+[def __fork_after__ `fork_after`]
+
+[def __get__ `get`]
+[def __wait__ `wait`]
+[def __wait_until__ `wait_until`]
+[def __wait_for__ `wait_for`]
+[def __is_ready__ `is_ready`]
+[def __has_value__ `has_value`]
+[def __has_exception__ `has_exception`]
+
+
+[def __get_all__ `get_all`]
+[def __wait_all__ `wait_all`]
+[def __wait_all_until__ `wait_all_until`]
+[def __wait_all_for__ `wait_all_for`]
+[def __are_all_ready__ `are_all_ready`]
+[def __have_all_value__ `have_all_value`]
+[def __have_all_exception__ `have_all_exception`]
+
+[def __detach__ `detach`]
+[def __interrupt__ `interrupt`]
+[def __interruption_requested__ `interruption_requested`]
+[def __join__ `join`]
+[def __join_until__ `join_until`]
+[def __join_for__ `join_for`]
+[def __joinable__ `joinable`]
+
+[def __detach_all__ `detach_all`]
+[def __interrupt_all__ `interrupt_all`]
+[def __interruption_requested_on_all__ `interruption_requested_on_all`]
+[def __join_all__ `join_all`]
+[def __join_all_until__ `join_all_until`]
+[def __join_for__ `join_all_for`]
+[def __are_all_joinable__ `are_all_joinable`]
[def __unique_threader__ `unique_threader`]
[def __shared_threader__ `shared_threader`]
@@ -204,21 +137,26 @@
[def __shared_launcher__ `shared_launcher`]
[def __scheduler__ `scheduler`]
+[def __asynchronous_executor_decorator__ `asynchronous_executor_decorator`]
+
[def __tp_task__ `tp::task`]
[def __tp_pool__ `tp::pool`]
-[def __handle__ `tp::task`]
-
+[def __handle__ `handle`]
+[def __decorate__ `bith::decorate`]
+[def __apply__ `apply`]
[warning InterThreads is not a part of the Boost libraries.]
+
[include overview.qbk]
[include users_guide.qbk]
-[include concepts.qbk]
+[/include concepts.qbk]
+
[include reference.qbk]
[include case_studies.qbk]
Modified: sandbox/interthreads/libs/interthreads/doc/introduction.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/introduction.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/introduction.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -14,84 +14,83 @@
[/=======================================================================]
In [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1883.pdf N1833 - Preliminary Threading Library Proposal for TR2]
-Kevlin Henney introduce the concept of threader an asynchronous executor and a function thread that evaluate a function
-asynchronously and returns an asynchronous completion token joiner, able to join but also to to get the value of the function result.
+Kevlin Henney introduce the concept of `threader` an asynchronous executor and a function `thread()` that evaluate a function
+asynchronously and returns an asynchronous completion token `joiner`, able to join but also to to get the value of the function result.
+
+In [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2185.html N2185 - Proposed Text for Parallel Task Execution]
+Peter Dimov introduce a `fork()` function able to evaluate a function asynchronously and returns a `future` handle.
-In [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2185.html N2185 - Proposed Text for Parallel Task Execution]
-Peter Dimov introduce a fork function able to evaluate a function asynchronously and
-returns a future handle.
-
-In [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2276.html N2276 - Thread Pools and Futures]
-Anthony William introduce launch_in_thread and launch_in_pool function templates which
-evaluate a function asynchronously either in a specific thread or a thread pool and
-returns a unique_future handle.
-
-In [@http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-threadpool.3.tar.gz&directory=Concurrent%20Programming& Boost.ThreadPool]
-Oliver Kowalke propose a complete implementation of a thread pool with a submit function
-which evaluate a function asynchronously and returns a task handle.
+In [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2276.html N2276 - Thread Pools and Futures]
+Anthony William introduce `launch_in_thread` and `launch_in_pool` function templates which
+evaluate a function asynchronously either in a specific `thread` or a thread pool and
+returns a `unique_future` handle.
+
+In [@http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-threadpool.3.tar.gz&directory=Concurrent%20Programming& Boost.ThreadPool]
+Oliver Kowalke propose a complete implementation of a thread `pool` with a `submit()` function
+which evaluate a function asynchronously and returns a `task` handle.
-Behind all these proposal there is a concept of asynchronous executor, fork-like function and
+Behind all these proposal there is a concept of asynchronous executor, fork-like function and
the asynchronous completion token handle.
[table fork Parameters
[
- [[*Proposal]] [[*executor]] [[*fork-like]] [[*ACT handle]]
+ [[*Proposal]] [[*executor]] [[*fork-like]] [[*ACT handle]]
]
[
- [Boost.Thread] [??] [thread constructor] [thread]
+ [Boost.Thread] [`thread` class] [`thread()` constructor] [__thread__]
]
[
- [Boost.ThreadPool] [tp::pool] [submit] [tp::task]
+ [Boost.ThreadPool] [__tp_pool__] [`submit()`] [__tp_task__]
]
[
- [N2276] [thread] [launch_in_thread] [unique_future<T>]
+ [N2276] [__thread__] [`launch_in_thread()`] [`unique_future<T>`]
]
[
- [N2276] [thread_pool] [launch_in_pool] [unique_future<T>]
+ [N2276] [thread_pool] [`launch_in_pool()`] [`unique_future<T>`]
]
[
- [N2185] [??] [fork] [future<T>]
+ [N2185] [thread pool] [`fork()`] [`future<T>`]
]
[
- [N1833] [threader] [thread] [joiner<T>]
+ [N1833] [`threader`] [`thread()`] [`joiner<T>`]
]
]
-The asynchronous completion token models can follows two interfaces, the thread interface and
-the unique_future interface. Some asynchronous completion token handle allows to recover the result of the evaluation of
-the function, other allows to manage the underlying thread of execution.
+The asynchronous completion token models can follows two interfaces, the thread interface and
+the unique_future interface. Some asynchronous completion token handle allows to recover the result of the evaluation of
+the function, other allows to manage the underlying thread of execution.
-It seems natural to make a generic fork function that will evaluate a function asynchronously
-with respect to the calling thread and returns an ACT handle. The following metafunction
+It seems natural to make a generic __fork__ function that will evaluate a function asynchronously
+with respect to the calling thread and returns an ACT handle. The following metafunction
associated an ACT handle to a asynchronous executor.
template <typename AE, typename T>
struct asynchronous_completion_token {
typedef typename AE::template handle<T>::type type;
- };
+ };
The result of forking a nullary function by an asynchronous executor is given by the metafunction result_of::fork<AE,F>
- namespace result_of {
+ namespace result_of {
template <typename AE,typename F>
- struct fork {
+ struct __c_fork__ {
typedef typename boost::result_of<F()>::type result_type;
typedef typename asynchronous_completion_token<AE, result_type>::type type;
- };
+ };
}
The default implementation of fork delegates on fork asynchronous executor function.
- template< typename AE, typename F >
+ template< typename AE, typename F >
typename result_of::fork<AE, F>::type fork( AE& ae, F fn ) {
return ae.fork(fn);
}
Forking n-ary functions relies on the nullary version and bind.
- template< typename AE, typename F, typename A1, ..., typename An >
- typename asynchronous_completion_token<AE,
- typename boost::result_of<F(A1,..., An)>::type >::type
+ template< typename AE, typename F, typename A1, ..., typename An >
+ typename asynchronous_completion_token<AE,
+ typename boost::result_of<F(A1,..., An)>::type >::type
fork( AE& ae, F fn, A1 a1, ..., An an ) {
return ae.fork( bind( fn, a1, ..., an ) );
}
@@ -99,7 +98,7 @@
We can define a basic_threader which just returns a new thread as follows:
class basic_threader {
- public:
+ public:
template <typename T>
struct handle {
typedef boost::thread type;
@@ -109,29 +108,29 @@
boost::thread fork(F f) {
thread th(f);
return boost::move(th);
- }
+ }
};
-The library includes also a launcher class that creates a thread and returns a unique_future when forking
+The library includes also a launcher class that creates a thread and returns a unique_future when forking
class launcher {
- public:
+ public:
template <typename T>
struct handle {
typedef unique_future<T> type;
};
template <typename F>
- unique_future<typename result_of<F()>::type>
+ unique_future<typename result_of<F()>::type>
fork(F f) {
typedef typename boost::result_of<F()>::type result_type;
packaged_task<result_type> tsk(f);
unique_future<result_type> res = tsk.get_future();
thread th(boost::move(tsk));
return res;
- }
+ }
};
-and a shared_launcher class that creates a thread and returns a shared_future when forking
+and a shared_launcher class that creates a thread and returns a shared_future when forking.
Given the sequential example:
@@ -172,80 +171,64 @@
}
-The library include also a threader class based on the Kevlin proposal:
-
- class unique_threader {
- public:
- template <typename T>
- struct handle {
- typedef unique_joiner<T> type;
- };
- template <typename F>
- unique_joiner<typename result_of<F()>::type>
- fork(F f) {
- typedef typename result_of<F()>::type result_type;
- return joiner<result_type>(f);
- }
-
- };
-
-The question now is how we can adapt it to an existing asynchronous executor such as
-the Boost.ThreadPool library. We need to specialize the template class
-asynchronous_completion_token
+The question now is how we can adapt it to an existing asynchronous executor such as
+the Boost.ThreadPool library. We need to specialize the template class
+asynchronous_completion_token to states which is the __ACT__ associate to the __tp_pool__.
namespace boost { namespace interthreads {
-
+
template <typename Channel, typename T>
struct asynchronous_completion_token<boost::tp::pool<Channel>,T> {
typedef boost::tp::task<T> type;
- };
-
+ };
+
}}
-and function fork function.
-
+and also to specialize the fork function as the default requires a form member function and __tp_pool__ provides a `submit()` member function`
+
namespace boost { namespace interthreads {
-
- template< typename Channel, typename F >
- result_of::fork<boost::tp::pool<Channel>, F>::type
+
+ template< typename Channel, typename F >
+ result_of::fork<boost::tp::pool<Channel>, F>::type
fork<boost::tp::pool<Channel>,F>( boost::tp::pool<Channel>& ae, F fn ) {
return ae.submit(fn);
}
}
}
-
-As the preceding is ilegal in C++03 we need to use an auxiliary class to define the default behaviour of fork
- namespace boost { namespace interthreads {
- template< typename AE, typename F >
- struct fork_aux {
- static typename result_of::fork<AE,F>::type fork(AE& ae, F fn ) {
- return ae.fork(fn);
- }
- };
+Evidently these specialization must be done on the `boost::interthreads` namespace.
- template< typename AE, typename F >
- typename result_of::fork<AE,F>::type
- fork( AE& ae, F fn ) {
- return fork_aux<AE,F>::fork(ae,fn);
- }
+As the preceding is ilegal in C++03 we need to use an auxiliary class to define the default behaviour of fork
+
+ namespace partial_specialization_workaround {
+ template< typename AE, typename F >
+ struct fork {
+ static typename result_of::fork<AE,F>::type apply(AE& ae, F fn ) {
+ return ae.fork(fn);
+ }
+ };
}
+ template< typename AE, typename F >
+ typename result_of::fork<AE,F>::type
+ fork( AE& ae, F fn ) {
+ return partial_specialization_workaround::fork<AE,F>::apply(ae,fn);
}
And specialize partially the fork_auc class
- template< typename Channel, typename F >
- struct fork_aux<boost::tp::pool<Channel>,F> {
- typename result_of::fork<boost::tp::pool<Channel>, F>::type
- fork( boost::tp::pool<Channel>& ae, F fn ) {
- return ae.submit(fn);
+ namespace boost { namespace interthreads {
+ namespace partial_specialization_workaround {
+ template< typename Channel, typename F >
+ struct fork<boost::tp::pool<Channel>,F> {
+ static typename result_of::fork<boost::tp::pool<Channel>, F>::type
+ apply( boost::tp::pool<Channel>& ae, F fn ) {
+ return ae.submit(fn);
+ }
+ };
}
- };
-
-
+ }}
-Note that the single fork function that needs specialization is the one taking a nullary
-function as parameter.
+Note that only the __fork__ function needs to be specialized. The library provides he other overloadings.
We can write the preceding main function in a more generic way
@@ -275,28 +258,34 @@
do(ae);
}
+Instead of definng a type the user can make use of BOOST_AUTO once she includes the
+associated files on the threadpool sub-directory.
+
+ BOOST_AUTO(fm1, bith::fork(ae, f, 1.0, 1000000 ));
+
+
The library allows also to fork several functions at the same time
result_of::fork_all<AE, int(*)(), int(*)(), int(*)()>::type handles = bith::fork_all(ae, f, g, h);
std::cout << get<1>(res).get() - get<0>(res).get() + get<2>(res).get() << std::endl;
-The result of the fork_all operation is a fusion tuple of asynchronous completion token handles.
+The result of the fork_all operation is a fusion tuple of asynchronous completion token handles.
The user can apply any fusion algorithm on this tuple as for example
bool b = fusion::none(handles, fct::interruption_requested());
-The asynchronous completion token models follows two interfaces, the thread interface and the
+The asynchronous completion token models follows two interfaces, the thread interface and the
unique_/shared_future interface.
-To make common tasks easier the library provide some functors in the name space fct:
-for the thread interface as
+To make common tasks easier the library provide some functors in the name space fct:
+for the thread interface as
-* fct::join
+* fct::join
* fct::join_until
-* fct::join_for
-* fct::detach
-* fct::interrupt
+* fct::join_for
+* fct::detach
+* fct::interrupt
* fct::interrupt_requested
and for the future operations as
@@ -320,12 +309,12 @@
};
}
-In addition the library provides some non member functions that are the result of applying
+In addition the library provides some non member functions that are the result of applying
these functors to the tuple using a fusion algorithm:
* join_all
* join_all_until
-* join_all_for
+* join_all_for
* detach_all
* interrupt_all
* interrupt_requested_on_all
@@ -346,8 +335,8 @@
return fusion::transform(t, fct::get());
}
-The library defines in a systematic way the result_of of a function as a metafunction
-having the same name as the function on the namespace result_of, as the Boost.Fusion library
+The library defines in a systematic way the result_of of a function as a metafunction
+having the same name as the function on the namespace result_of, as the Boost.Fusion library
does.
namespace result_of {
@@ -360,7 +349,7 @@
So the user can do the following
result_of::fork_all<AE, int(*)(), int(*)(), int(*)()>::type res = bith::fork_all(ae, f, g, h);
- result_of::get_all<result_of::fork_all<AE, int(*)(), int(*)(), int(*)()>::type>::type values
+ result_of::get_all<result_of::fork_all<AE, int(*)(), int(*)(), int(*)()>::type>::type values
= bith::get_all(handles);
or using a typedef
@@ -374,26 +363,32 @@
auto res = bith::fork_all(ae, f, g, h);
auto values = bith::get_all(handles);
-Last but not least the library provides also some sugaring functions like
-wait_for_all that forks and wait for the result.
+or using BOOST_AUTO
+
+ BOOST_AUTO(res, bith::fork_all(ae, f, g, h));
+ BOOST_AUTO(values, bith::get_all(handles));
+
+Last but not least the library provides also some sugaring functions like
+wait_for_all that forks and wait for the completion of all the functions.
result_of::wait_for_all<AE, int(*)(), int(*)(), int(*)()>::type res = bith::wait_for_all(ae, f, g, h);
std::cout << get<1>(res) - get<0>(res) + get<2>(res) << std::endl;
-and wait_for_any which works with functions that return the same type or are convertible to the same type.
+and wait_for_any, which works only with functions that return the same type or are convertible to the same
+type, and return the index and the value of the any of the completed functions.
result_of::wait_for_any<AE, int(*)(), int(*)(), int(*)()>::type res = bith::wait_for_any(ae, f, g, h);
std::cout << "function " << res.first << " finshed first with result=" << res.second << std::endl;
-The current implementation use the wait_for_any function so any AE must provide a way to get a
-unique|shared_future from its ACT.
+The current implementation use the wait_for_any function so any AE must provide a way to get a
+unique|shared_future from its __ACT__.
The library defines a functor allowing the user to specialize it
template <typename AE>
struct get_future {
template <typename T>
- shared_future<T>& operator()(typename asynchronous_completion_token<AE,T>::type& act)
+ shared_future<T>& operator()(typename asynchronous_completion_token<AE,T>::type& act)
{ return act.get_future(); }
};
@@ -404,11 +399,11 @@
struct AsynchronousExecutor {
template <typename T>
struct handle {
- typedef implementation-specific type;
+ typedef implementation-specific-type-modeling-a-ACT type;
};
-
+
template <typename F>
- typename handle<typename result_of<F()>::type>::type
+ typename handle<typename result_of<F()>::type>::type
fork(F f);
};
@@ -421,7 +416,7 @@
[/=============================================================================]
See the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1883.pdf N1833 - Preliminary Threading Library Proposal for TR2]
-where Kevlin Henney introduce the concept of threader an asynchronous executor and a function thread that evaluate a function
+where Kevlin Henney introduce the concept of threader as an asynchronous executor and a function thread that evaluate a function
asynchronously and returns an asynchronous completion token joiner, able to join but also to to get the value of the function result.
The main specifcities is that here we make a difference between unique_joiner (move-only) and shared_joiner and as consequence unique_threader and shared_threader.
@@ -432,8 +427,8 @@
[section Decorators]
[/=============================================================================]
-`boost::call_once` provides a mechanism for ensuring that an initialization routine is run exactly once on a
-programm without data races or deadlocks.
+`boost::call_once` provides a mechanism for ensuring that an initialization routine is run exactly once on a
+programm without data races or deadlocks.
`boost::this_thread::at_thread_exit` allows to execute a cleanup function at thread exit.
If we want a setup function be executed once at the begining on the threads and a cleanup at thread exit we need to do
@@ -457,8 +452,8 @@
boost::this_thread::at_thread_exit(cleanup);
}
-Different services could require these setup/cleanup functions to be called, and so
-each thread function should do
+Different services could require these setup/cleanup functions to be called, and so
+each thread function should do
void thread_main() {
serv1::init();
@@ -468,35 +463,36 @@
// ...
}
-This approach is valid for services that the user can configure for specifics threads,
+This approach is valid for services that the user can configure for specifics threads,
but not for services that must be installed on every thread.
-__thread_decoration__ ensures that a setup function is called only once by thread before
-the thread function provided the thread is created with a decorator wrapper.
+__thread_decoration__ ensures that a setup function is called only once by thread before
+the thread function provided the thread is created with a decorator wrapper.
This setup function is usualy used to set thread specific pointers and call functions once.
-The conterpart of the setup is the cleanup. The __thread_decoration__ takes an optional
+The conterpart of the setup is the cleanup. The __thread_decoration__ takes an optional
cleanup function which will be executed at thread exit.
// define in only the implementation file of each service
-
+
boost::interthreads::decoration serv1:decoration(serv1:setup, serv1:cleanup);
// ...
boost::interthreads::decoration servN:decoration(servN:setup, servN:cleanup);
-
-
+
+
void thread_main() {
// do whatever using serv1, ..., servN.
// ...
}
-
+
// ...
{
boost::thread th(boost::interthreads::make_decorator(thread_main));
//...
}
-
-We can use a basic_threader_decorator as asynchronous executor to fork thread_main.
+
+We can use a basic_threader_decorator as asynchronous executor to fork thread_main.
+
// ...
{
boost::thread th=fork(basic_threader_decorator(), thread_main);
@@ -509,21 +505,21 @@
[section Sharing Thread Local Storage]
[/=============================================================================]
-Thread local storage allows multi-threaded applications to have a separate instance of a given data item for
-each thread. But do not provide any mechanism to access this data from other threads. Although this seems to
-defeat the whole point of thread-specific storage, it is useful when these contexts needs some kind of
+Thread local storage allows multi-threaded applications to have a separate instance of a given data item for
+each thread. But do not provide any mechanism to access this data from other threads. Although this seems to
+defeat the whole point of thread-specific storage, it is useful when these contexts needs some kind of
communication between them, or some central global object needs to control them.
-The intent of the `boost::thread_specific_shared_ptr` class is to allow two threads to establish a shared memory
+The intent of the `boost::thread_specific_shared_ptr` class is to allow two threads to establish a shared memory
space, without requiring the user code to pass any information.
-`boost::thread_specific_shared_ptr` provides a portable mechanism for shared thread-local storage that works on
-all compilers supported by `boost::thread` and `boost::shared_ptr`. Each instance of
-`boost::thread_specific_shared_ptr` represents a pointer to a shared object where each thread must have a distinct
-value.
+`boost::thread_specific_shared_ptr` provides a portable mechanism for shared thread-local storage that works on
+all compilers supported by `boost::thread` and `boost::shared_ptr`. Each instance of
+`boost::thread_specific_shared_ptr` represents a pointer to a shared object where each thread must have a distinct
+value.
-Only the current thread can modify the thread specific shared pointer using the non const functions reset/release
+Only the current thread can modify the thread specific shared pointer using the non const functions reset/release
functions. Each time these functions are used a synchronization must be ensured to update the mapping.
-The other threads have only read access to the shared_ptr<T>. It is worh saying that the shared object T must be
+The other threads have only read access to the shared_ptr<T>. It is worh saying that the shared object T must be
thread safe.
[endsect]
@@ -533,13 +529,13 @@
On fault tolerant systems we need to be able to detect threads that could stay on a loop, or simply blocked.
One way to detect this situations is to require the thread to signal it is alive by calling a check point function.
-Of course it should be up to the user to state when this mechanism is enabled or disabled.
+Of course it should be up to the user to state when this mechanism is enabled or disabled.
At the begining of a thread the keep alive mechanism is disabled.
A thread will be considered dead if during a given period the number of checkins is inferior to a given threshold.
These two parameters can be given when the keep alive mechanislm is enabled.
-The controler checks at predefined intervals if the thread is dead, and in this case it will call a user specific
+The controler checks at predefined intervals if the thread is dead, and in this case it will call a user specific
function which by default aborts the program.
[endsect]
@@ -557,7 +553,7 @@
}
-The __thread_tuple__ class is responsible for launching and managing a static collection of threads
+The __thread_tuple__ class is responsible for launching and managing a static collection of threads
that are related in some fashion. No new threads can be added to the tuple once constructed. So we can write
{
@@ -578,19 +574,19 @@
{
boost::thread_group tg;
tg.create_thread(thread1);
-
+
// later on
tg.create_thread(thread2);
boost::thread th3(thread3)
tg.add_thread(th3);
-
+
// later on
tg.remove_thread(th3);
-
+
tg.join_all(thread1);
}
-Objects of type __thread_tuple__ are movable, so they can be stored in move-aware containers, and returned from
+Objects of type __thread_tuple__ are movable, so they can be stored in move-aware containers, and returned from
functions. This allows the details of thread tuple creation to be wrapped in a function.
boost::interthreads::thread_tuple<2> make_thread_tuple(...);
Modified: sandbox/interthreads/libs/interthreads/doc/overview.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/overview.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/overview.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -15,47 +15,57 @@
__boost_interthreads__ extends __boost_thread__ adding some features:
-* threader/joiner: A Threader runs a unary function in its own thread. A Joiner is used to synchronise with and pick
-up the result from the unary function.
+* An asynchronous execution framework working with __AE__ and __ACT__. It includes some generic functions and several __AE__ and __ACT__:
+ * fork and fork_all to execute asynchronously functions
+ * fork_after: request an __AE__ to execute a function asynchronously once each one of __ACT__ in the dependency tuple parameter are ready. It is similar to the async_with_dependencies proposed Peter Dimov.
+ * generic get, join, ... free functions to synchroyze on an __ACT__
+ * generic get_all, join_all, ... free functions to synchroyze on multiple __ACT__
+ * generic wait_for_all, wait_for_any to execute asynchronously functions and wait for the completion of all or any of them.
+
+* Some __AE__ and __ACT__ models
+ * basic_threader: can be seen as a thread factory executing asynchronously a function on the returned thread.
+ * launchers: Lanchers can be seen as a future factory executing asynchronously a function on a hiden thread.
+ * threader/joiner: A Threader runs a unary function in its own thread. A Threader can be seen as a Joiner
+ factory executing asynchronously a function on a thread encapsulated on the returned Joiner. The joiner is used
+ to synchronise with and pick up the result from a function or to manage the encapsulated thread.
+ * __tp_pool__ and __tp_task__ customization as an __AE__ and an __ACT__ respectively. __tp_pool__ can be seen as
+ a __tp_task__ factory executing asynchronously a function on a pool of threads.
+ * a generic asynchronous_executor_decorator which allows to decorate the function to be evaluated asynchronously.
+
+* Some thread extension
+ * A thread_decoration class allowing to define setup/cleanup functions which will be called only once by thread (if
+the thread function is decorated with thread_decorator): setup before the thread function and cleanup at thread exit.
+It is used together with asynchronous_executor_decorator
-* An asynchronous execution framework including
- * fork and fork_all functions
- * wait_for_all, wait_for_any functions
- * set_all, join_all, ...
- * fork_after: request the AE to execute a function asynchronously once each one of ACTs in the dependency tuple parameter are ready. It is similar to the async_with_dependencies proposed Peter Dimov.
+ * A thread_decorator/thread_decorate class/function which decorate a thread function in order to call the setup and the
+cleanup of all the thread_decorations.
-* thread decorator: thread_decorator allows to define setup/cleanup functions which will be called only once by thread:
-setup before the thread function and cleanup at thread exit.
-
-* thread specific shared pointer: this is an extension of the thread_specific_ptr providing access
+ * A thread specific shared pointer which is an extension of the thread_specific_ptr providing access
to this thread specific context from other threads.
As it is shared the stored pointer is a shared_ptr instead of a raw one.
-* thread keep alive mechanism: this mechanism allows to detect threads that do not prove that they are alive by
-calling to the keep_alive_point regularly.
+ * A thread keep alive mechanism: this mechanism allows to detect threads that do not prove that they are alive by
+calling to the keep_alive_point regularly.
When a thread is declared dead a user provided function is called, which by default will abort the program.
-* thread tuple: defines a thread groupe where the number of threads is know statically and the threads are
-created at construction time.
+* A thread static array
+ * thread tuple: defines a thread groupe where the number of threads is know statically and the threads are
+created at construction time in oposition to a thread_group.
+
+* A thread static array and a thread group with wait for any feature
+ * set_once: a synchonizer that allows to set a variable only once, notifying to the variable value to whatever is waiting for that.
-* set_once: a synchonizer that allows to set a variable only once, notifying
-to the variable value to whatever is waiting for that.
+ * thread_tuple_once: an extension of the boost::thread_tuple which allows to join the completion of any thread using for that the set_once synchronizer.
-* thread_tuple_once: an extension of the boost::thread_tuple which allows to join the thread finishing
-the first, using for that the set_once synchronizer.
+ * thread_group_once: an extension of the boost::thread_group which allows to join the completion of any thread in the group using for that the set_once synchronizer.
-* thread_group_once: an extension of the boost::thread_group which allows to join the thread finishing
-the first, using for that the set_once synchronizer.
References
-* thread_decorator and thread_specific_shared_ptr are based on the original implementation of
-[@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming [*threadalert]]
+* thread_decorator and thread_specific_shared_ptr are based on the original implementation of [@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming [*threadalert]]
written by Roland Schwarz.
-* threader/joiner are based on the original idea of Kevlin Henney
-[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1883.pdf Preliminary Threading Library
-Proposal for TR2]
+* threader/joiner are based on the original idea of Kevlin Henney [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1883.pdf N1833 - Preliminary Threading Library Proposal for TR2]
[/====================================]
@@ -67,14 +77,14 @@
* Code is in `fixed width font` and is syntax-highlighted.
* Replaceable text that you will need to supply is in [~italics].
* If a name refers to a free function, it is specified like this:
- `free_function()`; that is, it is in code font and its name is followed by `()`
+ `free_function()`; that is, it is in code font and its name is followed by `()`
to indicate that it is a free function.
* If a name refers to a class template, it is specified like this:
- `class_template<>`; that is, it is in code font and its name is followed by `<>`
+ `class_template<>`; that is, it is in code font and its name is followed by `<>`
to indicate that it is a class template.
* If a name refers to a function-like macro, it is specified like this: `MACRO()`;
that is, it is uppercase in code font and its name is followed by `()` to
- indicate that it is a function-like macro. Object-like macros appear without the
+ indicate that it is a function-like macro. Object-like macros appear without the
trailing `()`.
* Names that refer to /concepts/ in the generic programming sense are
specified in CamelCase.
Modified: sandbox/interthreads/libs/interthreads/doc/rationale.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/rationale.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/rationale.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -15,11 +15,11 @@
[variablelist
-[[Function wrapper versus thread refinement] [The threadalert on which this library was initialy based redefined the
-boost:thread class which called implicitly the wrapper. As the single varying features between both threads was this
+[[Function wrapper versus thread refinement] [The threadalert on which this library was initialy based redefined the
+boost:thread class which called implicitly the wrapper. As the single varying features between both threads was this
wrapping of the thread function it has been isolated in the interthreads library.]]
-[[Static decoration variables] [Thread decorations construction is not thread safe and must be done before other threads have been
+[[Static decoration variables] [Thread decorations construction is not thread safe and must be done before other threads have been
created and the __thread_decorator_decorate__ function is called.]]
]
@@ -36,8 +36,8 @@
[[External locking] [In order to ensure thread safety while providing as much functionality as possible the class allows
to get the map of thread specific contexts as soon as the application provides a `unique_lock`.]]
-[[Mimic thread_specific_ptr] [From the point of view of the current thread thread_specific_shared_ptr behaves as a thread_specific_ptr.
-From it we takes:
+[[Mimic thread_specific_ptr] [From the point of view of the current thread thread_specific_shared_ptr behaves as a thread_specific_ptr.
+From it we takes:
```thread_specific_shared_ptr();
explicit thread_specific_shared_ptr(void (*cleanup_)(shared_ptr_type));
@@ -46,12 +46,12 @@
T& operator*() const;
void reset();
template<class Y> void reset(Y * p);
-```
+```
]]
-[[Mimic shared_ptr] [From the point of the other threads thread_specific_shared_ptr behaves as a shared_ptr lockup.
+[[Mimic shared_ptr] [From the point of the other threads thread_specific_shared_ptr behaves as a shared_ptr lockup.
From the point of view of the current thread the stored pointer is located in a shared_pointer, so we can use the shared_ptr deleter feature
-From it we takes:
+From it we takes:
```T* get() const;
T* operator->() const;
@@ -60,10 +60,10 @@
template<class Y> void reset(Y * p);
template<class Y, class D> void reset(Y * p, D d);
template<class Y, class D, class A> void reset(Y * p, D d, A a);
-```
+```
]]
-[[Why doesn't thread_specific_shared_ptr provide a release() function?]
+[[Why doesn't thread_specific_shared_ptr provide a release() function?]
[As it store a shared_ptr, it cannot give away ownership unless it's unique() because the other copy will still destroy the object.]]
]
@@ -102,15 +102,15 @@
[variablelist
-[[Can a thread that has just do a check point be considered as dead less than one second after?]
-[Whell this depends on the enabling parameters. If the checking parameter is greater tan one it could be possible that
+[[Can a thread that has just do a check point be considered as dead less than one second after?]
+[Whell this depends on the enabling parameters. If the checking parameter is greater than one it could be possible that
the thread do a check_point just before the keep alive manager do the check, seen that there are not enough check_points and declaring the thread dead.
If you want to avoid this situation let the checkin to 1.
]]
[[Nesting enablers and disablers] [Enablers/disablers use RAII, so they can be nested and the context be restored on the destructor.]]
-[[Configurable on dead action] [The default action is to abort the process because I don't see any generic and cleaner way to manage this event.
+[[Configurable on dead action] [The default action is to abort the process because I don't see any generic and cleaner way to manage this event.
The library provides this hook for user wanting to try something specific.]]
[[Who control the controler?] [There is no way to control this thread other than adding an external process.]]
@@ -127,16 +127,16 @@
[variablelist
[[Why must be not copiable?] [Thread tuples can not be copiable since boost::thread is not copiable.]]
[[Why should be movable?] [If we want functions to return Thread tuples it is necessary to make them movable.]]
-[[Mimic boost::thread_group] [thread_tuple has in common some function found in thread_group. From it we take
+[[Mimic boost::thread_group] [thread_tuple has in common some function found in thread_group. From it we take
```void join_all();
void interrupt_all();
std::size_t size();
-```
+```
]]
-[[Mimic boost::thread] [We can consider a thread tuple as a compound thread, and so we can mimic
-the thread intyerface. From it we takes
+[[Mimic boost::thread] [We can consider a thread tuple as a compound thread, and so we can mimic
+the thread intyerface. From it we takes
```void join();
void interrupt();
@@ -153,14 +153,14 @@
The library provides a safe function to get a constant thread reference
```const thread& operator[](std::size_t i) const;```
-
+
The problem if we provide the non constant variant is that the user can detach them.
-
-
+
+
]]
-[[Joining the first finishing thread of a thread tuple]
+[[Joining the first finishing thread of a thread tuple]
[This functionallity has a price. We need to synchronize all the threads transparently, so we need to wrap the user thread functions.
]]
]
Modified: sandbox/interthreads/libs/interthreads/doc/reference.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/reference.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/reference.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,6 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J. Botet Escriba
+ 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).
]
@@ -7,3816 +8,102 @@
[/==========================]
[section:reference Reference]
[/==========================]
+[include concepts.qbk]
-[/==========================================================================================]
-[section Header `<boost/interthreads/fork.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- namespace result_of {
- template <typename AE, typename F, typename A1, ..., typename An>
- struct fork;
- typedef typename AE::handle<typename result_of<F(A1, ..., An)> >::type type;
- };
- }
-
- template< typename AE, typename F >
- typename result_of::fork<AE,F>::type
- fork( AE& ae, F fn );
-
- template< typename AE, typename F, typename A1 >
- typename result_of::fork<AE,F, mpl::vector<A1> >::type> >::type
- fork( AE& ae, F fn, A1 a1 );
-
- template< typename F >
- typename result_of::fork<default_asynchronous_executor,F>::type
- fork( F fn );
-
- template< typename F, typename A1 >
- typename result_of::forkT<default_asynchronous_executor,typename result_of<F(A1)>::type >::type
- fork( F fn, A1 a1 );
-
- }
- }
-
-
-
-[section Metafunction `result_of::fork<AE,F> `]
-[/==========================================================================================]
-
-A metafunction returning the result type of applying fork to an asynchronous executor and a Nullary functor.
-
- namespace result_of {
- template <typename AE, typename F, typename A1, ..., typename An>
- struct fork;
- typedef typename AE::handle<typename result_of<F(A1, ..., An)> >::type type;
- };
- }
-
-[table fork Parameters
- [
- [[*Parameter]]
- [[*Requirement]]
- [[*Description]]
- ]
- [
- [`AE`]
- [A model of `AsynchrousExecutor`]
- [Operation's argument ]
- ]
- [
- [`F`]
- [A model of n-ary function]
- [Operation's argument ]
- ]
- [
- [`Ak`]
- [A model of n-ary function]
- [n-ary function argument type for argument k]
- ]
-]
-
-[variablelist
-[[Expression:] [result_of::fork<AE,F,A1,...,An>::type]]
-[[Return type:] [AE::handle<typename result_of<F(A1,...,An)> >::type]]
-]
-
-[endsect]
-
-[section Non member function `fork()`]
-[/==========================================================================================]
-
- template< typename AE, typename F, typename A1 , ... typename An >
- typename result_of::fork<AE,F, A1, An> >::type> >::type
- fork( AE& ae, F fn, A1 a1 , ..., An an );
-
-[table fork Parameters
- [
- [[*Parameter]]
- [[*Requirement]]
- [[*Description]]
- ]
- [
- [`AE`]
- [A model of `AsynchrousExecutor`]
- [Operation's argument ]
- ]
- [
- [`F`]
- [A model of n-ary function]
- [Operation's argument ]
- ]
-]
-
-[variablelist
-[[Requires:] [The expression fn(a1, ..., an) must be valid and
-have a type convertible to R, where R is typename result_of<Fn()>::type..]]
-[[Efect:] [Request the `AE` to creates a thread of execution for the function `fn`
-Request the asynchronous evaluation the expression `fn()` with respect to the calling thread to the
-asynchronous executor `ae` and
-places its result in an object h of type AE::handle<R>::type as if by using h.set_value( fn() ).
-If the expression fn() throws an exception e, places e into h as if by using
-h.set_exception( current_exception() ).]]
-]
-[[Returns:] [the AE handle h.]]
-
-[endsect]
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/act_traits.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <typename ACT>
- struct act_value;
-
- template <typename ACT>
- struct is_movable;
-
- template <typename ACT>
- struct has_future_if;
-
- template <typename ACT>
- struct has_thread_if;
-
- template <typename AE, typename T>
- struct asynchronous_completion_token;
-
- template <typename AE>
- struct get_future;
-
-}
-}
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/asynchronous_executor.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <typename AE, template <class> class Decorator>
- struct asynchronous_executor_decorator : AE {
- template <typename T>
- struct handle {
- typedef typename AE::template handle<T>::type type;
- };
-
- template <typename F>
- typename AE::template handle< typename boost::result_of<F()>::type >::type
- fork( F fn );
-
- asynchronous_executor_decorator();
-
- template <typename Nullary>
- asynchronous_executor_decorator(thread::native_handle_attr_type& attr, Nullary f);
-
- asynchronous_executor_decorator(Nullary f);
-
- asynchronous_executor_decorator(boost::detail::thread_move_t<asynchronous_executor_decorator> x);
-
- asynchronous_executor_decorator& operator=(boost::detail::thread_move_t<asynchronous_executor_decorator> x);
-
- operator boost::detail::thread_move_t<asynchronous_executor_decorator>();
-
- boost::detail::thread_move_t<asynchronous_executor_decorator> move();
- };
-
- template <typename AE, template <class> class Decorator>
- struct get_future<asynchronous_executor_decorator<AE, Decorator> > {
- template <typename T>
- struct future_type {
- typedef typename AE::template get_future<AE>::type type;
- };
- template <typename T>
- typename future_type<T>::type& operator()(typename AE::template handle<T>::type & j);
- };
- }
- }
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/asynchronous_adapter.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <typename AE, template <class> class Decorator>
- struct asynchronous_executor_decorator : AE {
- template <typename T>
- struct handle {
- typedef typename AE::template handle<T>::type type;
- };
-
- template <typename F>
- typename AE::template handle< typename boost::result_of<F()>::type >::type
- fork( F fn );
-
- asynchronous_executor_decorator();
-
- template <typename Nullary>
- asynchronous_executor_decorator(thread::native_handle_attr_type& attr, Nullary f);
- asynchronous_executor_decorator(Nullary f);
-
- asynchronous_executor_decorator(boost::detail::thread_move_t<asynchronous_executor_decorator> x);
-
- asynchronous_executor_decorator& operator=(boost::detail::thread_move_t<asynchronous_executor_decorator> x);
-
- operator boost::detail::thread_move_t<asynchronous_executor_decorator>();
-
- boost::detail::thread_move_t<asynchronous_executor_decorator> move();
- };
-
- template <typename AE, template <class> class Decorator>
- struct get_future<asynchronous_executor_decorator<AE, Decorator> > {
- template <typename T>
- struct future_type {
- typedef typename AE::template get_future<AE>::type type;
- };
- template <typename T>
- typename future_type<T>::type& operator()(typename AE::template handle<T>::type & j);
- };
- }
- }
-
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/basic_threader.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- class basic_threader {
- public:
- thread::native_handle_attr_type& attr();
-
- template <typename T>
- struct handle {
- typedef thread type;
- };
-
- template <typename F> thread fork(F f);
- };
-
- template <>
- struct act_value<thread> {
- typedef void type;
- };
- }
- }
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/basic_threader_decorator.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- typedef asynchronous_executor_decorator<basic_threader,thread_decorator> basic_threader_decorator;
-
- }
- }
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/fork_after.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <typename ACT>
- struct act_wrapper {
- act_wrapper();
- void wait_initialized();
- void set(ACT& other);
- void set(boost::detail::thread_move_t<ACT> other);
- void wait();
- typename act_value<ACT>::type get();
- void join();
- };
-
- template <typename ACT>
- struct act_value<act_wrapper<ACT> > {
- typedef typename act_value<ACT>::type type;
- };
-
- template <typename ACT>
- struct is_movable<act_wrapper<ACT> > : is_movable<ACT>{};
-
- template <typename ACT>
- struct has_future_if<act_wrapper<ACT> > : has_future_if<ACT> {};
-
- template <typename ACT>
- struct has_thread_if<act_wrapper<ACT> > : has_thread_if<ACT>{};
-
-
- namespace result_of {
- template <typename AE,typename F>
- struct fork_after {
- typedef typename boost::result_of<F()>::type result_type;
- typedef typename asynchronous_completion_token<AE, result_type>::type act_type;
- typedef act_wrapper<act_type> type;
- };
- }
-
- namespace partial_specialization_workaround {
- template< typename AE, typename F, typename D >
- struct fork_after {
- static typename result_of::fork_after<AE,F>::type
- apply(AE& ae, F fn, D& d);
- };
- }
- template< typename AE, typename F, typename D>
- typename result_of::fork_after<AE,F>::type
- fork_after( AE& ae, F fn, D& d);
-
-
- }
- }
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/scheduler.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <typename C>
- class scheduler {
- explicit scheduler(
- tp::poolsize const& psize
- );
- template <typename T>
- struct handle {
- typedef tp::task<T> type;
- };
- template <typename F>
- tp::task<typename boost::result_of<F()>::type>
- fork(F f);
- };
-
- template <typename Channel>
- struct get_future<scheduler<Channel> > {
- template <typename T>
- struct future_type {
- typedef shared_future<T> type;
- };
- template <typename T>
- shared_future<T>& operator()(tp::task<T>& act);
- };
-
- template <typename Channel, typename T>
- struct asynchronous_completion_token<boost::tp::pool<Channel>,T> {
- typedef boost::tp::task<T> type;
- };
-
- namespace partial_specialization_workaround {
- template< typename Channel, typename F >
- struct fork<boost::tp::pool<Channel>,F> {
- static typename result_of::fork<boost::tp::pool<Channel>, F>::type
- apply( boost::tp::pool<Channel>& ae, F fn );
- };
- }
- template <typename C>
- struct get_future<tp::pool<C> > {
- template <typename T>
- shared_future<T>& operator()(tp::task<T>& act);
- };
-
- template <typename ResultType>
- struct act_value<tp::task<ResultType> > {
- typedef ResultType type;
- };
-
- template <typename R>
- struct is_movable<tp::task<R> > : mpl::false_{};
-
- template <typename R>
- struct has_future_if<tp::task<R> > : mpl::true_{};
-
- template <typename R>
- struct has_thread_if<tp::task<R> > : mpl::false_{};
-
- }
- }
-
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/fork_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- namespace result_of {
- template <typename AE, typename T>
- struct fork_all;
- template <typename AE, typename F1, ..., typename Fn>
- struct fork_all <AE,fusion::tuple<F1, ..., Fn> >{
- typedef fusion::tuple<
- typename result_of::fork<AE,F1>::type,
- ...
- typename result_of::fork<AE,Fn>::type
- > type;
- };
- }
-
- template< typename AE, typename F1, ..., typename Fn>
- typename result_of::fork_all<AE, mpl::tuple<F1, ..., Fn> >::type
- fork_all( AE& ae, F1 f1, ..., Fn fn );
-
- template< typename F1, ..., typename Fn>
- typename result_of::fork_all<default_asynchronous_executor, F1, ..., Fn>::type
- fork_all( F1 f1, ..., Fn fn );
-
- }
- }
-
-[section Metafunction `result_of::fork_all<AE,F1, ..., Fn> `]
-[/==========================================================================================]
-
-A metafunction returning the result type of applying fork_all to an asynchronous executor and n Nullary functors.
-
- namespace result_of {
- template <typename AE, typename T>
- struct fork_all;
- template <typename AE, typename F1, ..., typename Fn>
- struct fork_all <AE,fusion::tuple<F1, ..., Fn> >{
- typedef fusion::tuple<
- typename result_of::fork<AE,F1>::type,
- ...
- typename result_of::fork<AE,Fn>::type
- > type;
- };
- }
-
-[table fork_all Parameters
- [
- [[*Parameter]]
- [[*Requirement]]
- [[*Description]]
- ]
- [
- [`AE`]
- [A model of `AsynchrousExecutor`]
- [Operation's argument ]
- ]
- [
- [`Fk`]
- [A model of nullary function]
- [Operation's argument ]
- ]
-]
-
-[variablelist
-[[Expression:] [`result_of::fork_all<AE,F1,...,Fn>::type`]]
-[[Return type:] [a fusion tuple of the result of forking each `Fk` by the `AE`]]
-]
-
-[endsect]
-
-[section Non member function `fork_all()`]
-[/==========================================================================================]
-
- template< typename AE, typename F1, ..., typename Fn>
- typename result_of::fork_all<AE, mpl::tuple<F1, ..., Fn> >::type
- fork_all( AE& ae, F1 f1, ..., Fn fn );
-
- template< typename F1, ..., typename Fn>
- typename result_of::fork_all<default_asynchronous_executor, F1, ..., Fn>::type
- fork_all( F1 f1, ..., Fn fn );
-
-[table fork Parameters
- [
- [[*Parameter]]
- [[*Requirement]]
- [[*Description]]
- ]
- [
- [`AE`]
- [A model of `AsynchrousExecutor`]
- [Operation's argument ]
- ]
- [
- [`Fk`]
- [A model of nullary function]
- [Operation's argument ]
- ]
-]
-
-[variablelist
-[[Returns:] [a fusion tuple of the result of forking each `fk` by the `ae`]]
-[[Efect:] [Request the `AE` to creates a n thread of execution one for the function `fk`.]]
-]
-
-[endsect]
-
-
-[endsect]
-
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm.hpp>`]
-[/==========================================================================================]
-
- #include <boost/interthreads/algorithm/join_all.hpp>
- #include <boost/interthreads/algorithm/join_all_until.hpp>
- #include <boost/interthreads/algorithm/wait_all.hpp>
- #include <boost/interthreads/algorithm/wait_all_until.hpp>
- #include <boost/interthreads/algorithm/get_all.hpp>
- #include <boost/interthreads/algorithm/get_all_until.hpp>
- #include <boost/interthreads/algorithm/detach_all.hpp>
- #include <boost/interthreads/algorithm/interrupt_all.hpp>
- #include <boost/interthreads/algorithm/interruption_requested_on_all.hpp>
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/get_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- namespace fct {
- struct get {
- template<typename T>
- typename T::result_type operator()(T& t);
- };
- }
- namespace result_of {
- template <typename Sequence>
- struct get_all {
- typedef typename result_of::transform<Sequence, fct::get>::type type;
- };
- }
- namespace algo {
- template <typename Sequence>
- typename result_of::get_all<Sequence>::type
- get_all(Sequence& mt);
- }
- }
- }
-
-[section Functor `fct::get<>`]
-[/==========================================================================================]
-
- namespace fct {
- struct get {
- template<typename AE>
- typename AE::result_type operator()(AE& ae);
- };
- }
-
-
-[variablelist
-[[Returns:] [The result of the AE::get().]]
-[[Throws:] [if AE::get() throws.]]
-]
-
-[endsect]
-
-[section Metafunction `result_of::get_all<AE,F1, ..., Fn> `]
-[/==========================================================================================]
-
-A metafunction returning the result type of applying get_all to a Sequence of asynchronous executor.
-
- namespace result_of {
- template <typename Sequence>
- struct get_all {
- typedef typename result_of::transform<Sequence, fct::get>::type type;
- };
- }
-
-[table fork_all Parameters
- [
- [[*Parameter]]
- [[*Requirement]]
- [[*Description]]
- ]
- [
- [`Sequence`]
- [A sequence of of `AsynchrousExecutor`s]
- [Operation's argument ]
- ]
-]
-
-[variablelist
-[[Expression:] [`result_of::get_all<S>::type`]]
-[[Return type:] [a fusion tuple of the result of applying get to each one of the asynchronous executors in the sequence]]
-]
-
-[endsect]
-
-[section Non member function `get_all`]
-[/==========================================================================================]
-
- namespace algo {
- template <typename Sequence>
- typename result_of::get_all<Sequence>::type
- get_all(Sequence& mt);
- }
-
-
-[variablelist
-[[Returns:] [a fusion tuple of the result of applying `get` to each one of the asynchronous completion token handles in the sequence.]]
-[[Effect:] [Blocks until all the ACT handles in the Sequence are ready.]]
-[[Throws:] [if some of the ACT::get operation throws]]
-]
-
-[endsect]
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/detach_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- namespace fct {
- struct detach {
- typedef void result_type;
- template<typename ACT>
- void operator()(ACT& act) const;
- };
- }
-
- namespace result_of {
- template <typename Sequence>
- struct detach_all {
- typedef typename fusion::result_of::for_each<Sequence, fct::detach>::type type;
- };
- }
-
- template <typename Sequence>
- void detach_all(Sequence& t);
-
-
- }
- } // namespace boost
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/join_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- namespace fct {
- struct join {
- typedef void result_type;
- template<typename ACT>
- void operator()(ACT& act) const;
- };
- }
-
- namespace result_of {
- template <typename Sequence>
- struct join_all {
- typedef typename fusion::result_of::for_each<Sequence, fct::join>::type type;
- };
- }
-
- template <typename Sequence>
- typename result_of::join_all<Sequence>::type
- join_all(Sequence& t);
-
- }
- }
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/join_all_until.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- namespace fct {
- struct join_until {
- join_until(const system_time& abs_time);
- template<typename ACT>
- bool operator()(ACT& act) const;
- };
-
- struct join_for {
- template <typename Duration>
- join_for(const Duration& rel_time);
- template<typename ACT>
- bool operator()(ACT& act) const;
- }
-
- namespace result_of {
- template <typename Sequence>
- struct join_all_until {
- typedef bool type;
- };
-
- template <typename Sequence>
- struct join_all_for {
- typedef bool type;
- };
- }
-
- template <typename Sequence>
- typename result_of::join_all_until<Sequence>
- join_all_until(Sequence& t, const system_time& abs_time);
-
- template <typename Sequence, typename Duration>
- typename result_of::join_all_for<Sequence>
- join_all_for(Sequence& t, const Duration& rel_time);
-
- }
- } // namespace boost
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/interrupt_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- namespace fct {
- struct interrupt {
- template<typename ACT>
- void operator()(ACT& act) const;
- };
- }
-
- namespace result_of {
- template <typename Sequence>
- struct interrupt_all {
- typedef typename fusion::result_of::for_each<Sequence, fct::interrupt>::type type;
- };
- }
-
- template <typename Sequence>
- void interrupt_all(Sequence& t);
-
- }
- }
-
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/interruption_requested_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- namespace fct {
- struct interruption_requested {
- typedef bool result_type;
-
- template<typename ACT>
- bool operator()(ACT& act) const;
- };
- }
-
- namespace result_of {
- template <typename Sequence>
- struct interruption_requested_on_all {
- typedef typename fusion::result_of::all<Sequence, fct::interruption_requested>::type type;
- };
- }
-
- template <typename Sequence>
- bool interruption_requested_on_all(Sequence& t);
-
- }
- }
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/wait_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- namespace fct {
- struct wait {
- typedef void result_type;
- template<typename ACT>
- void operator()(ACT& act) const;
- };
- }
-
- namespace result_of {
- template <typename Sequence>
- struct wait_all {
- typedef typename fusion::result_of::for_each<Sequence, fct::wait>::type type;
- };
- }
-
- template <typename Sequence>
- typename result_of::wait_all<Sequence>::type
- wait_all(Sequence& t);
-
- }
- } // namespace boost
-
-
-[endsect]
-[/==========================================================================================]
-[section Header `<boost/interthreads/algorithm/wait_all_until.hpp>`]
-[/==========================================================================================]
-
-namespace boost {
-namespace interthreads {
-
- namespace fct {
- struct wait_until {
- wait_until(const system_time& abs_time);
- template<typename ACT>
- bool operator()(ACT& act) const;
-
- struct wait_for {
- template <typename Duration>
- wait_for(const Duration& rel_time);
- template<typename ACT>
- bool operator()(ACT& act) const;
- }
-
- namespace result_of {
- template <typename Sequence>
- struct wait_all_until {
- typedef bool type;
- };
-
- template <typename Sequence>
- struct wait_all_for {
- typedef bool type;
- };
- }
-
- template <typename Sequence>
- typename result_of::wait_all_until<Sequence const>
- wait_all_until(Sequence const& t, const system_time& abs_time);
-
- template <typename Sequence, typename Duration>
- typename result_of::wait_all_for<Sequence>
- wait_all_for(Sequence& t, const Duration& rel_time);
-
-}
-} // namespace boost
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/wait_for_all.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- namespace result_of {
- template <typename AE, typename F1, ..., typename Fn>
- struct wait_for_all {
- typedef fusion::tuple<
- typename result_of<F1()>::type,
- ...
- typename result_of<Fn()>::type,
- > type;
- };
- }
-
- template< typename AE, typename F1, ..., typename Fn>
- typename result_of::wait_for_all<AE, F1, ..., Fn>::type
- wait_for_all( AE& ae, F1 f1, ..., Fn fn );
- }
- }
-
-[section Metafunction `result_of::wait_for_all<AE,F1, ..., Fn> `]
-[/==========================================================================================]
-
-A metafunction returning the result type of applying get_all to a Sequence of asynchronous executor handles.
-
- namespace result_of {
- template <typename AE, typename F1, ..., typename Fn>
- struct wait_for_all {
- typedef fusion::tuple<
- typename result_of<F1()>::type,
- ...
- typename result_of<Fn()>::type,
- > type;
- };
- }
-
-[table wait_for_all Parameters
- [
- [[*Parameter]]
- [[*Requirement]]
- [[*Description]]
- ]
- [
- [`AE`]
- [A model of `AsynchrousExecutor`]
- [Operation's argument ]
- ]
- [
- [`Fk`]
- [A model of nullary function]
- [Operation's argument ]
- ]
-]
-
-[variablelist
-[[Expression:] [`result_of::wait_for_all<AE, F1, ..., Fn>::type`]]
-[[Return type:] [a fusion tuple of the result of applying get to each one of the asynchronous executors handles resulting of forking each function `Fk` by `AE`]]
-]
-
-[endsect]
-
-[section Non member function `wait_for_all`]
-[/==========================================================================================]
-
- template< typename AE, typename F1, ..., typename Fn>
- typename result_of::wait_for_all<AE, F1, ..., Fn>::type
- wait_for_all( AE& ae, F1 f1, ..., Fn fn );
-
-
-[variablelist
-[[Returns:] [a fusion tuple of the result of applying get to each one of the asynchronous executors handles resulting of forking each function `fk` by `ae`.]]
-[[Effect:] [Request the `AE` to creates a n thread of execution one for the function `fk` and
-blocks until all the AE handles are ready.]]
-
-]
-
-[endsect]
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/wait_for_any.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- namespace result_of {
- template <typename AE, typename F1, ..., typename Fn>
- struct wait_for_any {
- // requires typename result_of<F1()>::type == typename result_of<Fk()>::type
- typedef std::pair<unsigned,typename result_of<F1()>::type> type;
- };
- }
-
- template< typename AE, typename F1, ..., typename Fn>
- typename result_of::wait_for_any<AE, F1, ..., Fn>::type
- wait_for_any( AE& ae, F1 f1, ..., Fn fn );
- }
- }
-
-[section Metafunction `result_of::wait_for_all<AE,F1, ..., Fn> `]
-[/==========================================================================================]
-
-A metafunction returning the a pair: the index of the first function executed by the AE and the result type
-of applying get on an asynchronous executor handles.
-
- namespace result_of {
- template <typename AE, typename F1, ..., typename Fn>
- struct wait_for_any {
- // requires typename result_of<F1()>::type == typename result_of<Fk()>::type
- typedef std::pair<unsigned,typename result_of<F1()>::type> type;
- };
- }
-
-[table wait_for_all Parameters
- [
- [[*Parameter]]
- [[*Requirement]]
- [[*Description]]
- ]
- [
- [`AE`]
- [A model of `AsynchrousExecutor`]
- [Operation's argument ]
- ]
- [
- [`Fk`]
- [A model of nullary function]
- [Operation's argument ]
- ]
-]
-
-[variablelist
-[[Expression:] [`result_of::wait_for_any<AE, F1, ..., Fn>::type`]]
-[[Return type:] [a pair: the index of the first function executed by the AE and the result type
-of applying get on an asynchronous executor handles created by `ae` to fork each `fk`]]
-]
-
-[endsect]
-
-[section Non member function `wait_for_any`]
-[/==========================================================================================]
-
- template< typename AE, typename F1, ..., typename Fn>
- typename result_of::wait_for_any<AE, F1, ..., Fn>::type
- wait_for_any( AE& ae, F1 f1, ..., Fn fn );
-
-
-[variablelist
-[[Returns:] [a fusion tuple of the result of applying get to each one of the asynchronous executors handles resulting of forking each function `fk` by `ae`.]]
-[[Effect:] [Request the `AE` to creates a n thread of execution one for the function `fk` and
-blocks until all the AE handles are ready.]]
-
-]
-
-[endsect]
-
-[endsect]
-
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/launcher.hpp>`]
-[/==========================================================================================]
-
- #include <boost/interthreads/fork.hpp>
- namespace boost {
- namespace interthreads {
- class launcher;
- class shared_launcher;
- }
- }
-
-[section Class `launcher `]
-[/==========================================================================================]
-
-Thread launcher using a common configuration managed with the thread attributes and
-returning on the fork operation a unique_future to the resulting type of the call to the threaded function.
-
- class launcher {
- public:
- thread::native_handle_attr_type& attr();
-
- template <typename T>
- struct handle {
- typedef unique_future<T> > type;
- };
-
- template <typename F>
- unique_future<typename result_of<F()>::type>
- fork(F f);
- };
-
-[section Member function `launcher::attributes`]
-[/==========================================================================================]
-
-Reference to the thread attributes accesor.
-
- thread::native_handle_attr_type& attributes();
-
-[variablelist
-[[Returns:] [A reference to the thread attributes.]]
-[[Complexity:] [constant.]]
-]
-
-
-[endsect]
-[section Metafunction `launcher::handle<>`]
-[/==========================================================================================]
-
-Metafunction that returns the result type of the fork function applied to a launcher and the value type.
-
- template <typename T>
- struct handle {
- typedef unique_future<T> > type;
- };
-
-[variablelist
-[[Expression:] [L::handle<T>::type]]
-[[Return type:] [A unique_future<T>.]]
-[[Complexity:] [constant.]]
-
-]
-
-[endsect]
-
-[section Member function `lancher::fork`]
-[/==========================================================================================]
-
- template <typename F>
- unique_future<typename result_of<F()>::type>
- fork(F f);
-
-[variablelist
-[[Returns:] [A unique_future to the result of calling a function F.]]
-[[Effects:] [create a thread executing the function f.
- The result of the function will be stored on the resulting future.]]
-
-]
-
-
-[endsect]
-
-
-[endsect]
-
-[section Class `shared_launcher `]
-[/==========================================================================================]
-
-Thread shared_launcher using a common configuration managed with the thread attributes and
-returning on the fork operation a unique_future to the resulting type of the call to the threaded function.
-
- class shared_launcher {
- public:
- thread::native_handle_attr_type& attr();
-
- template <typename T>
- struct handle {
- typedef unique_future<T> > type;
- };
-
- template <typename F>
- unique_future<typename result_of<F()>::type>
- fork(F f);
- };
-
-[section Member function `shared_launcher::attributes`]
-[/==========================================================================================]
-
-Reference to the thread attributes accesor.
-
- thread::native_handle_attr_type& attributes();
-
-[variablelist
-[[Returns:] [A reference to the thread attributes.]]
-[[Complexity:] [constant.]]
-]
-
-
-[endsect]
-[section Metafunction `shared_launcher::handle<>`]
-[/==========================================================================================]
-
-Metafunction that returns the result type of the fork function applied to a shared_launcher and the value type.
-
- template <typename T>
- struct handle {
- typedef unique_future<T> > type;
- };
-
-[variablelist
-[[Expression:] [L::handle<T>::type]]
-[[Return type:] [A unique_future<T>.]]
-[[Complexity:] [constant.]]
-
-]
-
-[endsect]
-
-[section Member function `lancher::fork`]
-[/==========================================================================================]
-
- template <typename F>
- unique_future<typename result_of<F()>::type>
- fork(F f);
-
-[variablelist
-[[Returns:] [A unique_future to the result of calling a function F.]]
-[[Effects:] [create a thread executing the function f.
- The result of the function will be stored on the resulting future.]]
-
-]
-
-
-[endsect]
-
-
-[endsect]
-
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/threader.hpp>`]
-[/==========================================================================================]
-
- #include <boost/interthreads/fork.hpp>
- namespace boost {
- namespace interthreads {
- template <typename ResultType>
- class unique_joiner;
-
- template <typename ResultType>
- void swap(unique_joiner<ResultType>& lhs, unique_joiner<ResultType>& rhs);
-
- class unique_threader;
-
- template <typename ResultType>
- class shared_joiner;
-
- template <typename ResultType>
- void swap(shared_joiner<ResultType>& lhs, shared_joiner<ResultType>& rhs);
-
- class shared_threader;
- }
- }
-
-[/==================================================]
-[section Template Class `unique_joiner<>`]
-[/==========================================================================================]
-
-
-template <typename ResultType>
-class unique_joiner {
- typedef unique_joiner this_type;
-public:
- unique_joiner(const unique_joiner& rhs) = delete;
- unique_joiner& operator=(const unique_joiner& rhs) = delete;
-
- typedef ResultType result_type;
-
- template <typename Nullary>
- unique_joiner(thread::native_handle_attr_type& attr, Nullary f);
- template <typename Nullary>
- unique_joiner(Nullary f);
-
- unique_joiner(boost::detail::thread_move_t<unique_joiner> x);
- unique_joiner& operator=(boost::detail::thread_move_t<unique_joiner> x);
- operator boost::detail::thread_move_t<unique_joiner>();
- boost::detail::thread_move_t<unique_joiner> move();
-
- void swap(this_type& x);
-
- bool joinable() const;
- void join();
- bool join_until(const system_time& abs_time);
- template<typename TimeDuration>
- inline bool join_for(TimeDuration const& rel_time);
-
- result_type get();
- result_type operator()();
-
- bool is_ready() const;
- bool has_exception() const;
- bool has_value() const;
-
- void wait() const;
- bool wait_until(const system_time& abs_time) const;
- template<typename TimeDuration>
- inline bool wait_for(TimeDuration const& rel_time) const;
-
- thread::id get_id() const;
- void detach();
- void interrupt();
- bool interruption_requested() const;
-
- typedef platform-specific-type native_handle_type;
- native_handle_type native_handle();
-
- unique_future<result_type> get_future();
-
-};
-
-
-[section:destructor unique_joiner Destructor]
-[/==========================================================================================]
-
- ~unique_joiner();
-
-[variablelist
-[[Effects:] [If `*this` has an associated thread of execution, calls __detach__. Destroys `*this`.]]
-[[Throws:] [Nothing.]]
-]
-
-[endsect]
-
-[section:swap Member function `swap()`]
-
- void swap(unique_joiner& other);
-
-[variablelist
-[[Effects:] [Exchanges the threads of execution associated with `*this` and `other`, so `*this` is associated with the thread of
-execution associated with `other` prior to the call, and vice-versa.]]
-[[Postconditions:] [`this->get_id()` returns the same value as `other.get_id()` prior to the call. `other.get_id()` returns the same
-value as `this->get_id()` prior to the call.]]
-[[Throws:] [Nothing.]]
-
-]
-
-[endsect]
-
-
-[section Member Function `get()|operator()()`]
-[/==========================================================================================]
-
- result_type get();
- result_type operator()();
-
-[variablelist
-[[Effects:] [Retrieves the value returned by the Nullary function.]]
-[[Sychronization:][The completion of the call to the operator()() the Nullary function happens before get() returns.]]
-[[Returns:] [If the result type R is a reference, returns the stored reference.
-If R is void, there is no return value.
-Otherwise, returns an rvalue-reference to the value stored in the asynchronous result.]]
-[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
-[[Postconditions:] [It is unspecified what happens when get() is called a second time on the same unique_joiner.]]
-[[Thread safety:][unsafe]]
-]
-[endsect]
-
-
-[section Member Function `is_ready()`]
-[/==========================================================================================]
-
- bool is_ready() const;
-
-[variablelist
-[[Returns:] [true only if the associated state holds a value or an exception ready for retrieval.]]
-[[Remark:] [the return value is unspecified after a call to get().]]
-]
-[endsect]
-
-[section Member Function `has_exception()`]
-[/==========================================================================================]
-
- bool has_exception() const;
-
-[variablelist
-[[Returns:] [true only if is_ready() == true and the associated state contains an exception.]]
-]
-[endsect]
-
-[section Member Function `has_value()`]
-[/==========================================================================================]
-
- bool has_value() const;
-
-[variablelist
-[[Returns:] [true only if is_ready() == true and the associated state contains a value.]]
-]
-[endsect]
-
-[section Member Function `wait()`]
-[/==========================================================================================]
-
- void wait();
-
-[variablelist
-[[Effects:] [Blocks until the Nullariry function ends.]]
-[[Sychronization:][The completion of the call to the operator()() the Nullary function happens before wait() returns.]]
-[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
-[[Postconditions:] [is_ready() == true.]]
-[[Thread safety:][unsafe]]
-]
-[endsect]
-
-[section Member Function `wait_until()|wait_for()`]
-[/==========================================================================================]
-
- bool wait_until(const system_time& abs_time);
- template<typename TimeDuration>
- bool wait_for(TimeDuration const& rel_time);
-
-
-[variablelist
-[[Effects:] [Blocks until the Nullariry function ends.]]
-[[Sychronization:][The completion of the call to the operator()() the Nullary function happens before wait() returns.]]
-[[Returns:] [If the result type R is a reference, returns the stored reference.
-If R is void, there is no return value.
-Otherwise, returns an rvalue-reference to the value stored in the asynchronous result.]]
-[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
-[[Postconditions:] [is_ready() == true.]]
-[[Thread safety:][unsafe]]
-]
-[endsect]
-
-
-
-[section:joinable Member function `joinable()`]
-[/==========================================================================================]
-
- bool joinable() const;
-
-[variablelist
-[[Returns:] [`true` if `*this` refers to a thread of execution, `false` otherwise.]]
-[[Throws:] [Nothing]]
-]
-
-[endsect]
-
-[section:join Member function `join()`]
-[/==========================================================================================]
-
- void join();
-
-[variablelist
-[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
-[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete.]]
-[[Postconditions:] [If `*this` refers to a thread of execution on entry, that thread of execution has completed. `*this` no longer refers to any thread of execution.]]
-[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]
-[[Notes:] [`join()` is one of the predefined __interruption_points__.]]
-]
-
-[endsect]
-
-[section Member function `join_until()|join_for()`]
-[/==========================================================================================]
-
- bool join_until(const system_time& wait_until);
-
- template<typename TimeDuration>
- bool join_for(TimeDuration const& rel_time);
-
-[variablelist
-[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
-[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete, the time `wait_until` has
-been reach or the specified duration `rel_time` has elapsed. If `*this` doesn't refer to a thread of execution, returns immediately.]]
-[[Returns:] [`true` if `*this` refers to a thread of execution on entry, and that thread of execution has completed before the call
-times out, `false` otherwise.]]
-[[Postconditions:] [If `*this` refers to a thread of execution on entry, and `timed_join` returns `true`, that thread of execution
-has completed, and `*this` no longer refers to any thread of execution. If this call to `timed_join` returns `false`, `*this` is
-unchanged.]]
-[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]
-[[Notes:] [`timed_join()` is one of the predefined __interruption_points__.]]
-]
-
-[endsect]
-
-[section:detach Member function `detach()`]
-[/==========================================================================================]
-
- void detach();
-
-[variablelist
-[[Effects:] [If `*this` refers to a thread of execution, that thread of execution becomes detached, and no longer has an associated __thread__ object.]]
-[[Postconditions:] [`*this` no longer refers to any thread of execution.]]
-[[Throws:] [Nothing]]
-]
-
-[endsect]
-
-
-[section:get_id Member function `get_id()`]
-[/==========================================================================================]
-
- thread::id get_id() const;
-
-[variablelist
-[[Returns:] [If `*this` refers to a thread of execution, an instance of __thread_id__ that represents that thread. Otherwise returns
-a default-constructed __thread_id__.]]
-[[Throws:] [Nothing]]
-]
-
-[endsect]
-
-[section:interrupt Member function `interrupt()`]
-[/==========================================================================================]
-
- void interrupt();
-
-[variablelist
-[[Effects:] [If `*this` refers to a thread of execution, request that the thread will be interrupted the next time it enters one of
-the predefined __interruption_points__ with interruption enabled, or if it is currently __blocked__ in a call to one of the
-predefined __interruption_points__ with interruption enabled .]]
-[[Throws:] [Nothing]]
-]
-
-
-[endsect]
-
-
-[section:nativehandle Member function `native_handle()`]
-[/==========================================================================================]
-
- typedef platform-specific-type native_handle_type;
- native_handle_type native_handle();
-
-[variablelist
-[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
-implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
-[[Throws:] [Nothing.]]
-]
-
-[endsect]
-
-
-
-[endsect]
-[section:non_member_swap Non-member function `swap()`]
-
- void swap(unique_joiner& lhs,unique_joiner& rhs);
-
-[variablelist
-
-[[Effects:] [[link thread.thread_management.thread.swap `lhs.swap(rhs)`].]]
-
-]
-
-[endsect]
-
-[/==================================================]
-[section Template Class `unique_threader`]
-[/==========================================================================================]
-
- class unique_threader {
- public:
- thread::native_handle_attr_type& attributes();
-
- template <typename T>
- struct handle {
- typedef unique_joiner<T> type;
- };
-
- template <typename F>
- unique_joiner<typename result_of<F()>::type>
- fork(F f);
-
- };
-
-[section Member function `unique_threader::attributes()`]
-[/==========================================================================================]
-
-Reference to the thread attributes accesor.
-
- thread::native_handle_attr_type& attributes();
-
-[variablelist
-[[Returns:] [A reference to the thread attributes.]]
-[[Complexity:] [constant.]]
-]
-
-
-[endsect]
-[section Metafunction `unique_threader::handle<>`]
-[/==========================================================================================]
-
-Metafunction that returns the result type of the fork function applied to a unique_threader and the value type.
-
- template <typename T>
- struct handle {
- typedef unique_joiner<T> type;
- };
-
-
-[variablelist
-[[Expression:] [L::handle<T>::type]]
-[[Return type:] [A unique_joiner<T>.]]
-[[Complexity:] [constant.]]
-
-]
-
-[endsect]
-
-[section Member function `unique_threader::fork`]
-[/==========================================================================================]
-
- template <typename F>
- unique_joiner<typename result_of<F()>::type>
- fork(F f);
-
-[variablelist
-[[Returns:] [A unique_joiner to the result of calling a function F.]]
-[[Effects:] [create a thread executing the function f.
- The result of the function will be stored on the resulting unique_joiner.]]
-
-]
-
-
-[endsect]
-
-[endsect]
-
-[/==================================================]
-[section Template Class `shared_joiner<>`]
-[/==========================================================================================]
-
-
-template <typename ResultType>
-class shared_joiner {
- typedef shared_joiner this_type;
-public:
- shared_joiner(const shared_joiner& rhs);
- shared_joiner& operator=(const shared_joiner& rhs);
-
- typedef ResultType result_type;
-
- template <typename Nullary>
- shared_joiner(thread::native_handle_attr_type& attr, Nullary f);
- template <typename Nullary>
- shared_joiner(Nullary f);
-
- shared_joiner(boost::detail::thread_move_t<shared_joiner> x);
- shared_joiner& operator=(boost::detail::thread_move_t<shared_joiner> x);
- operator boost::detail::thread_move_t<shared_joiner>();
- boost::detail::thread_move_t<shared_joiner> move();
-
- void swap(this_type& x);
-
- bool joinable() const;
- void join();
- bool join_until(const system_time& abs_time);
- template<typename TimeDuration>
- inline bool join_for(TimeDuration const& rel_time);
-
- result_type get();
- result_type operator()();
-
- bool is_ready() const;
- bool has_exception() const;
- bool has_value() const;
-
- void wait() const;
- bool wait_until(const system_time& abs_time) const;
- template<typename TimeDuration>
- inline bool wait_for(TimeDuration const& rel_time) const;
-
- thread::id get_id() const;
- void detach();
- void interrupt();
- bool interruption_requested() const;
-
- typedef platform-specific-type native_handle_type;
- native_handle_type native_handle();
-
- shared_future<result_type> get_future();
-};
-
-
-[section:destructor shared_joiner Destructor]
-[/==========================================================================================]
-
- ~shared_joiner();
-
-[variablelist
-[[Effects:] [If `*this` has an associated thread of execution, calls __detach__. Destroys `*this`.]]
-[[Throws:] [Nothing.]]
-]
-
-[endsect]
-
-[section:swap2 Member function `swap()`]
-
- void swap(shared_joiner& other);
-
-[variablelist
-[[Effects:] [Exchanges the threads of execution associated with `*this` and `other`, so `*this` is associated with the thread of
-execution associated with `other` prior to the call, and vice-versa.]]
-[[Postconditions:] [`this->get_id()` returns the same value as `other.get_id()` prior to the call. `other.get_id()` returns the same
-value as `this->get_id()` prior to the call.]]
-[[Throws:] [Nothing.]]
-
-]
-
-[endsect]
-
-
-[section Member Function `get()|operator()()`]
-[/==========================================================================================]
-
- result_type get();
- result_type operator()();
-
-[variablelist
-[[Effects:] [Retrieves the value returned by the Nullary function.]]
-[[Sychronization:][The completion of the call to the operator()() the Nullary function happens before get() returns.]]
-[[Returns:] [If the result type R is a reference, returns the stored reference.
-If R is void, there is no return value.
-Otherwise, returns an rvalue-reference to the value stored in the asynchronous result.]]
-[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
-[[Postconditions:] [It is unspecified what happens when get() is called a second time on the same shared_joiner.]]
-[[Thread safety:][unsafe]]
-]
-[endsect]
-
-
-[section Member Function `is_ready()`]
-[/==========================================================================================]
-
- bool is_ready() const;
-
-[variablelist
-[[Returns:] [true only if the associated state holds a value or an exception ready for retrieval.]]
-[[Remark:] [the return value is unspecified after a call to get().]]
-]
-[endsect]
-
-[section Member Function `has_exception()`]
-[/==========================================================================================]
-
- bool has_exception() const;
-
-[variablelist
-[[Returns:] [true only if is_ready() == true and the associated state contains an exception.]]
-]
-[endsect]
-
-[section Member Function `has_value()`]
-[/==========================================================================================]
-
- bool has_value() const;
-
-[variablelist
-[[Returns:] [true only if is_ready() == true and the associated state contains a value.]]
-]
-[endsect]
-
-[section Member Function `wait()`]
-[/==========================================================================================]
-
- void wait();
-
-[variablelist
-[[Effects:] [Blocks until the Nullariry function ends.]]
-[[Sychronization:][The completion of the call to the operator()() the Nullary function happens before wait() returns.]]
-[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
-[[Postconditions:] [is_ready() == true.]]
-[[Thread safety:][unsafe]]
-]
-[endsect]
-
-[section Member Function `wait_until()|wait_for()`]
-[/==========================================================================================]
-
- bool wait_until(const system_time& abs_time);
- template<typename TimeDuration>
- bool wait_for(TimeDuration const& rel_time);
-
-
-[variablelist
-[[Effects:] [Blocks until the Nullariry function ends.]]
-[[Sychronization:][The completion of the call to the operator()() the Nullary function happens before wait() returns.]]
-[[Returns:] [If the result type R is a reference, returns the stored reference.
-If R is void, there is no return value.
-Otherwise, returns an rvalue-reference to the value stored in the asynchronous result.]]
-[[Throws:] [the stored exception, if an exception was stored and not retrieved before.]]
-[[Postconditions:] [is_ready() == true.]]
-[[Thread safety:][unsafe]]
-]
-[endsect]
-
-
-
-[section:joinable2 Member function `joinable()`]
-[/==========================================================================================]
-
- bool joinable() const;
-
-[variablelist
-[[Returns:] [`true` if `*this` refers to a thread of execution, `false` otherwise.]]
-[[Throws:] [Nothing]]
-]
-
-[endsect]
-
-[section:join2 Member function `join()`]
-[/==========================================================================================]
-
- void join();
-
-[variablelist
-[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
-[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete.]]
-[[Postconditions:] [If `*this` refers to a thread of execution on entry, that thread of execution has completed. `*this` no longer refers to any thread of execution.]]
-[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]
-[[Notes:] [`join()` is one of the predefined __interruption_points__.]]
-]
-
-[endsect]
-
-[section Member function `join_until()|join_for()`]
-[/==========================================================================================]
-
- bool join_until(const system_time& wait_until);
-
- template<typename TimeDuration>
- bool join_for(TimeDuration const& rel_time);
-
-[variablelist
-[[Preconditions:] [`this->get_id()!=boost::this_thread::get_id()`]]
-[[Effects:] [If `*this` refers to a thread of execution, waits for that thread of execution to complete, the time `wait_until` has
-been reach or the specified duration `rel_time` has elapsed. If `*this` doesn't refer to a thread of execution, returns immediately.]]
-[[Returns:] [`true` if `*this` refers to a thread of execution on entry, and that thread of execution has completed before the call
-times out, `false` otherwise.]]
-[[Postconditions:] [If `*this` refers to a thread of execution on entry, and `timed_join` returns `true`, that thread of execution
-has completed, and `*this` no longer refers to any thread of execution. If this call to `timed_join` returns `false`, `*this` is
-unchanged.]]
-[[Throws:] [__thread_interrupted__ if the current thread of execution is interrupted.]]
-[[Notes:] [`timed_join()` is one of the predefined __interruption_points__.]]
-]
-
-[endsect]
-
-[section:detach3 Member function `detach()`]
-[/==========================================================================================]
-
- void detach();
-
-[variablelist
-[[Effects:] [If `*this` refers to a thread of execution, that thread of execution becomes detached, and no longer has an associated __thread__ object.]]
-[[Postconditions:] [`*this` no longer refers to any thread of execution.]]
-[[Throws:] [Nothing]]
-]
-
-[endsect]
-
-
-[section:get_id2 Member function `get_id()`]
-[/==========================================================================================]
-
- thread::id get_id() const;
-
-[variablelist
-[[Returns:] [If `*this` refers to a thread of execution, an instance of __thread_id__ that represents that thread. Otherwise returns
-a default-constructed __thread_id__.]]
-[[Throws:] [Nothing]]
-]
-
-[endsect]
-
-[section:interrupt2 Member function `interrupt()`]
-[/==========================================================================================]
-
- void interrupt();
-
-[variablelist
-[[Effects:] [If `*this` refers to a thread of execution, request that the thread will be interrupted the next time it enters one of
-the predefined __interruption_points__ with interruption enabled, or if it is currently __blocked__ in a call to one of the
-predefined __interruption_points__ with interruption enabled .]]
-[[Throws:] [Nothing]]
-]
-
-
-[endsect]
-
-
-[section:nativehandle2 Member function `native_handle()`]
-[/==========================================================================================]
-
- typedef platform-specific-type native_handle_type;
- native_handle_type native_handle();
-
-[variablelist
-[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
-implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
-[[Throws:] [Nothing.]]
-]
-
-[endsect]
-
-
-
-[endsect]
-[section:non_member_swap2 Non-member function `swap()`]
-
- void swap(shared_joiner& lhs,shared_joiner& rhs);
-
-[variablelist
-
-[[Effects:] [[link thread.thread_management.thread.swap `lhs.swap(rhs)`].]]
-
-]
-
-[endsect]
-
-[/==================================================]
-[section Template Class `shared_threader`]
-[/==========================================================================================]
-
- class shared_threader {
- public:
- thread::native_handle_attr_type& attributes();
-
- template <typename T>
- struct handle {
- typedef shared_joiner<T> type;
- };
-
- template <typename F>
- shared_joiner<typename result_of<F()>::type>
- fork(F f);
-
- };
-
-[section Member function `shared_threader::attributes()`]
-[/==========================================================================================]
-
-Reference to the thread attributes accesor.
-
- thread::native_handle_attr_type& attributes();
-
-[variablelist
-[[Returns:] [A reference to the thread attributes.]]
-[[Complexity:] [constant.]]
-]
-
-
-[endsect]
-[section Metafunction `shared_threader::handle<>`]
-[/==========================================================================================]
-
-Metafunction that returns the result type of the fork function applied to a shared_threader and the value type.
-
- template <typename T>
- struct handle {
- typedef shared_joiner<T> type;
- };
-
-
-[variablelist
-[[Expression:] [L::handle<T>::type]]
-[[Return type:] [A shared_joiner<T>.]]
-[[Complexity:] [constant.]]
-
-]
-
-[endsect]
-
-[section Member function `shared_threader::fork`]
-[/==========================================================================================]
-
- template <typename F>
- shared_joiner<typename result_of<F()>::type>
- fork(F f);
-
-[variablelist
-[[Returns:] [A shared_joiner to the result of calling a function F.]]
-[[Effects:] [create a thread executing the function f.
- The result of the function will be stored on the resulting shared_joiner.]]
-
-]
-
-
-[endsect]
-
-[endsect]
-
-[endsect]
-
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/typeof/future.hpp>`]
-[/==========================================================================================]
-
- BOOST_TYPEOF_REGISTER_TEMPLATE(boost::interthreads::unique_future, 1)
- BOOST_TYPEOF_REGISTER_TEMPLATE(boost::interthreads::shared_future, 1)
- BOOST_TYPEOF_REGISTER_TEMPLATE(boost::interthreads::promise, 1)
- BOOST_TYPEOF_REGISTER_TEMPLATE(boost::interthreads::packaged_task, 1)
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/typeof/launcher.hpp>`]
-[/==========================================================================================]
-
- BOOST_TYPEOF_REGISTER_TYPE(boost::interthreads::launcher)
- BOOST_TYPEOF_REGISTER_TYPE(boost::interthreads::shared_launcher)
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/typeof/threader.hpp>`]
-[/==========================================================================================]
-
- BOOST_TYPEOF_REGISTER_TYPE(boost::interthreads::unique_threader)
- BOOST_TYPEOF_REGISTER_TEMPLATE(boost::interthreads::unique_joiner, 1)
-
- BOOST_TYPEOF_REGISTER_TYPE(boost::interthreads::shared_threader)
- BOOST_TYPEOF_REGISTER_TEMPLATE(boost::interthreads::shared_joiner, 1)
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/typeof/basic_threader.hpp>`]
-[/==========================================================================================]
-
- BOOST_TYPEOF_REGISTER_TYPE(boost::interthreads::basic_threader)
-
-[endsect]
-
-[/==========================================================================================]
-[section Header `<boost/interthreads/typeof/scheduler.hpp>`]
-[/==========================================================================================]
-[endsect]
-
- BOOST_TYPEOF_REGISTER_TEMPLATE(boost::tp::task, 1)
-
-
-[/==========================================================================================]
-[section:decorator_thread_decoration_file Header `<boost/interthreads/thread_decoration.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- class thread_decoration;
- }
- }
-
-[/==================================================]
-[section:thread_decoration Class `thread_decoration`]
-[/==========================================================================================]
-
-`thread_decoration` defines a couple of setup/cleanup functions chained to the last constructed decoration, i.e. decorations are chained between them.
-
- class thread_decoration {
- public:
- template<typename Callable1>
- thread_decoration(Callable1 setup);
-
- template<typename Callable1,typename Callable2>
- thread_decoration(Callable1 setup, Callable2 cleanup);
-
- ~thread_decoration() {
- };
-
-[section:thread_decoration_class_constructor_setup Constructor with setup]
-[/==========================================================================================]
-
- template<typename Callable>
- thread_decoration(Callable func);
-
-[variablelist
-
-[[Requires:] [`Callable` is `CopyConstructible`. Copying `setup` shall have no side effects, and the effect of calling the copy shall
-be equivalent to calling the original. ]]
-
-[[Effects:] [`setup` is copied into storage managed internally by the library, and that copy is invoked by the
-__thread_decorator_decorate__ function.]]
-
-[[Postconditions:] [`*this` refers to a decoration.]]
-
-[[Throws:] [Nothing]]
-
-[[Thread safety:][unsafe]]
-
-]
-
-[note The library do not ensures any order of decorations.]
-
-[endsect]
-
-[section Constructor with setup & cleanup]
-[/==========================================================================================]
-
- template<typename Callable1,typename Callable2>
- thread_decoration(Callable1 setup, Callable2 cleanup);
-
-
-[variablelist
-
-[[Requires:] [`Callable1` & `Callable1` are `CopyConstructible`. Copying `setup` or `cleanup` shall have no side effects, and the effect of calling the copy shall
-be equivalent to calling the original. ]]
-
-[[Effects:] [`setup` and `cleanup` are copied into storage managed internally by the library, and the `setup` copy is invoked by the
-__thread_decorator_decorate__ function. If successful the cleanup function is registered to the to the thread exit handler.]]
-
-[[Postconditions:] [`*this` refers to a decoration.]]
-
-[[Throws:] [Nothing]]
-
-[[Thread safety:][unsafe]]
-
-]
-
-[note The library do not ensures any order of setup decorations neither of cleanup decorations.]
-
-[endsect]
-[endsect]
-
-[endsect]
-
-
-
-[/==========================================================================================]
-[section:decorator_thread_decorator_file Header `<boost/interthreads/thread_decorator.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- class thread_decorator;
- void decorate();
- }
- }
-
-
-[section:thread_decorator Class `thread_decorator`]
-[/==========================================================================================]
-
-`thread_decorator` is a functor wrapping a function with the setup and the cleanup of chained decorations which will be called only once by thread:
-decoration's setup are called before the thread function and decoration's cleanup at thread exit.
-
- class thread_decorator {
- public:
-
- template <class Callable>
- explicit thread_decorator(Callable&& f);
- template <class Callable>
- explicit thread_decorator(detail::thread_move_t<Callable> f):
- template<typename Callable>
- thread_decorator(Callable f,
- typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >
- , detail::dummy* >::type=0);
-
- template <typename Callable, typename A1, typename A2, ...>
- thread_decorator(Callable f, A1 a1, A2 a2, ...)
-
- thread_decorator(thread_decorator&& other);
-
- thread_decorator& operator=(thread_decorator&& other);
-
- thread_decorator&& move();
-
- void swap(thread_decorator& x);
-
- void operator ()();
-
- };
-
-Functor wrapping the user function thread to ensure that all the decorations are called.
-
-Objects of type `thread_decorator` are movable, so they can be stored in move-aware containers, and returned from functions.
-This allows the details of thread decoration to be wrapped in a function.
-
-thread_decorator make_decorator();
-
-void f()
-{
- boot::thread some_thread(make_decorator());
- some_thread.join();
-}
-
-[note On compilers that support rvalue references, `thread_decorator` provides a proper move constructor and move-assignment operator,
-and therefore meets the C++0x `MoveConstructible` and `MoveAssignable` concepts. With such compilers, `thread_decorator` can therefore
-be used with containers that support those concepts.
-
-For other compilers, move support is provided with a move emulation layer, so containers must explicitly detect that move emulation
-layer. See `<boost/thread/detail/move.hpp>` for details.]
-
-[section:decorator_thread_decoration_decorate_constructor Constructor]
-[/==========================================================================================]
-
- template <class Callable>
- thread_decorator(Callable&& func);
- template<typename Callable>
- thread_decorator(Callable func);
-
-[variablelist
-
-[[Template parameters:] [`Callable` must by `CopyConstructible`.]]
-
-[[Effects:] [`func` is copied into storage managed internally by the library, and that copy will be invoked after the operator() function when the decorate is used as Callable of a newly-created
-thread of execution.]]
-
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-
-[[Thread safety:][safe]]
-
-]
-
-[endsect]
-
-[section:decorator_thread_decoration_decorate_constructorn Constructor]
-[/==========================================================================================]
-
- template <typename Callable, typename A1, typename A2, ...>
- thread_decorator(Callable func, A1 a1, A2 a2, ...)
-
-[variablelist
-
-[[Template parameters:] [`Callable` must by `CopyConstructible`.]]
-
-[[Effects:] [`func` is copied into storage managed internally by the library, and that copy will be invoked after the operator() function when the decorate is used as Callable of a newly-created
-thread of execution.]]
-
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-
-[[Thread safety:][safe]]
-
-]
-
-[endsect]
-
-[section:decorator_thread_decoration_decorate_copy_move_constructor Copy Move Constructor]
-[/==========================================================================================]
-
- thread_decorator(thread_decorator&& other);
- thread_decorator(detail::thread_move_t<thread_decorator> other) {
-
-[variablelist
-
-[[Template parameters:] [`Callable` must by `CopyConstructible`.]]
-
-[[Effects:] [`func` is copied into storage managed internally by the library, and that copy will be invoked after the operator() function when the decorate is used as Callable of a newly-created
-thread of execution.]]
-
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-
-[[Thread safety:][safe]]
-
-]
-
-[endsect]
-
-
-[section:decorator_thread_decoration_decorate_copy_constructor Assign Move Constructor]
-[/==========================================================================================]
-
- thread_decorator& operator=(thread_decorator&& other);
- thread_decorator& operator=(detail::thread_move_t<thread_decorator> x) {
-
-
-[variablelist
-
-[[Requires:] [`Callable` must by `CopyConstructible`.]]
-
-
-[[Effects:] [`func` is copied into storage managed internally by the library, and that copy will be invoked after the operator() function when the decorate is used as Callable of a newly-created
-thread of execution.]]
-
-[[Returns:] [a reference to `*this`.]]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][neutral]]
-
-]
-
-[endsect]
-
-[section:decorator_thread_decoration_conversion Member Function `operator detail::thread_move_t<thread_decorator>()`]
-[/==========================================================================================]
-
- operator detail::thread_move_t<thread_decorator>();
-
-
-[variablelist
-
-[[Effects:] [helper for move semantics emulation.]]
-
-[[Returns:] [the move form `*this`.]]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][neutral]]
-
-]
-
-[endsect]
-
-[section:decorator_thread_decoration_move Member Function `move()`]
-[/==========================================================================================]
-
- detail::thread_move_t<thread_decorator> move() {
- thread_decorator&& move();
-
-
-[variablelist
-
-[[Effects:] [Move *this to the caller.]]
-
-[[Returns:] [the move form `*this`.]]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][neutral]]
-
-]
-
-[endsect]
-
-[section:decorator_thread_decoration_swap Member Function `swap()`]
-[/==========================================================================================]
-
- void swap(thread_decorator& x);
-
-
-[variablelist
-
-[[Effects:] []]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][neutral]]
-
-]
-
-[endsect]
-
-[section:decorator_thread_decoration_operator_f Member Function `operator()()`]
-[/==========================================================================================]
-
- void operator()();
-
-
-[variablelist
-
-[[Effects:] [Functor operator]]
-
-[[Throws:] [Any exception thrown by the decorations or the user function.]]
-
-[[Thread safety:][unsafe - depends on the decorations constructio/destruction.]]
-
-]
-
-[endsect]
-[endsect]
-
-[section:decorate Non Member Function `decorate()`]
-[/==========================================================================================]
-
- void decorate();
-
-
-[variablelist
-
-[[Requires:] [`Callable` is `CopyConstructible`. Copying `f` shall have no side effects, and the effect of calling the copy shall
-be equivalent to calling the original. ]]
-
-[[Effects:] [Calls every declared decoration using the thread_decoration class.
-]]
-
-[[Postconditions:] [All the decorations have been called.]]
-
-[[Throws:] [Any exception thrown by the decorations.]]
-
-[[Thread safety:][unsafe - depends on the decorations constructio/destruction.]]
-
-]
-
-[endsect]
-
-
-[endsect]
-
-
-[section:thread_specific_shared_ptr_reference_Header Header `<boost/interthreads/thread_specific_shared_ptr.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <typename T>
- class thread_specific_shared_ptr;
-
- }
- }
-
-
-[section:thread_specific_shared_ptr_reference_thread_specific_shared_ptr Template Class `thread_specific_shared_ptr<>`]
-[/==========================================================================================]
-
-`bith::thread_specific_shared_ptr<>` is an extension of the thread_specific_ptr providing access
-to this thread specific context from other threads.
-
- template <typename T>
- class thread_specific_shared_ptr : private noncopyable
- {
- public:
- typedef shared_ptr<T> shared_ptr_type;
- typedef 'implementation defined' map_type;
- typedef 'implementation defined' mutex_type;
- typedef 'implementation defined' lock_type;
-
- thread_specific_shared_ptr();
- explicit thread_specific_shared_ptr(void (*cleanup_)(shared_ptr_type));
- ~thread_specific_shared_ptr();
-
- T* get() const;
- T* operator->() const;
- T& operator*() const;
- void reset();
- template<class Y>
- void reset(Y * p);
- template<class Y, class D>
- void reset(Y * p, D d);
- template<class Y, class D, class A>
- void reset(Y * p, D d, A a);
-
- mutex_type& get_mutex();
- const map_type& get_map(lock_type&) const;
- shared_ptr_type operator[](thread::id id) const;
- shared_ptr_type wait_and_get(thread::id id) const;
- private:
- shared_ptr_type get_shared_ptr() const;
- };
-
-[section:thread_specific_shared_ptr_reference_parameters Template parameters]
-[/==========================================================================================]
-
-`thread_specific_shared_ptr<>` is instantiated with the following types:
-
-* T The type of the pointeed object
-
-[endsect]
-
-[section:thread_specific_shared_ptr_reference_types Public types]
-[/==========================================================================================]
-
-`thread_specific_shared_ptr<>` defines the following types:
-
-* [*`shared_ptr_type`] The shared pointed type.
-* [*`map_type`] The mapping type from `thread::id` to `shared_ptr_type`
-* [*`mutex_type`] The protecting mutext type follwing the Lockable Concept
-* [*`lock_type`] The lock used to get the map follwing the unique_lock subjacent Concept
-
-[endsect]
-
-[section:thread_specific_shared_ptr_default_constructor Constructor]
-[/==========================================================================================]
-
- thread_specific_shared_ptr();
-
-[variablelist
-
-[[Effects:] [Construct a `thread_specific_shared_ptr<>` object for storing a pointer to an object of type `T` specific to each thread.]]
-
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-
-[[Thread safety:][safe.]]
-
-]
-
-[endsect]
-
-[section:thread_specific_shared_ptr_constructor_with_custom_cleanup Cleanup Constructor]
-[/==========================================================================================]
-
- explicit thread_specific_shared_ptr(void (*cleanup_)(shared_ptr_type));
-
-[variablelist
-
-[[Requires:] [`cleanup_function(this->get())` does not throw any exceptions.]]
-
-[[Effects:] [Construct a `thread_specific_shared_ptr<>` object for storing a pointer to an object of type `T` specific to each thread. The
-supplied `cleanup_function` will be called at thread exit.]]
-
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-
-[[Thread safety:][safe.]]
-
-]
-
-[endsect]
-
-[section:thread_specific_shared_ptr_destructor Destructor]
-[/==========================================================================================]
-
- ~thread_specific_shared_ptr();
-
-[variablelist
-
-[[Effects:] [Remove from the map the current thread::id and destroys `*this`.]]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][safe.]]
-
-]
-
-[note Care needs to be taken to ensure that any threads still running after an instance of `boost::thread_specific_shared_ptr<>` has been
-destroyed do not call any member functions on that instance. Is for this raison that usualy instance of this class are static.]
-
-[endsect]
-
-
-[section:thread_specific_shared_ptr_get Member Function `get()`]
-[/==========================================================================================]
-
- shared_ptr_type get() const;
-
-[variablelist
-
-[[Returns:] [The pointer associated with the current thread.]]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][safe.]]
-
-]
-
-[note The initial value associated with an instance of `boost::thread_specific_shared_ptr<>` is `NULL` for each thread.]
-
-[endsect]
-
-[section:thread_specific_shared_ptr_operator_arrow Member Function `operator->()`]
-[/==========================================================================================]
-
- T* operator->() const;
-
-[variablelist
-
-[[Requires:] [`this->get()` is not `NULL`.]]
-
-[[Returns:] [`this->get()`]]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][safe.]]
-
-]
-
-[endsect]
-
-[section:thread_specific_shared_ptr_operator_star Member Function `operator*()`]
-[/==========================================================================================]
-
- T& operator*() const;
-
-[variablelist
-
-[[Requires:] [`this->get()` is not `NULL`.]]
-
-[[Returns:] [`*(this->get())`]]
-
-[[Throws:] [Nothing.]]
-
-[[Thread safety:][safe.]]
-
-]
-
-[endsect]
-
-[section:thread_specific_shared_ptr_reset Member Function `reset()`]
-[/==========================================================================================]
-
- void reset();
-
-[variablelist
-[[Effects:] [Equivalent to `shared_ptr().swap(this->get_shared_ptr())`. Update the mapping.]]
-[[Postcondition:] [`this->get()==0`]]
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-[[Thread safety:][safe.]]
-
-]
-
- template<class Y> void reset(Y * new_value);
-
-[variablelist
-[[Effects:] [Equivalent to `shared_ptr(new_value).swap(this->get_shared_ptr())`. Update the mapping.]]
-[[Postcondition:] [`this->get()==new_value`]]
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-[[Thread safety:][safe.]]
-]
-
- template<class Y, class D> void reset(Y * new_value, D deleter);
-
-[variablelist
-[[Effects:] [Equivalent to `shared_ptr(new_value, deleter).swap(this->get_shared_ptr())`. Update the mapping.]]
-[[Postcondition:] [`this->get()==new_value`]]
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-[[Thread safety:][safe.]]
-]
-
- template<class Y, class D, class A> void reset(Y * new_value, D deleter, A a);
-
-[variablelist
-[[Effects:] [Equivalent to `shared_ptr(new_value, deleter, a).swap(this->get_shared_ptr())`. Update the mapping.]]
-[[Postcondition:] [`this->get()==new_value`]]
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-[[Thread safety:][safe.]]
-]
-
-[variablelist
-
-[[Effects:] [If `this->get()!=new_value` and `this->get()` is non-`NULL`, invoke `delete this->get()` or
-`deleter(this->get())` as appropriate. Store `new_value` as the pointer associated with the current thread.]]
-
-[[Throws:] [`std::bad_alloc` when resources unavailable.]]
-
-]
-
-[endsect]
-
-[section:thread_specific_shared_ptr_wait_and_get Member Function `wait_and_get()`]
-[/==========================================================================================]
-
- shared_ptr_type wait_and_get(thread::id id) const;
-
-[variablelist
-
-[[Effects:] [Waits until the specific shared pointer has been set and returns a shared pointer to this context.]]
-
-[[Throws:] [`boost::thread_interrupted` if the current thread of execution is interrupted.]]
-
-]
-
-[endsect]
-
-[section:thread_specific_shared_ptr_operatora Member Function `operator[]()`]
-[/==========================================================================================]
-
- shared_ptr_type operator[](thread::id id) const;
-
-[variablelist
-
-[[Effects:] [Returns a copy of the specific shared_ptr of the thread of execution identified by the `thread::id`.]]
-
-[[Throws:] [Nothing.]]
-
-]
-
-[endsect]
-
-
-[section:get_mutex Member Function `get_mutex()`]
-[/==========================================================================================]
-
- mutex_type& get_mutex();
-
-[variablelist
-
-[[Effects:] [Returns a reference to the protection mutex.]]
-
-[[Throws:] [Nothing.]]
-
-]
-
-[endsect]
-
-[section:get_map Member Function `get_map()`]
-[/==========================================================================================]
-
- const map_type& get_map(lock_type&) const;
-
-[variablelist
-
-[[Effects:] [Returns a reference to the mapping from `thread::id` to the specific pointers provided the user gives a lock on the motext get using `get_mutex()`.]]
-
-[[Throws:] [Nothing.]]
-
-]
-[endsect]
-
-
-
-
-[endsect]
-
-[endsect]
-
-[section:keep_alive_file Header `<boost/interthreads/thread_keep_alive.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- namespace this_thread {
- class enable_keep_alive;
- class disable_keep_alive;
-
- void keep_alive_check_point();
- bool keep_alive_enabled();
- typedef void (*on_dead_thread_type)(thread::id);
- void set_on_dead_thread(on_dead_thread_type fct);
- }
- }
- }
-
-[section:keep_alive_enable_keep_alive class `enable_keep_alive`]
-[/==========================================================================================]
-
- class enable_keep_alive : private noncopyable{
- public:
- enable_keep_alive(std::size_t threshold=2, std::size_t tap=1);
- ~enable_keep_alive();
- };
-
-[section:keep_alive_enable_keep_alive_Constructor Constructor]
-[/==========================================================================================]
-
- enable_keep_alive(std::size_t threshold=2, std::size_t tap=1);
-
-[variablelist
-
-[[Effects:] [Enable the keep alive mechanism on this thread of execution.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[section:keep_alive_enable_keep_alive_Destructor Destructor]
-[/==========================================================================================]
-
- ~enable_keep_alive();
-
-[variablelist
-
-[[Effects:] [Restore the keep alive mechanism as it was before the constructor.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-[endsect]
-
-[section:keep_alive_disable_keep_alive class `disable_keep_alive`]
-[/==========================================================================================]
-
- class disable_keep_alive private noncopyable {
- public:
- disable_keep_alive();
- ~disable_keep_alive();
- };
-
-[section:keep_alive_disable_keep_alive_Constructor Constructor]
-[/==========================================================================================]
-
- disable_keep_alive();
-
-[variablelist
-
-[[Effects:] [Disable the keep alive mechanism on this thread of execution.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[section:keep_alive_disable_keep_alive_Destructor Destructor]
-[/==========================================================================================]
-
- ~disable_keep_alive();
-
-[variablelist
-
-[[Effects:] [Restore the keep alive mechanism as it was before the constructor.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-[endsect]
-
-[section:keep_alive_keep_alive_check_point Non Member Function `keep_alive_check_point()`]
-[/==========================================================================================]
-
- void keep_alive_check_point();
-
-[variablelist
-
-[[Effects:] [States that the current thread is alive.]]
-[[Postconditions:] [The thread is alive.]]
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[section:keep_alive_keep_alive_enabled Non Member Function `keep_alive_enabled()`]
-[/==========================================================================================]
-
- bool keep_alive_enabled();
-
-[variablelist
-
-[[Effects:] [States if the keep alive mechanism is enabled on this thread.]]
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[section:keep_alive_keep_alive_set_on_dead_thread Non Member Function `set_on_dead_thread()`]
-[/==========================================================================================]
-
- void set_on_dead_thread(on_dead_thread_type fct);
-
-[variablelist
-
-[[Effects:] [Modifies the action to be done when a this thread is declared dead.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[endsect]
-
-[section:thread_tuple_thread_tuple_hpp Header `<boost/interthreads/thread_tuple.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <std::size_t N>
- class thread_tuple;
-
- template<typename F0, ..., typename Fn-1>
- thread_tuple<n> make_thread_tuple(F0 f0, ..., Fn fn-1);
-
- }
- }
-
-
-[section:thread_tuple_class Template Class `thread_tuple<>`]
-[/==========================================================================================]
-
-`thread_tuple<>` defines a thread groupe where the number of threads is know statically and the threads are
-created at construction time.
-
- template <std::size_t n>
- class thread_tuple {
- public:
- template<typename F0, ..., typename Fn-1>
- thread_tuple(F0 f0, ..., Fn-1 fn-1);
-
- template <class F>
- thread_tuple(boost::move_t<F> f);
- ~thread_tuple();
-
- // move support
- thread_tuple(boost::move_t<thread_tuple<n>> x);
- thread_tuple& operator=(boost::move_t<thread_tuple<n>> x);
- operator boost::move_t<thread_tuple<n>>();
- boost::move_t<thread_tuple<n>> move();
-
- void swap(thread_tuple<n>& x);
-
- bool joinable() const;
- void join_all();
- bool join_all_until(const system_time& wait_until);
- template<typename TimeDuration>
- bool join_all_for(TimeDuration const& rel_time);
-
- void detach();
- void detach_all();
-
- void interrupt();
- void interrupt_all();
- bool interruption_requested() const;
-
- size_t size();
-
- const thread& operator[](std::size_t i);
- };
- }
- }
-
-
-The __thread_tuple__ class is responsible for launching and managing a static collection of threads that are related in some fashion.
-No new threads can be added to the tuple once constructed.
-
-[section Template parameters]
-[/==========================================================================================]
-
-`thread_tuple<>` is instantiated with the following value:
-
-* n is the size of the tuple.
-
-[endsect]
-
-[section:thread_tuple_callable_constructor Constructor]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- thread_tuple(F0 func_0, ..., Fn-1 func_n-1);
-
-[variablelist
-
-[[Preconditions:] [`Fk` must by copyable.]]
-
-[[Effects:] [`func_k` is copied into storage managed internally by the library, and that copy is invoked on a newly-created
-thread of execution. If this invocation results in an exception being propagated into the internals of the library that is
-not of type __thread_interrupted__, then `std::terminate()` will be called.]]
-
-[[Postconditions:] [`*this` refers to the newly created tuple of threads of execution.]]
-
-[[Throws:] [__thread_resource_error__ if an error occurs.]]
-
-[[Note:] [Currently up to ten arguments `func_0` to `funct_9` can be specified.]]
-
-]
-
-[endsect]
-
-
-[section:thread_tuple_destructor Destructor]
-[/==========================================================================================]
-
- ~thread_tuple();
-
-[variablelist
-
-[[Effects:] [If *this have associateds thread of execution, calls detach() on them. Destroys *this.]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_joinable Member function `joinable()`]
-[/==========================================================================================]
-
- bool joinable() const;
-
-[variablelist
-
-[[Returns:] [`true` if `*this` refers to threads of execution, `false` otherwise.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_join Member function `join_all()`]
-[/==========================================================================================]
-
- void join();
- void join_all();
-
-[variablelist
-
-[[Effects:] [Call `join()` on each __thread__ object in the tuple.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::join` is one of the predefined interruption points, `thread_tuple<>::join_all()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section Member function `join_all_until()`]
-[/==========================================================================================]
-
- bool join_all_until(const system_time& wait_until);
-
-[variablelist
-
-[[Effects:] [Call `timed_join()` on each __thread__ object in the tuple.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Returns:] [true if joined.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::timed_join` is one of the predefined interruption points, `thread_tuple<>::join_all_until()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section Member function `join_all_for()`]
-[/==========================================================================================]
-
- template<typename TimeDuration>
- bool join_for(TimeDuration const& rel_time);
-
-[variablelist
-
-[[Effects:] [As `join_all_until(now()+rel_time)`.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Returns:] [true if joined.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::timed_join` is one of the predefined interruption points, `thread_tuple<>::join_all_for()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section:join_first_then_interrupt Member function `join_any()`]
-[/==========================================================================================]
-
- std::size_t conc_join_any();
-
-[variablelist
-
-[[Effects:] [Call `join_any()` on a temporary thread_tuple and the `interrup_all()`.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `join_any()` is one of the predefined interruption points, `conc_join_any()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section Member function `join_any_until()`]
-[/==========================================================================================]
-
- std::pair<bool,std::size_t> conc_join_any_until(
- const system_time& wait_until);
- template<typename TimeDuration>
- std::pair<bool,std::size_t> join_any_for(
- TimeDuration const& rel_time);
-
-[variablelist
-
-[[Effects:] [Call `join_any_until()` on a temporary thread_tuple and the `interrup_all()`.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Returns:] [true if joined.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `join_any_until()` is one of the predefined interruption points, `conc_join_any_until()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section:detach_all Member function `detach_all()`]
-[/==========================================================================================]
-
- void detach_all();
-
-[variablelist
-
-[[Effects:] [Call `detach()` on each __thread__ object in the tuple.]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_interrupt_all Member function `interrupt_all()`]
-[/==========================================================================================]
-
- void interrupt_all();
-
-[variablelist
-
-[[Effects:] [Call `thread::interrupt()` on each __thread__ object in the tuple.]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_size Member function `size()`]
-[/==========================================================================================]
-
- int size();
-
-[variablelist
-
-[[Returns:] [The number of threads in the tuple.]]
-
-[[Throws:] [Nothing.]]
-
-]
-
-[endsect]
-
-[endsect]
-
-[section:thread_tuple_make_thread_tuple Non Member Function `make_thread_tuple()`]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- thread_tuple make_thread_tuple(F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [makes a new thread_tuple<>.]]
-[[Returns:] [the created thread tuple.]]
-
-
-]
-
-[endsect]
-
-[endsect]
-
-[section:set_once_hpp Header `<boost/interthreads/set_once.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
- template <typename T>
- class set_once;
- }
- }
-
-
-[section:set_onceclass Template Class `set_once<>`]
-[/==========================================================================================]
-
-`set_once_once<>` is a synchonizer that allows to set a variable only once, notifying
-to the variable value to whatever is waiting for that.
-
-
- template <typename T>
- class set_once {
- public:
- typedef T value_type;
-
- set_once();
- void wait();
- bool wait_until(const system_time& abs_time);
- template<typename TimeDuration>
- bool wait_for(const TimeDuration& rel_time);
-
- value_type get();
- std::pair<bool,value_type> get_until(const system_time& abs_time);
- template<typename TimeDuration>
- std::pair<bool,value_type> get_for(const TimeDuration& rel_time);
-
- bool set_if_unassigned(value_type id);
-
- template<typename F>
- static void decorator(this_type& once, T value, F fct);
- template<typename F>
- static boost::detail::thread_move_t<thread> make_thread(this_type& once, T value, F fct);
- };
-
-[endsect]
-
-[endsect]
-
-[section:thread_tuple_once_hpp Header `<boost/interthreads/thread_tuple_once.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <std::size_t N>
- class thread_tuple_once;
-
- template<typename F0, ..., typename Fn-1>
- thread_tuple make_thread_tuple_once(F0 f0, ..., Fn fn-1);
-
- }
- }
-
-
-[section:thread_tuple_once_class Template Class `thread_tuple_once<>`]
-[/==========================================================================================]
-
-`biththread_tuple_once` is an extension of the `bith::thread_tuple` which allows to join the thread finishing
-the first, using for that the `bith::set_once` synchronizer.
-
- template <std::size_t n>
- class thread_tuple_once {
- public:
- template<typename F0, ..., typename Fn-1>
- thread_tuple_once(F0 f0, ..., Fn-1 fn-1);
-
- template <class F>
- thread_tuple_once(boost::move_t<F> f);
- ~thread_tuple_once();
-
- // move support
- thread_tuple_once(boost::move_t<thread_tuple_once<n>> x);
- thread_tuple_once& operator=(boost::move_t<thread_tuple_once<n>> x);
- operator boost::move_t<thread_tuple_once<n>>();
- boost::move_t<thread_tuple_once<n>> move();
-
- void swap(thread_tuple_once<n>& x);
-
- bool joinables() const;
- void join_all();
- bool join_all_until(const system_time& wait_until);
- template<typename TimeDuration>
- bool join_all_for(TimeDuration const& rel_time);
-
- std::size_t join_any();
- std::pair<bool,std::size_t> join_any_until(
- const system_time& wait_until);
- template<typename TimeDuration>
- std::pair<bool,std::size_t> join_any_for(
- TimeDuration const& rel_time);
-
- void detach_all();
-
- void interrupt_all();
- bool interruption_requested() const;
-
- size_t size();
-
- const thread& operator[](std::size_t i);
- };
- }
- }
-
-
-The __thread_tuple_once__ class is responsible for launching and managing a static collection of threads that are related in some fashion.
-No new threads can be added to the tuple once constructed.
-
-[section Template parameters]
-[/==========================================================================================]
-
-`thread_tuple_once<>` is instantiated with the following value:
-
-* n is the size of the tuple.
-
-[endsect]
-
-[section:thread_tuple_once_callable_constructor Constructor]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- thread_tuple_once(F0 func_0, ..., Fn-1 func_n-1);
-
-[variablelist
-
-[[Preconditions:] [`Fk` must by copyable.]]
-
-[[Effects:] [`func_k` is copied into storage managed internally by the library, and that copy is invoked on a newly-created
-thread of execution. If this invocation results in an exception being propagated into the internals of the library that is
-not of type __thread_interrupted__, then `std::terminate()` will be called.]]
-
-[[Postconditions:] [`*this` refers to the newly created tuple of threads of execution.]]
-
-[[Throws:] [__thread_resource_error__ if an error occurs.]]
-
-[[Note:] [Currently up to ten arguments `func_0` to `funct_9` can be specified.]]
-
-]
-
-[endsect]
+[section Thread Extensions Reference]
+[include reference/thread_decoration.qbk]
+[include reference/thread_decorator.qbk]
+[include reference/thread_specific_shared_ptr.qbk]
-[section:thread_tuple_once_destructor Destructor]
-[/==========================================================================================]
-
- ~thread_tuple_once();
-
-[variablelist
-
-[[Effects:] [If *this have associateds thread of execution, calls detach() on them. Destroys *this.]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_once_joinable Member function `joinables()`]
-[/==========================================================================================]
-
- bool joinables() const;
-
-[variablelist
-
-[[Returns:] [`true` if `*this` refers to threads of execution, `false` otherwise.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_once_join Member function `join_all()`]
-[/==========================================================================================]
-
- void join_all();
-
-[variablelist
-
-[[Effects:] [Call `join()` on each __thread__ object in the tuple.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::join` is one of the predefined interruption points, `thread_tuple_once<>::join_all()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section Member function `join_all_until()`]
-[/==========================================================================================]
-
- bool join_all_until(const system_time& wait_until);
- template<typename TimeDuration>
- bool join_all_for(TimeDuration const& rel_time);
-
-[variablelist
-
-[[Effects:] [Call `timed_join()` on each __thread__ object in the tuple.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Returns:] [true if joined.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::timed_join` is one of the predefined interruption points, `thread_tuple_once<>::timed_join_all()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section Member function `join_any()`]
-[/==========================================================================================]
-
- std::size_t join_any();
-
-[variablelist
-
-[[Effects:] [Call `join_first()` and the `interrup_all()`.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::join` is one of the predefined interruption points, `thread_tuple_once<>::join_all()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section:timed_join_first_then_interrupt Member function `timed_join_first_then_interrupt()`]
-[/==========================================================================================]
-
- std::pair<bool,std::size_t> timed_join_first_then_interrupt(
- const system_time& wait_until);
- template<typename TimeDuration>
- std::pair<bool,std::size_t> timed_join_first_then_interrupt(
- TimeDuration const& rel_time);
-
-[variablelist
-
-[[Effects:] [Call `timed_join_first()` and the `interrup_all()`.]]
-
-[[Postcondition:] [Every thread in the tuple has terminated.]]
-
-[[Returns:] [true if joined.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::timed_join` is one of the predefined interruption points, `thread_tuple_once<>::timed_join_all()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section:detach_all Member function `detach_all()`]
-[/==========================================================================================]
-
- void detach_all();
-
-[variablelist
-
-[[Effects:] [Call `detach()` on each __thread__ object in the tuple.]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_once_interrupt_all Member function `interrupt_all()`]
-[/==========================================================================================]
-
- void interrupt_all();
-
-[variablelist
-
-[[Effects:] [Call `thread::interrupt()` on each __thread__ object in the tuple.]]
-
-]
-
-[endsect]
-
-[section:thread_tuple_once_size Member function `size()`]
-[/==========================================================================================]
-
- int size();
-
-[variablelist
-
-[[Returns:] [The number of threads in the tuple.]]
-
-[[Throws:] [Nothing.]]
-
-]
-
-[endsect]
-
-[endsect]
-
-[section:thread_tuple_once_make_thread_tuple_once Non Member Function `make_thread_tuple_once()`]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- thread_tuple_once make_thread_tuple_once(F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [makes a new thread_tuple_once<>.]]
-[[Returns:] [the created thread tuple.]]
-
-
-]
-
-[endsect]
-
-[endsect]
-
-
-[section:thread_and_join_hpp Header `<boost/interthreads/thread_and_join.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template<typename F0, ..., typename Fn-1>
- void conc_join_all(F0 f0, ..., Fn fn-1);
- template<typename F0, ..., typename Fn-1>
- bool conc_join_all_until(const system_time& wait_until, F0 f0, ..., Fn fn-1);
- template<typename TimeDuration, typename F0, ..., typename Fn-1>
- bool conc_join_all_for(TimeDuration wait_for, F0 f0, ..., Fn fn-1);
-
- template<typename F0, ..., typename Fn-1>
- std::size_t conc_join_any(F0 f0, ..., Fn fn-1);
- template<typename F0, ..., typename Fn-1>
- std::pair<bool,std::size_t> conc_join_any_until(
- const system_time& wait_until, F0 f0, ..., Fn fn-1);
- template<typename TimeDuration, typename F0, ..., typename Fn-1>
- std::pair<bool,std::size_t> conc_join_all_for(
- TimeDuration wait_for, F0 f0, ..., Fn fn-1);
- }
- }
-
-
-
-[section:conc_join_all Non Member Function `conc_join_all()`]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- void conc_join_all(F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [launch in each function on a thread of execution and join all.]]
-
-]
-
-[endsect]
-
-[section:conc_join_all_until Non Member Function `conc_join_all_until()`]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- bool conc_join_all_until(const system_time& wait_until, F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [launch each function on a thread of execution and join all until a given time or duration if not interrup all.]]
-[[Returns:] [true if joined.]]
-
-]
-
-[endsect]
-
-[section:conc_join_all_for Non Member Function `conc_join_all_for()`]
-[/==========================================================================================]
-
- template<typename TimeDuration, typename F0, ..., typename Fn-1>
- bool conc_join_all_for(TimeDuration wait_for, F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [launch each function on a thread of execution and join all until a given time or duration if not interrup all.]]
-[[Returns:] [true if joined.]]
-
-]
-
-[endsect]
-
- template<typename F0, ..., typename Fn-1>
- std::size_t conc_join_any(F0 f0, ..., Fn fn-1);
- template<typename F0, ..., typename Fn-1>
- std::pair<bool,std::size_t> conc_join_any_until(
- const system_time& wait_until, F0 f0, ..., Fn fn-1);
- template<typename TimeDuration, typename F0, ..., typename Fn-1>
- std::pair<bool,std::size_t> conc_join_all_for(
- TimeDuration wait_for, F0 f0, ..., Fn fn-1);
-
-[section:conc_join_any Non Member Function `conc_join_any()`]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- std::size_t conc_join_any(F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [launch in each function on a thread of execution, join the first and then interrupt the others.]]
-[[Returns:] [the index on the tuple of the first thread joined.]]
-
-]
-
-[endsect]
-
-[section:conc_join_any_until Non Member Function `conc_join_any_until()`]
-[/==========================================================================================]
-
- template<typename F0, ..., typename Fn-1>
- std::pair<bool,std::size_t> conc_join_any_until(
- const system_time& wait_until, F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [launch in each function on a thread of execution, join the first and then interrupt the others or interrup all.]]
-[[Returns:] [a pair consisting of a boolean stating if the a thread has been joined before the given time and the index on the tuple of the first thread joined.]]
-
-]
-
-[endsect]
-
-[section:conc_join_any_for Non Member Function `conc_join_any_for()`]
-[/==========================================================================================]
-
- template<typename TimeDuration, typename F0, ..., typename Fn-1>
- std::pair<bool,std::size_t> conc_join_any_for(
- TimeDuration wait_for, F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [launch in each function on a thread of execution, join the first and then interrupt the others or interrup all.]]
-[[Returns:] [a pair consisting of a boolean stating if the a thread has been joined before the given time and the index on the tuple of the first thread joined.]]
-
-]
-
-[endsect]
-
-
-[endsect]
-
-[section:thread_group_once_hpp Header `<boost/interthreads/thread_group_once.hpp>`]
-[/==========================================================================================]
-
- namespace boost {
- namespace interthreads {
-
- template <std::size_t N>
- class thread_group;
-
- }
- }
-
-
-[section:thread_group_once_class Template Class `thread_group_once<>`]
-[/==========================================================================================]
-
-`thread_group_once<>` is an extension of the boost::thread_group which allows to join the thread finishing
-the first, using for that the set_once synchronizer.
-
- template <std::size_t n>
- class thread_group_once {
- public:
- thread_group_once();
- ~thread_group_once();
-
- template<typename F>
- thread* create_thread(F threadfunc);
- void remove_thread(thread* thrd);
-
- // move support
- thread_group_once(boost::move_t<thread_group_once<n>> x);
- thread_group_once& operator=(boost::move_t<thread_group_once<n>> x);
- operator boost::move_t<thread_group_once<n>>();
- boost::move_t<thread_group_once<n>> move();
-
- void swap(thread_group_once<n>& x);
-
- bool joinables() const;
-
- void join_all();
- bool join_all_until(const system_time& wait_until);
- template<typename TimeDuration>
- bool join_all_for(TimeDuration const& rel_time);
-
- std::size_t join_any();
- std::pair<bool,std::size_t> join_any_until(
- const system_time& wait_until);
- template<typename TimeDuration>
- std::pair<bool,std::size_t> join_any_for(
- TimeDuration const& rel_time);
-
- void detach_all();
-
- void interrupt_all();
- bool interruption_requested() const;
-
- size_t size();
-
- const thread& operator[](std::size_t i);
- };
- }
- }
-
-
-[section:thread_group_once_callable_constructor Constructor]
-[/==========================================================================================]
-
- thread_group_once();
-
-[variablelist
-
-
-[[Effects:] [creates a thread group.]]
-
-[[Postconditions:] [`*this` refers to the newly created group of threads of execution.]]
-
-[[Throws:] [__thread_resource_error__ if an error occurs.]]
-
-]
-
-[endsect]
-
-
-[section:thread_group_once_destructor Destructor]
-[/==========================================================================================]
-
- ~thread_group_once();
-
-[variablelist
-
-[[Effects:] [If *this have associateds thread of execution, calls detach() on them. Destroys *this.]]
-
-]
-
-[endsect]
-
-[section:thread_group_once_joinable Member function `joinables()`]
-[/==========================================================================================]
-
- bool joinables() const;
-
-[variablelist
-
-[[Returns:] [`true` if `*this` refers to threads of execution, `false` otherwise.]]
-
-[[Throws:] [Nothing]]
-
-]
-
-[endsect]
-
-[section:thread_group_once_join Member function `join_all()`]
-[/==========================================================================================]
-
- void join_all();
-
-[variablelist
-
-[[Effects:] [Call `join()` on each __thread__ object in the group.]]
-
-[[Postcondition:] [Every thread in the group has terminated.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::join` is one of the predefined interruption points, `thread_group_once<>::join_all()` is also an interruption point.]]
-
-]
-
-[endsect]
-
-[section:thread_group_once_timed_join Member function `join_all_until()`]
-[/==========================================================================================]
-
- bool join_all_until(const system_time& wait_until);
- template<typename TimeDuration>
- bool join_all_for(TimeDuration const& rel_time);
-
-[variablelist
-
-[[Effects:] [Call `timed_join()` on each __thread__ object in the group.]]
-
-[[Postcondition:] [Every thread in the group has terminated.]]
-
-[[Returns:] [true if joined.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::timed_join` is one of the predefined interruption points, `thread_group_once<>::timed_join_all()` is also an interruption point.]]
-
-]
-
+[include reference/thread_keep_alive.qbk]
[endsect]
-[section:join_first_then_interrupt Member function `join_any()`]
-[/==========================================================================================]
-
- std::size_t join_any();
-
-[variablelist
-
-[[Effects:] [Call `join_any()` and the `interrup_all()`.]]
-[[Postcondition:] [Every thread in the group has terminated.]]
+[section AE/ACT Framework Reference]
-[[Throws:] [Nothing]]
+[include reference/act_traits.qbk]
-[[Note:] [Since `join_any` is one of the predefined interruption points, `thread_group_once<>::join_any()` is also an interruption point.]]
+[section AE operations]
-]
+[include reference/fork.qbk]
+[include reference/fork_after.qbk]
+[include reference/fork_all.qbk]
+[include reference/wait_for_all.qbk]
+[include reference/wait_for_any.qbk]
[endsect]
-[section:timed_join_first_then_interrupt Member function `join_any_until()`]
-[/==========================================================================================]
-
- std::pair<bool,std::size_t> join_any_until(
- const system_time& wait_until);
- template<typename TimeDuration>
- std::pair<bool,std::size_t> join_any_for(
- TimeDuration const& rel_time);
-
-[variablelist
-
-[[Effects:] [Call `get_until()` and the `interrup_all()`.]]
+[include reference/algorithm.qbk]
-[[Postcondition:] [Every thread in the group has terminated.]]
+[section Future based ACT operations]
+[include reference/wait.qbk]
+[include reference/wait_until.qbk]
+[include reference/get.qbk]
+[include reference/is_ready.qbk]
+[include reference/has_value.qbk]
+[include reference/has_exception.qbk]
-[[Returns:] [true if joined.]]
-
-[[Throws:] [Nothing]]
-
-[[Note:] [Since `boost::thread::timed_join` is one of the predefined interruption points, `thread_group_once<>::timed_join_all()` is also an interruption point.]]
-
-]
+[include reference/wait_all.qbk]
+[include reference/wait_all_until.qbk]
+[include reference/get_all.qbk]
+[include reference/are_all_ready.qbk]
+[include reference/have_all_value.qbk]
+[include reference/have_all_exception.qbk]
[endsect]
-[section:detach_all Member function `detach_all()`]
-[/==========================================================================================]
+[section Thread based ACT operations]
- void detach_all();
+[include reference/detach.qbk]
+[include reference/joinable.qbk]
+[include reference/join.qbk]
+[include reference/join_until.qbk]
+[include reference/interrupt.qbk]
+[include reference/interruption_requested.qbk]
-[variablelist
-
-[[Effects:] [Call `detach()` on each __thread__ object in the group.]]
-
-]
+[include reference/detach_all.qbk]
+[include reference/join_all.qbk]
+[include reference/are_all_joinable.qbk]
+[include reference/join_all_until.qbk]
+[include reference/interrupt_all.qbk]
+[include reference/interruption_requested_all.qbk]
[endsect]
-[section Member function `interrupt_all()`]
-[/==========================================================================================]
-
- void interrupt_all();
-
-[variablelist
-
-[[Effects:] [Call `thread::interrupt()` on each __thread__ object in the group.]]
-
-]
[endsect]
-[section:thread_group_once_size Member function `size()`]
-[/==========================================================================================]
+[section AE/ACT Models Reference]
- int size();
+[include reference/basic_threader.qbk]
+[include reference/launcher.qbk]
+[include reference/threader.qbk]
+[include reference/scheduler.qbk]
-[variablelist
+[include reference/typeof/futures.qbk]
+[include reference/typeof/launcher.qbk]
+[include reference/typeof/threader.qbk]
+[include reference/typeof/basic_threader.qbk]
+[include reference/typeof/scheduler.qbk]
-[[Returns:] [The number of threads in the group.]]
+[include reference/asynchronous_executor_decorator.qbk]
+[include reference/basic_threader_decorator.qbk]
+[include reference/threader_decorator.qbk]
+[include reference/launcher_decorator.qbk]
-[[Throws:] [Nothing.]]
-
-]
-
-[endsect]
+[/include reference/asynchronous_adapter.qbk]
[endsect]
-[section:thread_group_once_make_thread_group_once Non Member Function `make_thread_group_once()`]
-[/==========================================================================================]
+[section Thread Array Reference]
- template<typename F0, ..., typename Fn-1>
- thread_group_once make_thread_group_once(F0 f0, ..., Fn fn-1);
-
-[variablelist
-
-[[Effects:] [makes a new thread_group_once<>.]]
-[[Returns:] [the created thread group.]]
-
-
-]
-
-[endsect]
+[include reference/set_once.qbk]
+[include reference/thread_tuple.qbk]
+[include reference/thread_tuple_once.qbk]
+[include reference/thread_group_once.qbk]
+[/include reference/thread_and_join.qbk]
[endsect]
-
[endsect]
Modified: sandbox/interthreads/libs/interthreads/doc/tutorial.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/tutorial.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/tutorial.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,5 +1,5 @@
[/
- (C) Copyright 2008-20009 Vicente J Botet Escriba.
+ (C) Copyright 2008-2009 Vicente J Botet Escriba.
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).
@@ -8,6 +8,8 @@
[section:tutorial Tutorial]
[/========================]
+[section Thread Extensions]
+
[section Thread Decorator]
[/==========================================================================================]
@@ -16,28 +18,31 @@
static boost::interthreads::thread_decoration d;
void setup();
-
- boost::interthreads::thread_decoration d(setup)
-These decorations will be called either when we request this explicitly at the initialization of the
-thread (this is needed on the main thread) or when we create a thread using specific decorator wrapper. This is explained in more detail
-in the next sections.
+ bith::thread_decoration d(setup);
+
+These decorations will be called either when we request this explicitly at the initialization of the thread (this is needed on the main thread) or when we create a thread using specific decorator wrapper. This is explained in more detail in the next sections.
[endsect]
[section Creating threads with decorators]
When we want the decorations to decorate one thread of execution we can create the thread using the decorator wrapper.
- boost::thread th(boost::interthreads::thread_decorator(fct));
+ boost::thread th(bith::thread_decorator(fct));
+
+or using one of the __AE__ decorators, as
+
+ bith::basic_threader_decorator ae;
+ BOOST_AUTO(th, bith::fork(ae, fct));
[endsect]
[section:decorator_explicit_call Calling explictly the decoration on a thread]
-For threads that are not created using the boost::thread class, as it is the case of the main thread, we need to call explicitly the function
-__thread_decoration_decorate__ at the begining of the thread.
+For threads that are not created using the boost::thread class, as it is the case of the main thread, we need to call explicitly the function
+__decorate__ at the begining of the thread.
int main() {
- boost::interthreads::decorate();
+ bith::decorate();
// ...
}
@@ -52,7 +57,7 @@
[section Key initialization]
[/==========================================================================================]
-As the curent implementation use the address of the thread_specific_shared_ptr<> object, there is no need to do whatever to get the key.
+As the curent implementation use the address of the thread_specific_shared_ptr<> object, there is no need to do whatever to get the key.
bith::thread_specific_shared_ptr<myclass> ptr;
@@ -68,32 +73,27 @@
deleter routine. Alternatively, the stored value can be reset to `NULL` and the prior value returned by calling the `release()`
member function, allowing the application to take back responsibility for destroying the object.
-Initialization can be done
+Initialization can be done
* explicitly on the curret thread. Basically it works like a thread local storage from inside the thread.
bith::thread_specific_shared_ptr<myclass> ptr;
- void func() {
- { // current thread
+ void func() { // current thread
// ...
ptr.reset(p);
// ...
}
-* When we associate a thread decoration to the thread_specific_shared_ptr<> we can initialize all the decorations either calling
-decorate or creating a thread wrapping the function with the thread thread_decorator functor.
+* When we associate a thread decoration to the thread_specific_shared_ptr<> we initialize implicitly every thread created with a thread_decorator.
bith::thread_specific_shared_ptr<myclass> ptr;
- void myclass_init() {
+ void myclass_setup() {
ptr.reset(new myclass(any specific parameters));
}
- bith::thread_decoration myclass_decoration(myclass_init);
+ bith::thread_decoration myclass_decoration(myclass_setup);
+
+ void func() { // ptr.reset(p); done implicitly
- void func() {
- { // current thread
- // ...
- ptr.reset(p);
- // ...
}
boost::thread th=bith::make_decorated_thread(func);
@@ -103,7 +103,7 @@
[section Obtain the pointer to the thread-specific object on the current thread]
[/==========================================================================================]
-All functions known from boost::thread_specific_ptr are available except release, and so its
+All functions known from boost::thread_specific_ptr are available except release, and so its
semantics from inside the thread.
The value for the current thread can be obtained using the `get()` member function, or by using
the `*` and `->` pointer deference operators.
@@ -131,15 +131,15 @@
where `foo()` is a function of `myclass`.
-This could work or not. the issue apears as we can get a reference to a thread before the threads has started,
-so the setting of the threads specific context could be not done yet. One way to manage with this error is to
+This could work or not. the issue apears as we can get a reference to a thread before the threads has started,
+so the setting of the threads specific context could be not done yet. One way to manage with this error is to
get the shared pointer and check if it contains something or not.
shared_ptr<myclass> shp = ptr[th->get_id()]->foo();
if (shp.get() != 0) shp->foo();
- else ...
-
+ else ...
+
When we need this we can pool:
shared_ptr<myclass> shp;
@@ -149,7 +149,7 @@
shp->foo();
-The library provides a synchonization mechanism to solve this issue.
+The library provides a synchonization mechanism to solve this issue.
The wait_and_get() function allows a thread to synchronize with the setting from another thread.
shared_ptr<myclass> shp = ptr.wait_and_get(th->get_id());
@@ -159,6 +159,14 @@
ptr.wait_and_get(th->get_id()->foo();
+In order to ensure that the decorations have been called a cleaner and safer option is don't retunr the thread until it has been started.
+This behavior is obtained each time the thread is created with an __AE__ decorator, as
+
+ bith::basic_threader_decorator ae;
+ BOOST_AUTO(th, bith::fork(ae, func));
+ // here you are sure all the decorations have been called
+ // so we can access any thread_specific_shared_ptr of the created thread.
+
The lifetime of the myclass instance is managed by a shared_ptr. One reference is held by the thread (by means of a tss), a second is
held by the thread::id to shared_ptr<T> map and additional references might be held by other threads that obtained it by `*pmyclass[th]`.
@@ -167,12 +175,12 @@
[section Iterating through all the thread specific context]
[/==========================================================================================]
-Another use case appears when some global controller needs to access the thread specific data of all the threads. Several approaches are
-here possible; the library has choosed to provide a map getter using a external locking mechanism that 'ensure' that the map access is
-locked during the map query.
+Another use case appears when some global controller needs to access the thread specific data of all the threads. Several approaches are
+here possible; the library has choosen to provide a map getter using a external locking mechanism that 'ensure' that the map access is
+locked during the map query.
- {
- bith::thread_specific_shared_ptr<myclass>::lock_type lock(ptr.get_mutex(lock));
+ {
+ bith::thread_specific_shared_ptr<myclass>::lock_type lock(ptr.get_mutex());
const bith::thread_specific_shared_ptr<myclass>::map_type amap = ptr.get_map(lock);
// use the map
}
@@ -184,24 +192,28 @@
[section Deleting the context]
[/==========================================================================================]
-When a thread exits, the objects associated with each `boost::thread_specific_shared_ptr<>` instance is not inmediately destroyed due to
-its shared nature. It is detached from the current thread and removed from the map.
+When a thread exits, the objects associated with each `boost::thread_specific_shared_ptr<>` instance is not inmediately destroyed due to
+its shared nature. It is detached from the current thread and removed from the map.
Only when there are no more references to the shared pointer it will be destroyed. By default, the object
pointed to by a pointer `p` is destroyed by invoking `delete p`, but this can be overridden for a specific instance of
`boost::thread_specific_shared_ptr<>` by providing a deleter routine to the constructor. In this case, the object is destroyed by invoking
-`deleter(p)` where `deleter` is the deleter routine supplied to the constructor. The deleter function is called only when there are no
+`deleter(p)` where `deleter` is the deleter routine supplied to the constructor. The deleter function is called only when there are no
more references to the shared pointer.
+ // Add use of deleter !!!
+
[endsect]
[section Cleanup at thread exit]
[/==========================================================================================]
-When a thread exits, the objects associated with each thread_specific_shared_ptr<> instance is not inmediately destroyed due to its shared nature. Only when there are no more references to the shared pointer it will be destroyed. By default, the object pointed to by a pointer p is destroyed by invoking delete p, but this can be overridden for a specific instance of boost::thread_specific_shared_ptr<> by providing a cleanup routine to the constructor. In this case, the object is destroyed by invoking func(p) where func is the cleanup routine supplied to the constructor. The cleanup functions are called in an unspecified order. If a cleanup routine sets the value of associated with an instance of boost::thread_specific_shared_ptr<> that has already been cleaned up, that value is added to the cleanup list. Cleanup finishes when there are no outstanding instances of boost::thread_specific_shared_ptr<> with values.
+When a thread exits, the objects associated with each thread_specific_shared_ptr<> instance is not inmediately destroyed due to its shared nature. Only when there are no more references to the shared pointer it will be destroyed. By default, the object pointed to by a pointer p is destroyed by invoking delete p, but this can be overridden for a specific instance of boost::thread_specific_shared_ptr<> by providing a cleanup routine to the constructor. In this case, the object is destroyed by invoking func(p) where func is the cleanup routine supplied to the constructor. The cleanup functions are called in an unspecified order. If a cleanup routine sets the value of associated with an instance of boost::thread_specific_shared_ptr<> that has already been cleaned up, that value is added to the cleanup list. Cleanup finishes when there are no outstanding instances of boost::thread_specific_shared_ptr<> with values.
If a cleanup routine sets the value associated with an instance of `boost::thread_specific_shared_ptr<>` that has already been
cleaned up, that value is added to the cleanup list. Cleanup finishes when there are no outstanding instances of
`boost::thread_specific_shared_ptr<>` with values.
+ // Add use of at thread_exit!!!
+
[endsect]
[endsect]
@@ -209,14 +221,14 @@
[section Keep alive]
[/==========================================================================================]
-We will use the implementation of the keep alive mechanism as tutorial for the thread decorators,
+We will use the implementation of the keep alive mechanism as tutorial for the thread decorators,
thread specific shared pointers and the kepp alive mechanism itself.
We want to detect situations on which a thread is looping or blocked on some component.
The user needs to state when this mechanism is enabled or disabled.
-Since the only purpose is to find threads that don't work, the thread needs to say if it is alive to a controller.
-The controler request at predefined intervals if the thread is dead, and in this case it will call a user specific function
+Since the only purpose is to find threads that don't work, the thread needs to say if it is alive to a controller.
+The controler request at predefined intervals if the thread is dead, and in this case it will call a user specific function
which by default aborts the program.
A thread is considered dead if during a given period the number of checkins is inferior to a given threshold.
@@ -230,42 +242,38 @@
namespace boost {
namespace interthreads {
- namespace this_thread {
- class enable_keep_alive
- {
- enable_keep_alive(const enable_keep_alive&);
- enable_keep_alive& operator=(const enable_keep_alive&);
- public:
- enable_keep_alive(std::size_t periods=2, std::size_t checkins=1);
- ~enable_keep_alive();
- };
-
- class disable_keep_alive
- {
- disable_keep_alive(const disable_keep_alive&);
- disable_keep_alive& operator=(const disable_keep_alive&);
- public:
- disable_keep_alive();
- ~disable_keep_alive();
- };
+ namespace this_thread {
+ class enable_keep_alive {
+ public:
+ enable_keep_alive(std::size_t periods=2, std::size_t checkins=1);
+ ~enable_keep_alive();
+ };
+
+ class disable_keep_alive {
+ public:
+ disable_keep_alive();
+ ~disable_keep_alive();
+ };
- void keep_alive_point();
- bool keep_alive_enabled();
+ void keep_alive_point();
+ bool keep_alive_enabled();
- typedef void (*on_dead_thread_type)(thread*);
- void set_on_dead_thread(on_dead_thread_type fct);
-
- }
+ typedef void (*on_dead_thread_type)(thread::id, thread*);
+ void set_on_dead_thread(on_dead_thread_type fct, thread* th=0);
+
+ }
+ bool keep_alive_enabled(thread::id);
+ void set_on_dead_thread(thread::id, on_dead_thread_type fct, thread* th=0);
}
}
[endsect]
-[section Keep alive mechanism initialization]
+[section Keep alive mechanism initialization]
[/==========================================================================================]
-There is a single controller `keep_alive_mgr`. The controler needs to access some thread specific shared context
-`thread_keep_alive_ctx` to be able to control a thread.
+There is a single controller `keep_alive_mgr`. The controler needs to access some thread specific shared context
+`thread_keep_alive_ctx` to be able to control a thread.
namespace detail {
struct thread_keep_alive_ctx {
@@ -291,9 +299,9 @@
};
}
-The initialization of the controller itself and the setting the thread specific context is done
-using an internal thread decoration `thread_keep_alive_ctx::initializer_`
-with thread_keep_alive_ctx::init as setup function.
+The initialization of the controller itself and the setting the thread specific context is done
+using an internal thread decoration `thread_keep_alive_ctx::initializer_`
+with `thread_keep_alive_ctx::init` as setup function.
thread_specific_shared_ptr<detail::thread_keep_alive_ctx> thread_keep_alive_ctx::instance_;
thread_decoration thread_keep_alive_ctx::initializer_(thread_keep_alive_ctx::init);
@@ -306,8 +314,8 @@
instance_.reset(new thread_keep_alive_ctx());
}
-The keep_alive_mgr::initialize function ensure just that the init function is called once using the boost::call_once.
-This init function create the instance of the keep_alive_mgr singleton.
+The `keep_alive_mgr::initialize` function ensure just that the init function is called once using the `boost::call_once`.
+This `init` function create the instance of the `keep_alive_mgr` singleton.
void keep_alive_mgr::initialize() {
boost::call_once(flag_, init);
@@ -315,15 +323,16 @@
void keep_alive_mgr::init() {
instance_=new keep_alive_mgr();
}
+
[endsect]
-[section:keep_alive_threads Which threads can be controlled?]
+[section:keep_alive_threads Which threads can be controlled?]
[/==========================================================================================]
-As the keep alive mechanism use a thread decoration, the user needs to explicit calls the
-`bith::decorate` function at the begining of the thread function or by wrapping the thread function.
-Instead of having a specific function to call or thread function wrapper the keep alive uses the functions
-provided by the thread decorator (`bith::decorate` and `bith::thread_decorator`).
+As the keep alive mechanism use a thread decoration, the user needs to explicit calls the
+`bith::decorate` function at the begining of the thread function or by wrapping the thread function.
+Instead of having a specific function to call or thread function wrapper the keep alive uses the functions
+provided by the thread decorator (`bith::decorate` and `bith::thread_decorator`).
So we must either call `bith::decorate` explicitly on the thread function
void fct() {
@@ -342,7 +351,7 @@
[/==========================================================================================]
To be controled by the keep alive manager we need to enable the mechanism using the enable_keep_alive.
-By default this enabler requires the application to do at least one check point every 2 seconds using the
+By default this enabler requires the application to do at least one check point every 2 seconds using the
`bith::keep_alive_point()` function.
void fct() {
@@ -355,29 +364,29 @@
for(;;) {
// do a check point
keep_alive_point();
- // ...
+ // ...
}
}
[endsect]
-[section:keep_alive_disabling Disabling the keep alive mechanism]
+[section:keep_alive_disabling Disabling the keep alive mechanism]
[/==========================================================================================]
-Some times we need to do an external task that could take an undefined time. We can then disable the
+Some times we need to do an external task that could take an undefined time. We can then disable the
keep alive mechanisme by using a disabler `bith::disable_keep_alive`.
void fct() {
using bith::this_thread;
// ...
- // states that the thread will be declared dead if threre are
+ // states that the thread will be declared dead if threre are
// less that 1 check_points in 2 seconds.
enable_keep_alive enabler;
for(;;) {
// do a check point
keep_alive_point();
-
+
if (cnd) {
// when a blocking task spending an undefined time
// you can disable the keep alive mechanism
@@ -387,9 +396,9 @@
}
}
-If on the contrary we don't want to disable the keep alive mechanism, it will be interesting to do a
-`boost::interruption_check_point()` just after the blocking task. In this way if the task takes too much time and
-the thread is declared dead, you let the possibility to manage the keep alive error by interrupting
+If on the contrary we don't want to disable the keep alive mechanism, it will be interesting to do a
+`boost::interruption_check_point()` just after the blocking task. In this way if the task takes too much time and
+the thread is declared dead, you let the possibility to manage the keep alive error by interrupting
the dead thread, once the task is finished.
void fct() {
@@ -397,15 +406,15 @@
using bith::this_thread;
// ...
- // states that the thread will be declared dead if threre are
+ // states that the thread will be declared dead if threre are
// less that 1 check_points in 2 seconds.
enable_keep_alive enabler;
for(;;) {
// do a check point
keep_alive_point();
-
+
if (cnd) {
- // when a blocking task spending an undefined time
+ // when a blocking task spending an undefined time
// you can disable the keep alive mechanism
unknow_time_task();
interruption_check_point();
@@ -416,22 +425,22 @@
[endsect]
-[section:keep_alive_persistent Configuring the dead persistency]
+[section:keep_alive_persistent Configuring the dead persistency]
[/==========================================================================================]
The default enabling parameters could be too restrictive in some cases. But the `enable_keep_alive` configure that with the two parameters.
-We can declare a thread dead when the thread has not done a number of checkins in a given period.
+We can declare a thread dead when the thread has not done a number of checkins in a given period.
This can be useful when you know the time a given task should take.
void fct() {
using bith::this_thread;
// ...
- // states that the thread will be declared dead if threre are
+ // states that the thread will be declared dead if threre are
// less that 4 check_points in 30 seconds.
enable_keep_alive enabler(15, 1);
for(;;) {
-
+
if (cnd) {
// it is know that this task will take no more than 15 seconds
enable_keep_alive control(15, 1);
@@ -440,7 +449,7 @@
this_thread::interruprion_check_point();
}
-
+
}
// ...
}
@@ -448,16 +457,16 @@
[endsect]
-[section Access from the current thread]
+[section Access from the current thread]
[/==========================================================================================]
But how all this works. We start with enablers/disablers.
-Enablers/disablers use RAII, so they can be nested and the context be restored on the destructor.
-At the construction they store the current state of the keep alive of this thread using the backup
+Enablers/disablers use RAII, so they can be nested and the context be restored on the destructor.
+At the construction they store the current state of the keep alive of this thread using the backup
function and then they enable/disable the KA mechanism. On destruction they restore the backuped context.
enable_keep_alive::enable_keep_alive(
- std::size_t periods, std::size_t checkins)
+ std::size_t periods, std::size_t checkins)
{
backup_=detail::thread_keep_alive_ctx::instance()->backup(data_);
detail::thread_keep_alive_ctx::instance()->enable_keep_alive(periods, checkins);
@@ -483,7 +492,7 @@
data_=new_data
return the_backup;
}
-
+
void thread_keep_alive_ctx::restore(thread_keep_alive_internal* backup) {
data_=backup;
}
@@ -494,57 +503,58 @@
void thread_keep_alive_ctx::disable_keep_alive() {
data_->enabled_ = false;
}
-
-Note that there is no need to check if the `detail::thread_keep_alive_ctx::instance_`
+
+Note that there is no need to check if the `detail::thread_keep_alive_ctx::instance_`
contains a poiter because we have ensured that at initialization time.
-Next there is the central function `keep_alive_point()`. This function
-does nothing more than relaying the request to the specific context of this thread.
+Next there is the central function `keep_alive_point()`. This function
+does nothing more than relaying the request to the specific context of this thread.
This function just increase the number of `checkins_`.
void keep_alive_point() {
detail::thread_keep_alive_ctx::instance()->check_point();
}
-
+
void thread_keep_alive_ctx::check_point() {
++data_->checkins_;
}
-
+
The `set_on_dead_thread()` do the same. This function just store the on dead action.
- void set_on_dead_thread(on_dead_thread_type fct);
- detail::thread_keep_alive_ctx::instance()->set_on_dead_thread(fct);
+ void set_on_dead_thread(on_dead_thread_type fct, thread* th) {
+ detail::thread_keep_alive_ctx::instance()->set_on_dead_thread(fct, th);
}
- void set_on_dead_thread(on_dead_thread_type fct);
- data_->on_dead_=fct;
- }
+ void set_on_dead_thread(on_dead_thread_type fct, thread* th) {
+ data_->on_dead_=fct;
+ data_->thread_ptr_=th;
+ }
[endsect]
-[section Access from the controller thread]
+[section Access from the controller thread]
[/==========================================================================================]
-Up to now we have see the use of `bith::thread_keep_alive_ctx` as a `boost::thread_specific_ptr`, i.e. it is used
+Up to now we have see the use of `bith::thread_keep_alive_ctx` as a `boost::thread_specific_ptr`, i.e. it is used
from the current thread.
-We will see now how the controler behaves. The single instance of the keep_alive_mgr has been created on the
+We will see now how the controler behaves. The single instance of the keep_alive_mgr has been created on the
init function.
The constructor just construct a thread with the loop function.
- keep_alive_mgr::keep_alive_mgr() : thread_(loop) {}
+ keep_alive_mgr() : end_(false), thread_(boost::bind(loop, boost::ref(end_))) {}
The loop function will every second iterate over all the thread_keep_alive_ctx threads specific contexts asking them to control itselfs.
-Note that as the map can be modified when threads are created or finish we nee to protect the iteration externally with a lock on the
+Note that as the map can be modified when threads are created or finish we nee to protect the iteration externally with a lock on the
protecting mutex.
- void keep_alive_mgr::loop() {
+ static void loop(bool& end) {
boost::xtime t;
- boost::xtime_get(&t,1);
- for(;;) {
- t.sec += 1;
+ boost::xtime_get(&t,1);
+ while(!end) {
+ t.sec += 1;
boost::thread::sleep(t);
lock_type lock(thread_keep_alive_ctx::instance().get_mutex());
const detail::thread_keep_alive_ctx::tssp::map_type& tmap(
@@ -556,9 +566,18 @@
}
}
+The thread loops until the end variable is true. In order to stop proprely this thread we will use the destructor of singleton instance.
+This end variable is a reference to a variable stored on the keep_alive_mgr context which
+has been initialized staticly. So its destrcutor will be called when the program finish.
+So it is up to the destructor to set this variable and wait for the thread completion
+
+ ~keep_alive_mgr() {
+ end_=true;
+ thread_.join();
+ }
-The thread_keep_alive_ctx::control function behaves as follows: if it is enabled decrease
-the number of remaining periods and if the thread is declared dead execute the on dead
+The thread_keep_alive_ctx::control function behaves as follows: if it is enabled decrease
+the number of remaining periods and if the thread is declared dead execute the on dead
action and reset the checkings and periods.
void control(thread::id id) {
@@ -568,7 +587,7 @@
on_dead(id);
data_->checkins_=0;
data_->periods_=data_->total_periods;
- }
+ }
}
}
@@ -582,9 +601,9 @@
[section:thread_tuple_launching Launching thread tuple]
[/==========================================================================================]
-A new thread tuple is launched by passing a collection of object of some callable type that can be invoked with no parameters to the constructor.
-These objects are then copied into internal storage, and invoked on the newly-created threads of execution.
-If the objects must not (or cannot) be copied, then `boost::ref` can be used to pass in a reference to the function object.
+A new thread tuple is launched by passing a collection of object of some callable type that can be invoked with no parameters to the constructor.
+These objects are then copied into internal storage, and invoked on the newly-created threads of execution.
+If the objects must not (or cannot) be copied, then `boost::ref` can be used to pass in a reference to the function object.
In this case, the user of __thread_tuple__ must ensure that the referred-to object outlives the newly-created thread of execution.
struct callable
@@ -625,23 +644,23 @@
[/==========================================================================================]
If the function or callable objects passed to the __thread_tuple__ constructor propagates an exception when invoked that is not of type
-__thread_interrupted__, `std::terminate()` is called.
+__thread_interrupted__, `std::terminate()` is called.
[endsect]
[section:thread_tuple_joining Joining and detaching]
[/==========================================================================================]
-When the __thread_tuple__ object that represents a collection of threads of execution is destroyed the threads become ['detached].
+When the __thread_tuple__ object that represents a collection of threads of execution is destroyed the threads become ['detached].
Once a threads are detached, they will continue executing until the invocation of the functions or callable objects supplied on construction have completed,
or the program is terminated. The threads of a __thread_tuple__ can also be detached by explicitly invoking the detach member function on the __thread_tuple__
object. In this case, all the threads of the __thread_tuple__ object ceases to represent the now-detached thread, and instead represents 'Not-a-Thread.
In order to wait for a tuple of threads of execution to finish, the __join__ or __timed_join__ member functions of the __thread_tuple__ object must be
-used.
-__join__ will block the calling thread until the all the threads represented by the __thread_tuple__ object have completed.
-If the threads of execution represented by the __thread_tuple__ object have already completed, or
-the __thread_tuple__ objects represents __not_a_thread__, then __join__ returns immediately.
+used.
+__join__ will block the calling thread until the all the threads represented by the __thread_tuple__ object have completed.
+If the threads of execution represented by the __thread_tuple__ object have already completed, or
+the __thread_tuple__ objects represents __not_a_thread__, then __join__ returns immediately.
__timed_join__ is similar, except that a call to __timed_join__ will also return if the threads being waited for
does not complete when the specified time has elapsed.
@@ -651,7 +670,7 @@
[section:thread_tuple_interruption Interruption]
[/==========================================================================================]
-A tuple of running threads can be ['interrupted] by invoking the __interrupt__ member function of the corresponding __thread_tuple__ object.
+A tuple of running threads can be ['interrupted] by invoking the __interrupt__ member function of the corresponding __thread_tuple__ object.
When the interrupted threads next executes one of the specified __interruption_points__ (or if it is currently __blocked__ whilst executing one)
with interruption enabled, then a __thread_interrupted__ exception will be thrown in the interrupted thread. If not caught,
this will cause the execution of the interrupted thread to terminate. As with any other exception, the stack will be unwound, and
@@ -668,6 +687,11 @@
[endsect]
[endsect]
+[endsect]
+
+[section AE/ACT framework]
+[endsect]
+
[endsect]
\ No newline at end of file
Modified: sandbox/interthreads/libs/interthreads/doc/users_guide.qbk
==============================================================================
--- sandbox/interthreads/libs/interthreads/doc/users_guide.qbk (original)
+++ sandbox/interthreads/libs/interthreads/doc/users_guide.qbk 2009-02-08 16:28:32 EST (Sun, 08 Feb 2009)
@@ -1,6 +1,6 @@
[/
[/
- (C) Copyright 2008-20009 Vicente J. Botet Escriba
+ (C) Copyright 2008-2009 Vicente J. Botet Escriba
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).
@@ -18,14 +18,29 @@
[section:bibliography References]
[/==============================]
+[/
[variablelist
[[boost::call_once] [Boost.Thread implementation for call_once.]]
[[boost::this_thread::at_thread_exit] [Boost.Thread implementation for at thread exit cleanup registration.]]
[[boost::thread_specific_ptr] [Boost.Thread implementation for TSS.]]
[[boost::thread_group] [Boost.Thread thread_group.]]
]
+]
+
+[variablelist
+[[[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1883.pdf N1833 - Preliminary Threading Library Proposal for TR2]] []]
+[[[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2185.html N2185 - Proposed Text for Parallel Task Execution]] []]
+[[[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2276.html N2276 - Thread Pools and Futures]] []]
+[[[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2802.html N2802: A plea to reconsider detach-on-destruction for thread objects] ] []]
+[[[@http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-threadpool.3.tar.gz&directory=Concurrent%20Programming& Boost.ThreadPool (O. Kowalke)]] []]
+[[[@http://www.justsoftwaresolutions.co.uk/threading/free-implementation-of-c++-futures.html Boost.Futures (A. Williams)]] []]
+[[[@http://www.boost.org/libs/thread Boost.Thread (A. Williams)]] []]
+]
+
+
[endsect]
+
[/=======================]
[section:glosary Glossary]
[/=======================]
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