diff --git a/doc/compliance.qbk b/doc/compliance.qbk index aea1e5c8..015e3a8c 100644 --- a/doc/compliance.qbk +++ b/doc/compliance.qbk @@ -9,6 +9,8 @@ [section:cpp11 C++11 standard Thread library] +[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.html C++11 standard]] + [table C++11 standard Conformance [[Section] [Description] [Status] [Comments] [Ticket]] @@ -86,24 +88,155 @@ [endsect] -[section:shared Shared Locking extensions] +[section:cxx14 C++14 standard Thread library - accepted changes] -[table Howard's Shared Locking Proposal Conformance +[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.html C++14 on-going standard]] + + +[table [@http://isocpp.org/files/papers/N3659.html N3659 Shared locking in C++ revision 2] Conformance [[Section] [Description] [Status] [Comments]] - [[X] [Shared Locking] [Yes] [Needs `BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSION]] - [[X.1] [Shared Lockables Concepts] [Yes] [ - ]] - [[X.1.1] [SharedLockable concept] [Yes] [ - ]] - [[X.1.2] [UpgradeLockable concept] [Yes] [ - ]] - [[X.2] [Shared Mutex Types] [Yes] [ - ]] - [[X.2.1] [shared_mutex class] [Yes] [ - ]] - [[X.2.2] [upgrade_mutex class] [Yes] [ - ]] - [[X.3] [Locks] [Yes] [-]] - [[X.3.1] [unique_lock class adaptations] [Yes] [-]] - [[X.3.2] [shared_lock class] [Yes] [ - ]] - [[X.3.3] [upgrade_lock class] [Yes] [-]] + [[30.4.1.4] [Shared Lockables Types] [Yes] [ - ]] + [[30.4.1.4.1] [shared_mutex class] [Yes] [ - ]] + [[30.4.2.3] [Class template shared_lock] [Yes] [-]] +] + +[endsect] + +[section:cxx1y C++1y TS Concurrency - On going proposals] + +[section:latch C++ Latches and Barriers] + +[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3600.html N3659 C++ Latches and Barriers]] + +[table C++ Latches and Barriers Conformance + [[Section] [Description] [Status] [Comments]] + [[X.1] [Class latch] [Partial] [ A new class latch has been added. The interface is a super set of the one of the proposal, taking some of the functions of the class barrier.]] + [[X.2] [Class barrier] [No] [ Even if Boost.Thread has a class boost:barrier it doesn't provides the same kind of services. There is an experimental completion_latch that could be used instead. ]] +] + +[endsect] +[section:queue C++ Concurrent Queues] + +[note [@ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3533.html N3533 C++ Concurrent Queues]] + +[table C++ Concurrent Queues Conformance + [[Section] [Description] [Status] [Comments]] + [[X.1] [Conceptual interface] [Partial] [ The interface provided has some differences respect to this proposal. All the functions having a queue_op_status are not provided. No lock-free concrete classes ]] + [[X.1.1] [Basic Operations] [Partial] [ - ]] + [[X.1.1.1] [push] [yes] [ - ]] + [[X.1.1.2] [value_pop] [no] [ renamed pull with two flavors + a ptr_pull that returns a sharted_ptr<>. ]] + [[X.1.2] [Non-waiting operations] [] [ - ]] + [[X.1.2.1] [try_push] [Partial] [ return bool instead ]] + [[X.1.2.2] [try_pop] [Partial] [ renamed try_pull, returns null ]] + [[X.1.3] [Non-blocking operations] [] [ - ]] + [[X.1.3.1] [nonblocking_push] [Partial] [ renamed try_push(no_block, ]] + [[X.1.3.2] [nonblocking_pop] [Partial] [ renamed try_pop(no_block, ]] + [[X.1.4] [Push-front operations] [No] [ - ]] + [[X.1.5] [Closed queues] [Partial] [ - ]] + [[X.1.5.1] [close] [Yes] [ - ]] + [[X.1.5.2] [is_closed] [Yes] [ - ]] + [[X.1.5.3] [wait_push] [Partial] [ - ]] + [[X.1.5.4] [wait_pop] [Partial] [ - ]] + [[X.1.5.5] [wait_push_front] [no] [ - ]] + [[X.1.5.6] [wait_pop] [Partial] [ - ]] + [[X.1.5.6] [open] [no] [ - ]] + [[X.1.6] [Empty and Full Queues] [Yes] [ - ]] + [[X.1.6.1] [is_empty] [Yes] [ - ]] + [[X.1.6.2] [is_full] [Yes] [ Added capacity ]] + [[X.1.7] [Queue Names] [No] [ Not considere a must for the time been. ]] + [[X.1.8] [Element Type Requirements] [Yes?] [ - ]] + [[X.1.9] [Exception Handling] [Yes?] [ - ]] + [[X.1.10] [Queue Ordering] [Yes?] [ - ]] + [[X.1.11] [Lock-Free Implementations] [No] [ waiting to stabilize the lock-based interface. Will use Boost.LockFree once it is Move aware. ]] + [[X.2] [Concrete queues] [Partial] [ ]] + [[X.2.1] [Locking Buffer Queue] [Partial] [ classes sync_queue and a sync_bounded_queue. ]] + [[X.2.1] [Lock-Free Buffer Queue] [No] [ ]] + [[X.3] [Additional Conceptual Tools] [No] [ ]] + [[X.3.1] [Fronts and Backs] [No] [ ]] + [[X.3.2] [Streaming Iterators] [No] [ ]] + [[X.3.3] [Storage Iterators] [No] [ ]] + [[X.3.4] [Binary Interfaces] [No] [ ]] + [[X.3.4] [Managed Indirection] [No] [ ]] +] +[endsect] + + +[section:executors Asynchronous Executors] + +While Boost.Thread implementation of executors would not use dynamic polymorphism, it is worth comparing with the current trend on the standard. + +[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3378.pdf N3378 A preliminary proposal for work executors]] + + +[table Asynchronous Executors + [[Section] [Description] [Status] [Comments]] + [[30.X.1] [Class executor] [No] [ - ]] + [[30.X.1.1] [add] [No] [ renamed with a function template submit ]] + [[30.X.1.1] [num_of_pendin_closures] [??] [ ]] + [[30.X.2] [Class sceduled_executor] [No] [ - ]] + [[30.X.2.1] [add_at] [No] [ renamed with a function template submit_at ]] + [[30.X.2.2] [add_after] [No] [ renamed with a function template submit_after ]] + [[30.X.3] [Executor utilities functions] [No] [ - ]] + [[30.X.3.1] [default_executor] [No] [ - ]] + [[30.X.3.2] [set_default_executor] [No] [ - ]] + [[30.X.3.3] [singleton_inline_executor] [No] [ - ]] + [[30.X.4] [Concrete executor classes] [No] [ - ]] + [[30.X.4.1] [loop_executor] [No] [ - ]] + [[30.X.4.1] [serial_executor] [No] [ - ]] + [[30.X.4.1] [thread_pool] [No] [ #8513 ]] +] + +[endsect] + + +[section:async A Standardized Representation of Asynchronous Operations] + +[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf N3558 A Standardized Representation of Asynchronous Operations]] + +[table A Standardized Representation of Asynchronous Operations Conformance + [[Section] [Description] [Status] [Comments]] + [[30.6.6] [Class template future] [Partial] [ - ]] + [[30.6.6.1] [then] [Partial] [ executor interface missing #8516 ]] + [[30.6.6.2] [unwrap] [No] [ #XXXX ]] + [[30.6.6.3] [ready] [yes] [ is_ready ]] + [[30.6.7] [Class template shared_future] [Partial] [ - ]] + [[30.6.7.1] [then] [No] [ #8515 ]] + [[30.6.7.2] [unwrap] [No] [ #XXXX ]] + [[30.6.7.3] [ready] [Yes] [ is_ready ]] + [[30.6.X] [Function template when_any] [No] [ #7446 ]] + [[30.6.X] [Function template when_all] [No] [ #7447 ]] + [[30.6.X] [Function template make_ready_future] [Yes] [ - ]] + [[30.6.8] [Function template async ] [No] [ executor interface missing #7448 ]] +] + +[endsect] + +[section:stream_mutex C++ Stream Mutexes] + +While Boost.Thread implementation of stream mutexes differ in the approach, it is worth comparing with the current trend on the standard. + +[note [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html N3535 - C++ Stream Mutexes]] + +[table C++ C++ Stream MutexesConformance + [[Section] [Description] [Status] [Comments]] + [[X.1] [Class template stream_mutex] [Partial] [ externally_locked_stream<> ]] + [[X.2.1] [constructor] [Partial] [ externally_locked_stream needs a mutex in addition as argumement. ]] + [[X.2.2] [lock] [yes] [ - ]] + [[X.2.3] [unlock] [yes] [ - ]] + [[X.2.4] [try_lock] [yes] [ - ]] + [[X.2.5] [hold] [Yes] [ - ]] + [[X.2.6] [bypass] [Yes] [ - ]] + [[X.2] [Class template stream_guard] [Yes] [ - ]] + [[X.2.1] [stream_guard] [Yes] [ - ]] + [[X.2.2] [~stream_guard] [Yes] [ - ]] + [[X.2.3] [bypass] [Yes] [ - ]] + [[X.3] [Stream Operators] [Yes] [.]] + [[X.4] [Predefined Objects] [No] [.]] ] [endsect] +[endsect] + [endsect] diff --git a/doc/sync_queues_ref.qbk b/doc/sync_queues_ref.qbk index 5dd796ce..4e3f7263 100644 --- a/doc/sync_queues_ref.qbk +++ b/doc/sync_queues_ref.qbk @@ -381,7 +381,7 @@ Non-blocking operations are provided by BlockingQueues [endsect] -[section:sync_bounded_queue Class `sync_bounded_queue<>`] +[section:sync_bounded_queue Class template `sync_bounded_queue<>`] #include namespace boost @@ -470,7 +470,7 @@ Non-blocking operations are provided by BlockingQueues sync_queue& operator>>(sync_queue& sbq, ValueType &elem); } -[section:sync_queue Class `sync_queue<>`] +[section:sync_queue Class template `sync_queue<>`] #include diff --git a/doc/sync_streams.qbk b/doc/sync_streams.qbk index d7ee42cd..06c31d73 100644 --- a/doc/sync_streams.qbk +++ b/doc/sync_streams.qbk @@ -65,15 +65,76 @@ stream_guard& operator=(stream_guard const&) = delete; stream_guard(externally_locked_stream& mtx); stream_guard(externally_locked_stream& mtx, adopt_lock_t); - stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs); + stream_guard(stream_guard&& rhs); ~stream_guard(); // Observers bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT; Stream& get() const; + Stream& bypass() const; + }; } +`stream_guard` is a model of __StrictLock. + +[section:constructor `stream_guard(mutex_type & m)`] + +[variablelist + +[[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]] + +[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] + +] + +[endsect] + +[section:constructor_adopt `stream_guard(mutex_type & m,boost::adopt_lock_t)`] + +[variablelist + +[[Precondition:] [The current thread owns a lock on `m` equivalent to one +obtained by a call to [lock_ref_link `m.lock()`].]] + +[[Effects:] [Stores a reference to `m`. Takes ownership of the lock state of +`m`.]] + +[[Throws:] [Nothing.]] + +] + +[endsect] + + +[section:move_constructor `stream_guard(stream_guard && m)`] + + +[variablelist + +[[Effects:] [Stores a reference to `m`. Invokes [lock_ref_link `m.lock()`].]] + +[[Throws:] [Any exception thrown by the call to [lock_ref_link `m.lock()`].]] + +] + +[endsect] + + +[section:destructor `~stream_guard()`] + +[variablelist + +[[Effects:] [Invokes [unlock_ref_link `m.unlock()`] on the __lockable_concept_type__ +object passed to the constructor.]] + +[[Throws:] [Nothing.]] + +] + +[endsect] + + [endsect] [section:externally_locked_stream Class `externally_locked_stream `] @@ -87,12 +148,12 @@ // Constructors, Assignment and Destructors externally_locked_stream(externally_locked_stream const&) = delete; externally_locked_stream& operator=(externally_locked_stream const&) = delete; - // Effects: Constructs an externally locked object storing the cloaked reference object. externally_locked_stream(Stream& stream, RecursiveMutex& mtx); - // Observers + // Modifiers stream_guard hold(); - Stream& hold(strict_lock& lk); + Stream& bypass() const; + }; } @@ -101,6 +162,26 @@ provides full access to that object through the `get` member functions, provided pass a reference to a strict lock object. +[section:constructor `externally_locked_stream(Stream&, RecursiveMutex&)`] + +[variablelist + +[[Effects:] [Constructs an externally locked object storing the cloaked reference object and its locking mutex.]] + +] + +[endsect] + +[section:hold `hold()`] + +[variablelist + +[[Returns:] [A stream_guard which will hold the mutex during it lifetime .]] + +] + +[endsect] + [endsect] diff --git a/example/not_interleaved.cpp b/example/not_interleaved.cpp index 4efded38..2cd9f7ba 100644 --- a/example/not_interleaved.cpp +++ b/example/not_interleaved.cpp @@ -50,8 +50,8 @@ int main() std::string nm; { strict_lock lk(terminal_mutex); - std::ostream & gcout = mcout.hold(lk); - //std::istream & gcin = mcin.hold(lk); + std::ostream & gcout = mcout.get(lk); + //std::istream & gcin = mcin.get(lk); gcout << "Enter name: "; //gcin >> nm; } diff --git a/include/boost/thread/externally_locked_stream.hpp b/include/boost/thread/externally_locked_stream.hpp index 85c873b4..8d039cef 100644 --- a/include/boost/thread/externally_locked_stream.hpp +++ b/include/boost/thread/externally_locked_stream.hpp @@ -21,12 +21,6 @@ namespace boost { - // inline static recursive_mutex& terminal_mutex() - // { - // static recursive_mutex mtx; - // return mtx; - // } - template class externally_locked_stream; @@ -51,7 +45,7 @@ namespace boost { } - stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs) + stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs) BOOST_NOEXCEPT : mtx_(rhs.mtx_) { rhs.mtx_= 0; @@ -62,15 +56,24 @@ namespace boost if (mtx_ != 0) mtx_->unlock(); } - bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT + bool owns_lock(const mutex_type * l) const BOOST_NOEXCEPT { return l == mtx_->mutex(); } + /** + * @Requires mtx_ + */ Stream& get() const { + BOOST_THREAD_ASSERT_PRECONDITION( mtx_, lock_error() ); return mtx_->get(*this); } + Stream& bypass() const + { + return get(); + } + private: externally_locked_stream* mtx_; @@ -98,22 +101,20 @@ namespace boost /** * Effects: Constructs an externally locked object storing the cloaked reference object. */ - externally_locked_stream(Stream& stream, RecursiveMutex& mtx) : + externally_locked_stream(Stream& stream, RecursiveMutex& mtx) BOOST_NOEXCEPT : base_type(stream, mtx) { } - stream_guard hold() + stream_guard hold() BOOST_NOEXCEPT { return stream_guard (*this); } - - Stream& hold(strict_lock& lk) + Stream& bypass() const { - return this->get(lk); + stream_guard lk(*this); + return get(lk); } - - }; //] diff --git a/include/boost/thread/strict_lock.hpp b/include/boost/thread/strict_lock.hpp index 40fd6848..65d04bd5 100644 --- a/include/boost/thread/strict_lock.hpp +++ b/include/boost/thread/strict_lock.hpp @@ -73,7 +73,6 @@ namespace boost // observers - private: /** * @return the owned mutex. @@ -82,12 +81,19 @@ namespace boost { return &mtx_; } - public: + + /** + * @return whether this lock is locking a mutex. + */ + bool owns_lock() const BOOST_NOEXCEPT + { + return true; + } /** * @return whether this lock is locking that mutex. */ - bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT + bool owns_lock(const mutex_type* l) const BOOST_NOEXCEPT { return l == mutex(); } /*< strict locks specific function >*/ @@ -173,7 +179,6 @@ namespace boost } // observers -private: /** * return @c the owned mutex. */ @@ -181,7 +186,15 @@ private: { return tmp_lk_.mutex(); } -public: + + /** + * @return whether this lock is locking a mutex. + */ + bool owns_lock() const BOOST_NOEXCEPT + { + return true; + } + /** * @return whether if this lock is locking that mutex. */