Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r51168 - sandbox/synchro/libs/synchro/doc
From: vicente.botet_at_[hidden]
Date: 2009-02-09 18:44:08


Author: viboes
Date: 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
New Revision: 51168
URL: http://svn.boost.org/trac/boost/changeset/51168

Log:
Boost.Synchro V0.0.0
Added:
   sandbox/synchro/libs/synchro/doc/Jamfile.v2 (contents, props changed)
   sandbox/synchro/libs/synchro/doc/acknowledgements.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/appendices.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/case_studies.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/changes.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/getting_started.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/history.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/implementation.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/index.html (contents, props changed)
   sandbox/synchro/libs/synchro/doc/installation.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/introduction.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/introduction_traits_and_concepts.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/overview.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/rationale.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/reference.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/references.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/synchro.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/tutorial.qbk (contents, props changed)
   sandbox/synchro/libs/synchro/doc/users_guide.qbk (contents, props changed)

Added: sandbox/synchro/libs/synchro/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/Jamfile.v2 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,72 @@
+# Boost.LUID library documentation Jamfile ---------------------------------
+#
+# Copyright Vicente J. Botet Escriba 2008. Use, modification and
+# distribution is subject to 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)
+#
+# See http://www.boost.org for updates, documentation, and revision history.
+
+#import doxygen ;
+import quickbook ;
+
+#doxygen autodoc
+# :
+# [ glob ../../../boost/interprocess/*.hpp ]
+# [ glob ../../../boost/interprocess/allocators/*.hpp ]
+# :
+# <doxygen:param>EXTRACT_ALL=NO
+# <doxygen:param>HIDE_UNDOC_MEMBERS=YES
+# <doxygen:param>EXTRACT_PRIVATE=NO
+# <doxygen:param>EXPAND_ONLY_PREDEF=YES
+# <doxygen:param>PREDEFINED=BOOST_INTERPROCESS_DOXYGEN_INVOKED
+# <xsl:param>"boost.doxygen.reftitle=Boost.Interprocess Reference"
+# ;
+
+xml synchro : synchro.qbk ;
+
+boostbook standalone
+ :
+ synchro
+ :
+ # HTML options first:
+ # Use graphics not text for navigation:
+ <xsl:param>navig.graphics=1
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=2
+ # Don't put the first section on the same page as the TOC:
+ <xsl:param>chunk.first.sections=1
+ # How far down sections get TOC's
+ <xsl:param>toc.section.depth=4
+ # Max depth in each TOC:
+ <xsl:param>toc.max.depth=2
+ # How far down we go with TOC's
+ <xsl:param>generate.section.toc.level=10
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ # Path for libraries index:
+ <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
+ # Or enable this if you're using XEP:
+ <xsl:param>xep.extensions=1
+ # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
+ <xsl:param>fop.extensions=0
+ # No indent on body text:
+ <xsl:param>body.start.indent=0pt
+ # Margin size:
+ <xsl:param>page.margin.inner=0.5in
+ # Margin size:
+ <xsl:param>page.margin.outer=0.5in
+ # Yes, we want graphics for admonishments:
+ <xsl:param>admon.graphics=1
+ # Set this one for PDF generation *only*:
+ # default pnd graphics are awful in PDF form,
+ # better use SVG's instead:
+ <format>pdf:<xsl:param>admon.graphics.extension=".svg"
+ <format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
+ ;

Added: sandbox/synchro/libs/synchro/doc/acknowledgements.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/acknowledgements.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,12 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[section:acknowledgements Appendix D: Acknowledgements]
+
+TBC
+
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/appendices.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/appendices.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,33 @@
+[/
+[/
+ (C) Copyright 2008 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).
+]
+
+[/=================]
+[section Appendices]
+[/=================]
+
+[include history.qbk]
+
+[include rationale.qbk]
+
+[include implementation.qbk]
+
+[include acknowledgements.qbk]
+
+
+[/=====================================]
+[section:todo Appendix E: Future plans]
+[/=====================================]
+
+[heading Tasks to do before review]
+
+[heading For later releases]
+
+[endsect]
+
+[endsect]
+

Added: sandbox/synchro/libs/synchro/doc/case_studies.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/case_studies.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,15 @@
+[/
+ (C) Copyright 2008 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).
+]
+
+[/============================]
+[section Examples]
+[/============================]
+
+This section includes complete examples using the library.
+
+
+[endsect]
\ No newline at end of file

Added: sandbox/synchro/libs/synchro/doc/changes.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/changes.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,43 @@
+[/
+ (C) Copyright 2008 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).
+]
+
+[section:changes Appendix A: History]
+
+[heading [*Version 0.2, December 07, 2008] ['Movable thread tuples, Threader and test on more toolsets]]
+
+[*Features:]
+
+* Make movable thread_tuple_once and thread_group_once
+* Threader/joiner classes
+
+[*Toolsets:]
+
+* Tested with static and shared lib.
+* Tested on Linux gcc 3.4.6.
+* Tested on Linux gcc 4.1.2.
+* Modification helping Windows.
+
+[*Bugs:]
+
+* basic_keep_alive example do not link.
+
+[heading [*Version 0.1, November 30, 2008] ['Announcement of Interthreads]]
+
+[*Features:]
+
+* thread setup/cleanup decorator,
+* thread specific shared pointer,
+* thread keep alive mechanism,
+* thread tuples, set_once synchrohonizer, thread_tuple_once and thread_group_once.
+
+[heading [*Bugs:]]
+
+[*v0.1#1: basic_keep_alive example do not link.]
+
+
+
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/getting_started.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/getting_started.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,25 @@
+[/
+[/
+ (C) Copyright 2008 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).
+]
+
+
+[/======================================]
+[section:getting_started Getting Started]
+[/======================================]
+
+[include installation.qbk]
+
+[/=============================]
+[section Hello World! ]
+[/=============================]
+
+
+[endsect]
+
+[endsect]
+
+

Added: sandbox/synchro/libs/synchro/doc/history.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/history.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,18 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[section:history Appendix A: History]
+
+[variablelist
+[
+ [Mars 23, 2008]
+ [Synchro is born.
+ ]
+]
+]
+
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/implementation.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/implementation.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,14 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[section:implementation Appendix C: Implementation Notes]
+
+
+TBC
+
+
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/index.html
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/index.html 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,9 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=html/index.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+../../doc/html/luid.html
+</body>
+</html>

Added: sandbox/synchro/libs/synchro/doc/installation.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/installation.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,81 @@
+[/
+ (C) Copyright 2008 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).
+]
+
+
+[/======================================]
+[section:install Installing Synchro]
+[/======================================]
+
+[/=================================]
+[heading Getting Boost.Synchro]
+[/=================================]
+
+You can get the last stable release of Boost.Synchro by downloading [^synchro.zip] from the
+[@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming Boost Vault]
+
+You can also access the latest (unstable?) state from the [@https://svn.boost.org/svn/boost/sandbox/synchro Boost Sandbox].
+
+[/=================================]
+[heading Building Boost.Synchro]
+[/=================================]
+
+There is no need to compile [*Boost.Synchro], since it's
+a header only library. Just include your Boost header directory in your
+compiler include path.
+
+[/=========================]
+[heading Requirements]
+[/=========================]
+
+[*Boost.Synchro] depends on Boost. You must use either Boost version 1.35.x
+or the version in SVN trunk. In particular, [*Boost.Synchro] depends on:
+
+
+[variablelist
+[
+ [[@http://www.boost.org/libs/interprocess [*Boost.Interprocess]]]
+ [interprocess synchronization primitives]
+]
+[
+ [[@http://www.boost.org/libs/mpl [*Boost.MPL]]]
+ [for all the meta programing task]
+]
+[
+ [[@http://www.boost.org/libs/thread [*Boost.Thread]]]
+ [thread synchronization primitives]
+]
+]
+
+
+[/========================]
+[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.
+
+[/====================]
+[heading Thread safety]
+[/====================]
+
+All functions in the library are exception-safe except:
+
+
+[/=======================]
+[heading Tested compilers]
+[/=======================]
+Currently, [*Boost.Synchro] has been tested in the following compilers/platforms:
+
+* GCC 3.4.4 Cygwin
+* GCC 3.4.6 Linux
+* GCC 4.3.2 Cygwin
+* GCC 4.1.2 Linux
+
+[note Please send any questions, comments and bug reports to boost <at> lists <dot> boost <dot> org.]
+
+[endsect]
+

Added: sandbox/synchro/libs/synchro/doc/introduction.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/introduction.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,153 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[section:intro Introduction]
+
+
+[*Description]
+
+To date, C++ multi threaded programs that need to be efficient use the same mutexes,
+semaphores, and events that Dijkstra described 40 years ago. This unfortunate state
+of affairs makes multi threaded programs difficult to design, debug, ensure correct,
+optimize, maintain, and analyze formally. Consequently, building tools that automate
+detection of race conditions and deadlocks is highly desirable.
+
+[*Boost.Synchro] provides:
+
+* A uniforme usage of Boost.Thread and Boost.Interprocess synchronization mechanisms
+based on some lock concepts, lock traits and locking families.
+* semaphore, null_mutex and null_condition
+* Some lockers are also provided as `strict_locker`, `nested_strict_locker`,
+`condition_locker`, `locking_ptr`, `externally_locked`, `reverse_lock`.
+* Introduce high-level abstractions for handling more complicated
+synchronization problems, including monitor for guaranteeing exclusive access to an object,
+and a so-called rendezvous mechanism for handling direct communication between
+objects.
+* In addition a polymorph lockable hierarchy is also included.
+
+This library is much more a compilation of what I have found in the literature
+that is not yet present in Boost.
+
+Other abstractions that I would also like to see soon in Boost are futures, task
+schedulers, continuations, coroutines, non-premptyble threads, ...
+
+[include introduction_traits_and_concepts.qbk]
+
+
+[section:conc Concurrent components]
+
+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.
+
+Concurrent execution of objects requires a mechanism
+for synchronizing the access to shared objects, just as direct communication
+between objects may require synchronization. The basic mechanism for synchronization in
+Boost.Threads and Boost.Interprocess are the well known mutex and condition_variables. Mutexes
+and condition variables are, however, only useful for very simple synchronization problems.
+The Synchro Library therefore introduce high-level abstractions for handling more complicated
+synchronization problems, including monitor for guaranteeing exclusive access to an object,
+and a so-called rendezvous mechanism for handling direct communication between
+objects. All the concurrency abstractions being introduced are defined by
+means of mutexes an conditions.
+
+[endsect]
+
+[section:lockers Lockers]
+
+Typically, object-oriented programs use object-level locking by associating a
+synchronization object (mutex) with each object that is susceptible to be shared
+between threads. Then, code that manipulates the state of the object can synchronize
+by locking that object. Inside a synchronized section, the mutex associated with the
+object is locked, and consequently that object's fields can be accessed safely.
+
+In C++, this fundamental idiom is typically implemented with a helper Locker object.
+
+A locker is any object or function responsible for coordinating the use of lockable objects
+
+* Lockers depend on lockable objects - which need not be locking primitives - and not vice-versa.
+This avoids cycles in the dependency graph
+* Lockers are applications of lockable objects and, as such, form a potentially unbounded family
+Most common role of lockers is for exception safety and programming convenience
+* Lockers execute-around the lock-unlock pairing.
+
+A locker defines an execution strategy for locking and unlocking that
+is automated by construction and destruction. It simplifies common
+use of locking, and does so in an exception-safe fashion. As such,
+lockers depend on the interface of lockables -e.g. lock and unlock
+- but lockables do not depend on lockers. The relationship is strictly
+layered, open and extensible: lockable types may be whole, externally
+locked objects against which existing lockers can be used; new lockers
+can be defined that work against existing lockable types.
+
+Boost.Thread and Boost.Interprocess defines already a good starting point with these lockers:
+
+* `boost::lock_guard`,
+* `boost::unique_lock`, `boost::interprocess::unique_lock` and `boost::interprocess::scoped_lock`
+* `boost::share_lock` and `boost::interprocess::sharable_lock`
+* `boost::upgrade_lock` and `boost::interprocess::upgradable_lock`.
+
+[*Strict lockers]
+
+A `strict_locker` is a scoped lock guard ensuring the mutex is locked on the
+scope of the lock, by locking the mutex on construction and unlocking it on
+destruction.
+
+The library provides two strict lockers
+
+* `strict_locker`
+* `neested_strict_locker`
+
+and a meta function `is_strict_locker` which states if a locker is a strict locker
+
+Substitutability between lockables and lockers does not make sense,
+so the constructor is explicit. Implicit copyability is also disabled.
+strict_lockers are not Lockables.
+
+
+[*External lockers]
+
+An alternative or complementary approach to internal locking is
+to support external locking for an object - Multiple calls may be
+grouped within the same externally defined critical region.
+
+External locking has some associated risks for high-level objects.
+Incorrect usage can be too easy: a forgotten call to lock or unlock is
+more likely than with synchronisation primitives because the focus of
+using the object is on the rest of its non-Lockable interface, so it
+becomes easy to forget that to use the interface correctly also requires
+participation in a locking scheme.
+
+To some extent lockers can help, but such a co-operative scheme
+should only be employed when internal locking is too restricted for a
+given use, e.g. multiple operations must be performed together.
+Ideally, if such operations are common they should be defined
+internally locked and defined in the interface of the object as
+Combined Methods.
+Assuming that locks are re-entrant, external locking can be provided
+to complement the more encapsulated internal locking, i.e. by default
+if you want to call a single function you just call it and it
+automatically locks, but if you want to call multiple functions
+together you first apply an external lock.
+
+The library provides a `externally_locked` class that allows to access a
+externally locked class in a thread safe mode through strict lockers.
+
+Where only external locking is used, a safe approach is needed for
+calling single functions easily. The library provides two classes
+
+* `locking_ptr` and
+* `on_dereference_locking_ptr`
+
+[endsect]
+
+[section:poly Polymorphic lockable]
+
+[endsect]
+
+[endsect]
\ No newline at end of file

Added: sandbox/synchro/libs/synchro/doc/introduction_traits_and_concepts.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/introduction_traits_and_concepts.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,113 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+
+[section:uniform Using thread, Interprocess and null synchronization mechanisms uniformly]
+
+One of the problems when doing multi threaded application with Bosst.Thread and
+Boost.Interprocess is that the synchronization mechanism of these two libraries
+even if they are very close since the release 1.35, there are some minor
+differences that make quite difficult to design a class that can work
+independently with synchronization mechanisms of both libraries.
+
+This library proposes some classes that allows to write code that can be used
+distinguishably with thread or interprocess synchronization mechanisms. It is inspired on the work
+from [*C++ Threading - A Generic-Programming Approach] - Kevlin Henney and
+[*An OO Encapsulation of Lightweight OS Concurrency Mechanisms in the ACE Toolkit] Douglas C. Schmidt.
+
+
+[*Lock substitutability]
+
+The Boost (C++0x) mutexes have associated a category which form a subtyping hierarchy:
+ExclusiveLock <- SharableLock <- UpgradableLock
+
+ exclusive_lock <- sharable_lock <- upgradable_lock
+
+[category_tag_hierarchy]
+
+Locking behaviour can be further cathegorized as:
+
+* Re-entrancy: recursive or not
+
+ non_recursive <- recursive
+
+* Scope: whether the lock is usable with a mono-threaded, multi-threaded or multi-process context
+
+ mono_threaded <- multi_threaded <- multi_process
+
+* Lifetime: The lifetime of a lock coudl be associated to the process, the kernel or the filesystem
+
+ process_lifetime <- kernel_lifetime <- filesystem_lifetime
+
+* Timed interface: has or not a timed interfaces
+
+ hasnt_timed_interface <- has_timed_interface
+
+Substitutability applies both to the degree of syntactic support and to the locking semantics
+
+* A recursive mutex and binary semaphore are substitutable in code written against a exclusive mutex
+* A null mutex is substitutable for all others in a single-threaded environment
+
+
+We can see these axes of variation expressed against some
+Boost synchronisation mechanisms (from now bip stands for boost::interprocess):
+
+* boost::mutex: ExclusiveLock, non-recursive, has-not-timed-interface, multi-threaded
+* boost::shared_mutex: UpgradableLock, non-recursive, has-timed-interface, multi-threaded
+* bip::synchro::null_mutex: UpgradableLock, recursive, has-timed-interface, mono-threaded
+* bip::synchro::interprocess_recursive_mutex ExclusiveLock, recursive, has-timed-interface, multi_process.
+
+[*Lock traits]
+
+The Boost.Synchro library contains a set of very specific traits classes, some of them encapsulate a single trait for
+a Lockable type; for example, is a lock recursive (is_recursive), is useful in a multi threaded context
+(is_multi_threaded).
+
+The Boost.Synchro lock-traits classes share a unified design that mimic the one of Boost.TypeTraits: each class
+inherits from a the type true_type if the type has the specified property and inherits from false_type otherwise.
+
+Boost.Synchro also contains a set of classes that perform a specific transformation on a type;
+for example, they can remove a top-level const or volatile qualifier from a type.
+Each class that performs a transformation defines a single typedef-member type that is the result of the transformation.
+
+[*Finding the best lock]
+
+Inverse traits can match a lockable type based on specific traits, for a given family of lock types.
+
+It is also possible to specify characteristics to perform a reverse lookup to find a primitive lock type, either by
+exact match or by substitutable match.
+
+[*Synchrohronization familly]
+
+A class that will do internal locking can be parameterized by the type of synchronization familly needed to achieve
+the desired level of concurrency control. This depends of the usage scope of this class, and this can be
+mono_threaded, multi_threaded, multi_process.
+
+For example the thread_synchronization_familly can be used to instantiate a message_queue class in a multi_threaded
+environment, all public methods will be thread-safe, with the corresponding overhead that implies. In contrast, if a
+null_synchronization_policy class is used to instantiate message_queue, all public methods will not be thread-safe,
+and there will be no additional overhead.
+
+[*Syntactic lock traits]
+
+The Boost.Synchro library also contains classes that try to remove the syntactic differences between the synchronization
+mechanisms of the Boost.Thread and Boost::Interprocess libraries. The differences identified up to now are:
+
+* The scoped locks live in a different namespace and some have different names with the same semantic. IMO these
+should be shared.
+* The exception thrown lives in a different name space and different names with the same semantic.
+* This exception should be common.
+* The move semantics (&&) are expressed with a class named differently. This class could be a good candidate of Boost
+library by itself.
+* The scoped locks can be initialized with static const variables in order to overload the constructor for lock
+adoption, lock deferral or try to lock. Even if the name of these variables is the same, these variables live in
+different namespace. It would be nice if these both libraries use the same type and the same variables
+
+I hope that these two Boost libraries will merge their synchronization mechanisms in a near future. Waiting for this merge this could serve as a temporary solution.
+
+[endsect]
+

Added: sandbox/synchro/libs/synchro/doc/overview.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/overview.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,74 @@
+[/
+ (C) Copyright 2008 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).
+]
+
+[/========================]
+[section:overview Overview]
+[/========================]
+
+[/==================]
+[heading Description]
+[/==================]
+
+To date, C++ multi threaded programs that need to be efficient use the same mutexes,
+semaphores, and events that Dijkstra described 40 years ago. This unfortunate state
+of affairs makes multi threaded programs difficult to design, debug, ensure correct,
+optimize, maintain, and analyze formally. Consequently, building tools that automate
+detection of race conditions and deadlocks is highly desirable.
+
+[*Boost.Synchro] provides:
+
+* A uniforme usage of Boost.Thread and Boost.Interprocess synchronization mechanisms
+based on some lock concepts, lock traits and locking families.
+* semaphore, null_mutex and null_condition
+* Some lockers are also provided as `strict_locker`, `nested_strict_locker`,
+`condition_locker`, `locking_ptr`, `externally_locked`, `reverse_lock`.
+* Introduce high-level abstractions for handling more complicated
+synchronization problems, including monitor for guaranteeing exclusive access to an object,
+and a so-called rendezvous mechanism for handling direct communication between
+objects.
+* In addition a polymorph lockable hierarchy is also included.
+
+This library is much more a compilation of what I have found in the literature
+that is not yet present in Boost.
+
+Other abstractions that I would also like to see soon in Boost are futures, task
+schedulers, continuations, coroutines, non-premptyble threads, ...
+
+[/====================================]
+[heading How to Use This Documentation]
+[/====================================]
+
+This documentation makes use of the following naming and formatting conventions.
+
+* 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 `()`
+ 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 `<>`
+ 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
+ trailing `()`.
+* Names that refer to /concepts/ in the generic programming sense are
+ specified in CamelCase.
+
+[note In addition, notes such as this one specify non-essential information that
+provides additional background or rationale.]
+
+Finally, you can mentally add the following to any code fragments in this document:
+
+ // Include all of InterThreads
+ #include <boost/synchro/synchro.hpp>
+
+ // Create a namespace aliases
+ namespace bsynchro = boost::synchro;
+
+[include introduction.qbk]
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/rationale.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/rationale.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,12 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[section:rationale Appendix B: Rationale]
+
+TBC
+
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/reference.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/reference.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,921 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[section Reference]
+
+[/==========================================================================================]
+[section Header `<boost/synchro/lock_generator.hpp>`]
+[/==========================================================================================]
+
+[endsect]
+
+[/==========================================================================================]
+[section Header `<boost/synchro/lockable_concept.hpp>`]
+[/==========================================================================================]
+
+
+[section Class `exclusive_lockable`]
+[*Synopsis]
+Polimorphic exclusive lock interface.
+
+[*Description]
+The boost::mutex and boost:interprocess mutex family classes are a non-polymorphic
+classes that encapsulates
+a system primitive and portion of C API. Clearly, many of the synchronisation
+primitives support common operations, and hence interfaces. In some cases a more
+general interface is useful.
+The exclusive_lockable interface class may be used explicitly as a base class for a
+class supporting exclusive synchronisation.
+
+[*`exclusive_lock` public member functions]
+
+# `;`
+
+[endsect]
+
+[endsect]
+
+[/==========================================================================================]
+[section Header `<boost/synchro/locker_concept.hpp>`]
+[/==========================================================================================]
+
+ template <typename Lockable> struct LockableConcept;
+ template <typename Lockable> struct TimedLockableConcept;
+ template <typename Lockable> struct ShareLockableConcept;
+ template <typename Lockable> struct UpgradeLockableConcept;
+
+
+[section Template Class `LockableConcept`]
+
+
+
+[endsect]
+
+[section Template Class `TimedLockableConcept`]
+
+
+
+[endsect]
+[section Template Class `ShareLockableConcept`]
+
+
+
+[endsect]
+[section Template Class `UpgradeLockableConcept`]
+
+
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/make_lockable.hpp>`]
+[/==========================================================================================]
+
+ template <typename Lockable> class make_exclusive_lockable;
+ template <typename TimedLock> class make_timed_lockable;
+ template <typename SharableLock> class make_share_lockable;
+ template <typename UpgradableLock> class make_upgrade_lockable;
+ template <typename Lockable, typename category, typename timed_interface>
+ struct make_lockable;
+
+
+
+[endsect]
+
+[/==========================================================================================]
+[section Header `<boost/synchro/monitor.hpp>`]
+[/==========================================================================================]
+
+template <
+ typename Lockable,
+ class Condition,
+ class ConditionBoosted
+>
+class exclusive_monitor;
+
+[endsect]
+
+[/==========================================================================================]
+[section Header `<boost/synchro/null_condition.hpp>`]
+[/==========================================================================================]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/null_mutex.hpp>`]
+[/==========================================================================================]
+
+[endsect]
+
+[/==========================================================================================]
+[section Header `<boost/synchro/null_synchronization_family.hpp>`]
+[/==========================================================================================]
+
+[section Class `null_synchronization_policy`]
+
+[*Synopsis]
+
+
+ struct null_synchronization_policy
+ {
+ typedef boost::interprocess::null_mutex mutex_type;
+ typedef boost::interprocess::null_mutex recursive_mutex_type;
+ typedef boost::interprocess::null_mutex timed_mutex_type;
+ typedef boost::interprocess::null_mutex recursive_timed_mutex_type;
+ typedef boost::interprocess::null_mutex shared_mutex_type;
+ typedef boost::condition_variable_any condition_variable_type;
+ };
+
+[*Description]
+
+[*`nesteed_strict_locker` public types]
+
+# `;`
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/semaphore.hpp>`]
+[/==========================================================================================]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/process_synchronization_family.hpp>`]
+[/==========================================================================================]
+
+[section Class `process_synchronization_family`]
+
+[*Synopsis]
+
+ struct process_synchronization_family
+ {
+ typedef boost::interprocess::interprocess_mutex mutex_type;
+ typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type;
+ typedef boost::interprocess::interprocess_mutex timed_mutex_type;
+ typedef boost::interprocess::interprocess_recursive_mutex recursive_timed_mutex_type;
+ typedef boost::interprocess::interprocess_upgradable_mutex shared_mutex_type;
+ typedef boost::interprocess::interprocess_condition condition_variable_type;
+ };
+
+[*Description]
+
+[*`process_synchronization_family` public member types]
+
+# `;`
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/thread_synchronization_family.hpp>`]
+[/==========================================================================================]
+
+[section Class `thread_synchronization_family`]
+
+[*Synopsis]
+
+ struct thread_synchronization_family
+ {
+ typedef boost::mutex mutex_type;
+ typedef boost::recursive_mutex recursive_mutex_type;
+ typedef boost::timed_mutex timed_mutex_type;
+ typedef boost::recursive_timed_mutex recursive_timed_mutex_type;
+ typedef boost::shared_mutex shared_mutex_type;
+ typedef boost::condition_variable_any condition_variable_type;
+ };
+
+
+[endsect]
+
+
+
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/locker/condition_locker.hpp>`]
+[/==========================================================================================]
+
+ template <typename Condition> struct condition_backdoor;
+ template <typename Condition> class condition_safe;
+ template <typename Condition> class condition_safe_boosted;
+ template <typename Lockable, typename Condition>
+ class condition_unique_locker
+ template <typename Lockable, typename Condition>
+ class condition_shared_locker
+
+ template <typename Lockable, typename Condition>
+ class condition_unique_lockable
+ template <typename Lockable, typename Condition>
+ class condition_shared_lockable
+
+
+[section Template Class `condition_backdoor`]
+
+ template <class Condition>
+ struct condition_backdoor {
+ condition_backdoor(condition_safe<Condition>&cnd);
+ template <typename Locker>
+ void wait(Locker& lock);
+ template <typename Locker>
+ bool wait_until(Locker& lock, boost::system_time const& abs_time);
+ template<typename Locker, typename duration_type>
+ bool wait_for(Locker& lock, duration_type const& rel_time);
+
+ template <typename Locker, typename Predicate>
+ void wait_when(Locker& lock, Predicate pred);
+ template<typename Locker, typename predicate_type>
+ bool wait_when_until(Locker& lock, predicate_type pred, boost::system_time const& abs_time);
+ template<typename Locker, typename predicate_type, typename duration_type>
+ bool wait_when_for(Locker& lock, predicate_type pred, duration_type const& rel_time);
+
+ template <typename Locker>
+ void notify_one(Locker& lock);
+ template <typename Locker>
+ void notify_all(Locker& lock);
+ };
+
+[endsect]
+
+[section Template Class `condition_safe`]
+
+ template <class Condition>
+ class condition_safe {
+ public:
+ typedef Condition condition;
+ typedef condition_backdoor<Condition> backdoor;
+ void notify_one();
+ void notify_all();
+ };
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/locker/externally_locked.hpp>`]
+[/==========================================================================================]
+
+
+[section Template Class `externally_locked`]
+[*Synopsis]
+
+ template <class T, class Lockable>
+ class externally_locked {
+ public:
+ externally_locked(Lockable& owner);
+ externally_locked(const T& obj, Lockable& own);
+
+ template <typename Locker>
+ T& get(Locker& locker);
+ void set(const T& obj, Lockable& owner);
+ };
+
+[*Description]
+`externally_locked` cloaks an object of type T, and actually provides full access to that object through
+the get and set member functions, provided you pass a reference to a strict_locker<Lockable> object.
+
+[*`externally_locked` template parameters]
+
+* `T` : the type locked externally
+* `Lockable` : The lockable type used to synchronize the access to a T instance
+
+[*`externally_locked` public member functions]
+
+* `template <typename Locker> T& get(Locker& locker);`
+
+[*Requires:] mpl:and_<is_strict_locker<Locker>, is_same<lockable_type_trait<Locker>, Lockable>.
+
+[*Returns:] a reference to the type locked externally.
+
+[*Throws:] lock_error when the locker do not owns the lockable instance
+
+* `void set(const T& obj, Lockable& owner);`
+
+[*Effect:] reinit the type and lockable references with the given values.
+
+[*Example:]
+See
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/locker/is_strict_locker.hpp>`]
+[/==========================================================================================]
+
+
+[section Template Class `is_strict_locker`]
+
+ template <typename Locker>
+ struct is_strict_locker {
+ typedef unspecified value;
+ };
+
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/locker/locking_ptr.hpp>`]
+[/==========================================================================================]
+
+[section Class `locking_ptr`]
+
+[*Synopsis]
+
+ template <typename T, typename Lockable>
+ class locking_ptr : private boost::noncopyable {
+ public:
+ typedef T value_type;
+ typedef Lockable mutex_type;
+
+ locking_ptr(volatile value_type& obj, mutex_type& mtx);
+ ~locking_ptr();
+
+ value_type& operator*();
+ const value_type& operator*() const;
+ value_type* operator->();
+ const value_type* operator->() const;
+ };
+
+[*Description]
+
+The `locking_ptr` overloads `operator->` to return a temporary object that will
+perform the locking. This too provides an `operator->`. Calls to `operator->`
+are automatically chained by the compiler until a raw pointer type is returned. In
+pointer's `operator->` the lock is applied and in its destructor, called at the
+end of a full expression, it is released.
+
+[warning Programmers should be careful about attempting to access the same object twice in
+a statement using `locking_ptr`: this will cause deadlock if the synchronisation
+strategy is not re-entrant.]
+
+[*Example Code]
+
+
+[*`locking_ptr` constructors:destructors]
+# `locking_ptr(volatile value_type& obj, mutex_type& mtx);`
+# `~locking_ptr();`
+
+[*`locking_ptr` public member functions]
+
+# `value_type& operator*();`
+# `const value_type& operator*() const;`
+# `value_type* operator->();`
+# `const value_type* operator->() const;`
+
+[endsect]
+
+[section Class `sharable_locking_ptr`]
+[*Synopsis]
+
+ template <typename T, typename SharableLockable>
+ class sharable_locking_ptr
+ : private boost::noncopyable {
+ public:
+ typedef T value_type;
+ typedef SharableLockable mutex_type;
+
+ sharable_locking_ptr(volatile value_type& obj, mutex_type& mtx);
+ ~sharable_locking_ptr();
+
+ value_type& operator*();
+ const value_type& operator*() const;
+ value_type* operator->();
+ const value_type* operator->() const;
+ };
+
+ template <typename T, typename SharableLockable>
+ class sharable_locking_ptr<const T, SharableLockable>
+ : private boost::noncopyable {
+ public:
+ typedef T value_type;
+ typedef SharableLockable mutex_type;
+
+ sharable_locking_ptr(
+ volatile const value_type& obj,
+ mutex_type& mtx);
+ ~sharable_locking_ptr();
+
+ value_type& operator*();
+ const value_type& operator*() const;
+ value_type* operator->();
+ const value_type* operator->() const;
+ };
+
+[*Description]
+
+[*`nesteed_strict_locker` public member functions]
+
+# `;`
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/locker/on_derreference_locking_ptr.hpp>`]
+[/==========================================================================================]
+
+[section Class `on_derreference_locking_ptr`]
+[*Synopsis]
+
+ template<typename T, typename Lockable>
+ class on_derreference_locking_ptr
+ {
+ public:
+ class pointer
+ {
+ public:
+ explicit pointer(T* target, Lockable* mutex);
+ ~pointer();
+ T *operator->();
+ };
+
+ explicit on_derreference_locking_ptr(T &target, Lockable& mutex);
+ pointer operator->() const;
+ };
+
+[*Description]
+
+[*`nesteed_strict_locker` public member functions]
+
+# `;`
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/locker/reverse_lock.hpp>`]
+[/==========================================================================================]
+
+[section Class `reverse_lock`]
+A reverse (or anti) lock.
+
+[*Synopsis]
+
+[*Description]
+
+This is an interesting adapter class that changes a lock into a reverse lock, i.e.,
+`lock` on this class calls `unlock` on the lockable, and `unlock` on this class
+calls `lock` on the lock. One motivation for this class is when we temporarily
+want to release a lock (which we have already acquired) but then reacquire it soon
+after.
+
+
+[*`reverse_lock` public member functions]
+
+# `;`
+# `;`
+# `;`
+
+[endsect]
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/locker/strict_loker.hpp>`]
+[/==========================================================================================]
+
+[section Class `strict_locker`]
+[*Synopsis]
+
+[strict_locker_synopsis]
+[*Description]
+
+[Note strict_locker is not a model of Locable concept.]
+
+[*`strict_locker` template parameters]
+
+* `Lockable` : The exclusive lockable type used to synchronize exclusive access
+
+[*`strict_locker` public types]
+
+* `lockable_type` : The exclusive lockable type used to synchronize exclusive access
+* `lock_error` : The exception type throw incase of errors
+* `bool_type` : The bool_type of the safe_bool idiom
+
+[*`nesteed_strict_locker` public member functions]
+
+* `explicit strict_locker(lockable_type& obj);`
+* `~strict_locker();`
+* `operator bool_type() const;`
+* `bool operator!() const;`
+* `operator bool_type() const;`
+* `lockable_type* mutex() const;`
+* `lockable_type* get_lockable() const;`
+
+[*`nesteed_strict_locker` private and not defined member functions]
+
+* `strict_locker()`
+* `strict_locker(strict_locker&);`
+* `operator=(strict_locker&);`
+* `operator&();`
+* `void* operator new(std::size_t)`
+* `void* operator new[](std::size_t)`
+* `void operator delete(void*)`
+* `void operator delete[](void*)`
+
+[endsect]
+[section Class `nesteed_strict_locker`]
+[*Synopsis]
+
+ template <typename Locker>
+ class nesteed_strict_locker : private boost::noncopyable {
+ public:
+ typedef typename locker_traits<Locker>::bad_lock bad_lock;
+
+ nesteed_strict_locker(Locker& lock);
+ ~nesteed_strict_locker();
+
+ typedef unspecified bool_type;
+ operator bool_type() const;
+
+ bool operator!() const
+ bool owns_lock() const
+ Mutex* mutex() const
+ private:
+ strict_locker();
+ BOOST_NON_ALIAS(strict_locker);
+ BOOST_NON_HEAP_ALLOCATED();
+ };
+
+[*Description]
+
+[*`nesteed_strict_locker` public member functions]
+
+# `;`
+
+[endsect]
+
+[section Template Class `reverse_locker`]
+A reverse (or anti) locker.
+
+[*Synopsis]
+
+[*Description]
+`unlock` on construction and `lock` destruction.
+
+[*`reverse_locker` public member functions]
+
+# `;`
+# `;`
+# `;`
+
+[*Example Code]
+
+[endsect]
+
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/conc/concurrent_component.hpp>`]
+[/==========================================================================================]
+
+ class port;
+ class object_port;
+ template <typename TYPE> class qualified_port;
+ class concurrent_component;
+
+[section Class `port`]
+
+ class port {
+ public:
+ class synchronizer {
+ synchronizer(port& that);
+ ~synchronizer() {
+ };
+ port();
+ ~port();
+ void accept();
+ bool accept_until(const boost::posix_time::ptime &abs_time);
+ template<typename TimeDuration>
+ bool accept_for(TimeDuration const& rel_time);
+ };
+
+[endsect]
+
+[section Class `object_port`]
+
+ class object_port {
+ public:
+ class synchronizer {
+ synchronizer(object_port& that, const concurrent_component_base* snd);
+ ~synchronizer() {
+ };
+ object_port();
+ ~object_port();
+ void accept(const void* snd);
+ bool accept_until(const void* snd, const boost::posix_time::ptime &abs_time);
+ template<typename TimeDuration>
+ bool accept_for(const void* snd, TimeDuration const& rel_time);
+ };
+
+[endsect]
+
+[section Class `qualified_port`]
+
+ template <typename TYPE>
+ class qualified_port {
+ public:
+ class synchronizer {
+ synchronizer(qualified_port& that, const concurrent_component_base* snd);
+ ~synchronizer() {
+ };
+ object_port();
+ ~object_port();
+ void accept(const TYPE* snd);
+ bool accept_until(const TYPE* snd, const boost::posix_time::ptime &abs_time);
+ template<typename TimeDuration>
+ bool accept_for(const TYPE* snd, TimeDuration const& rel_time);
+ };
+
+[endsect]
+
+[section Class `concurrent_component`]
+
+ class concurrent_component
+ typedef unspecified port;
+ typedef unspecified object_port;
+ typedef unspecified qualified_port;
+
+ static void accept(port& p);
+ static void accept_until(const boost::posix_time::ptime &abs_time, port& p);
+ template<typename TimeDuration>
+ static bool accept_for(TimeDuration const& rel_time, port& p);
+
+ static void accept_all(port& p1, ..., port& pn);
+ static void accept_all_until(const boost::posix_time::ptime &abs_time, port& p1, ..., port& pn);
+ template<typename TimeDuration>
+ static void accept_all_for(TimeDuration const& rel_time, port& p1, ..., port& pn);
+
+ static void accept_any(port& p1, ..., port& pn);
+ static void accept_any_until(const boost::posix_time::ptime &abs_time, port& p1, ..., port& pn);
+ template<typename TimeDuration>
+ static void accept_any_for(TimeDuration const& rel_time, port& p1, ..., port& pn);
+
+ };
+
+[endsect]
+
+
+
+[endsect]
+[/==========================================================================================]
+[section Header `<boost/synchro/lockable_traits.hpp>`]
+[/==========================================================================================]
+
+namespace boost { namespace synchro {
+
+ struct mono_threaded_tag;
+ struct multi_threaded_tag;
+ struct multi_process_tag;
+ template <typename Lockable> struct scope_tag;
+
+ template <typename Lockable> struct is_mono_threaded;
+ template <typename Lockable> struct is_multi_threaded;
+ template <typename Lockable> struct is_multi_process;
+
+ struct process_lifetime_tag;
+ struct kernel_lifetime_tag;
+ struct filesystem_lifetime_tag;
+ template <typename Lockable> struct lifetime_tag;
+
+ struct anonymous_tag;
+ struct named_tag;
+ template <typename Lockable> struct naming_tag;
+
+ struct exclusive_lock_tag;
+ struct sharable_lock_tag;
+ struct upgradable_lock_tag;
+ template <typename Lockable> struct category_tag;
+
+ template <typename Lockable> struct is_exclusive_lock;
+ template <typename Lockable> struct is_sharable_lock;
+ template <typename Lockable> struct is_upgradable_lock;
+
+ struct non_recursive_tag;
+ struct recursive_tag;
+ template <typename Lockable> struct reentrancy_tag;
+
+ template <typename Lockable> struct is_recursive_lock;
+
+ struct hasnt_timed_interface_tag;
+ struct has_timed_interface_tag;
+ template <typename Lockable> struct timed_interface_tag;
+
+ template <typename Lockable> struct has_timed_interface;
+
+ template <typename Locker> struct lockable_type;
+
+ template <typename Lockable> struct best_condition;
+
+ template <typename Lockable> struct best_condition_any;
+
+ template <typename Lockable> struct scoped_lock_type;
+ template <typename Lockable> struct unique_lock_type;
+ template <typename Lockable> struct shared_lock_type;
+ template <typename Lockable> struct upgrade_lock_type;
+
+ template <typename Lockable> struct lock_error_type;
+
+ template <typename Lockable> struct move_object_type;
+
+ template <typename Lockable> struct defer_lock_type;
+ template <typename Lockable> struct adopt_lock_type;
+ template <typename Lockable> struct try_to_lock_type;
+
+ template<typename Scope> struct default_lifetime;
+
+ template<
+ typename Scope=multi_threaded_tag,
+ typename Cathegory=exclusive_lock_tag,
+ typename Reentrancy=non_recursive_tag,
+ typename TimedInterface=has_timed_interface_tag,
+ typename Lifetime=typename default_lifetime<Scope>,
+ typename Naming=anonymous_tag,
+ typename Base=void
+ > struct lock_traits_base;
+
+
+
+[section Template Class `has_timed_interface`]
+
+ template <typename Lockable>
+ struct has_timed_interface
+ : is_same_or_is_base_and_derived<
+ has_timed_interface_tag,
+ typename timed_interface_tag<Lockable>::type
+ >
+ {};
+
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `is_exclusive`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `is_shared`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `is_recursive`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `is_mono_threaded`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `is_multi_threaded`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `is_multi_process`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `mutex_type`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `scoped_lock`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `unique_lock`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `shared_lock`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `upgrade_lock`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `lock_error`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `moved_object`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `lock_error2`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `lock_error3`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+[section Class `lock_error4`]
+[*Synopsis]
+[*Description]
+
+[endsect]
+
+[section Class `lock_traits`]
+
+[*Synopsis]
+
+ template<typename Lockable>
+ struct lock_traits;
+ typedef Lockable mutex_type;
+ typedef unspecified scoped_lock;
+ typedef unspecified unique_lock;
+ typedef unspecified shared_lock;
+ typedef unspecified upgrade_lock;
+ typedef unspecified lock_error;
+ typedef unspecified moved_object;
+ static const unspecified defer_lock();
+ static const unspecified adopt_lock();
+ static const unspecified try_to_lock();
+ };
+
+
+[*Description]
+Lock Traits characterise lockable types.
+
+[*`nesteed_strict_locker` public member types]
+
+# `;`
+
+[endsect]
+
+[endsect]
+
+
+
+
+
+
+
+
+[/==========================================================================================]
+[section Header `<boost/synchro/poly/adaptive_lock.hpp>`]
+[/==========================================================================================]
+
+[section Class `lock_adapter`]
+[*Synopsis]
+
+[*Description]
+
+More usefully for primitives, which are best left as
+non-polymorphic, an adaptor class can be used to provide the interface - run-time
+polymorphism - on behalf of anything supporting the correctly named functions -
+sometimes known as compile time polymorphism. It easier to take a nonpolymorphic
+class and adapt it to be polymorphic, than it is do it the other way
+around: the overhead and semantics of polymorphism can only introduced to a class,
+not removed.
+
+[*`lock_adapter` public member functions]
+
+# `;`
+
+[endsect]
+[section Class `adaptive_lock`]
+An adaptive general locking class that defers the decision of lockable type to run time.
+
+[*Synopsis]
+
+[*Description]
+
+This class, as locable, provide a set of general locking APIs.
+However, it defers our decision of what kind of lockable to use to the run time and delegates
+all locking operations to the actual lockable. Users must define a constructor in their subclass
+to initialize lock_.
+
+[*`adaptive_lock` public member functions]
+
+# `;`
+
+
+[endsect]
+
+[endsect]
+
+[endsect]
+
+

Added: sandbox/synchro/libs/synchro/doc/references.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/references.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,51 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[section:ext_references Appendix E: References]
+
+[variablelist References
+[
+ [[@http://www.ddj.com/cpp/184403766
+ [*volatile - Multithreaded Programmer's Best Friend]]]
+ [Andrei Alexandrescu.
+ ]
+]
+
+[
+ [[@http://www.informit.com/articles/article.aspx?p=25298
+ [*Multithreading and the C++ Type System]]]
+ [Andrei Alexandrescu.]
+]
+
+[
+ [[@http://www.two-sdg.demon.co.uk/curbralan/papers/accu/C++Threading.pdf
+ [*C++ Threading - A Generic-Programming Approach]]]
+ [Kevlin Henney]
+]
+
+[/
+ [[@http://www.comedi.org/projects/libpoet/boostbook/doc/boostbook/html/index.html
+ [*libpoet]]]
+ [Frank Mori Hess]
+/]
+
+[
+ [[@http://www.cs.wustl.edu/~schmidt/PDF/ACE-concurrency.pdf
+ [*An OO Encapsulation of Lightweight OS
+Concurrency Mechanisms in the ACE Toolkit]]]
+ [Douglas C. Schmidt]
+]
+
+[
+ [[@http://www.cs.wustl.edu/~schmidt/ACE-documentation.html
+ [*ACE ]]]
+ [Douglas C. Schmidt]
+]
+
+]
+
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/synchro.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/synchro.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,101 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+[library Boost.Synchro
+ [quickbook 1.3]
+ [authors [Botet Escriba, Vicente J.]]
+ [copyright 2008 Vicente J. Botet Escriba]
+ [id boost.synchro]
+ [dirname synchro]
+ [purpose Concurrent synchronization utilities]
+ [license
+ 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])
+ ]
+]
+[template concept_param[role concept] A type playing the role of [role] in the [concept] concept.]
+
+[template concept_var[type] Object of type [type].]
+
+[template var[name type]
+
+* [*[name]] Object of type [type].
+]
+
+[template concept_arg[name concept]
+
+The type [*[name]] must be a model of [*[concept]].
+]
+
+[template concept_valid_expressions[concept]
+[*Valid expressions]
+
+In addition to the expressions defined in [concept], the following expressions must be valid.
+]
+
+[/
+[section Preface]
+
+[:[".]]
+[:[*['-- ]]]
+
+[endsect]
+/]
+
+[warning Synchro is not a part of the Boost libraries.]
+
+[import ../../../boost/synchro/lockable_traits.hpp]
+[import ../../../boost/synchro/lockable_concepts.hpp]
+[import ../../../boost/synchro/make_lockable.hpp]
+[import ../../../boost/synchro/monitor.hpp]
+[import ../../../boost/synchro/thread_synchronization_family.hpp]
+
+[import ../../../boost/synchro/conc/concurrent_component.hpp]
+
+[import ../../../boost/synchro/lockers/condition_locker.hpp]
+[import ../../../boost/synchro/lockers/externally_locked.hpp]
+[import ../../../boost/synchro/lockers/locking_ptr.hpp]
+[import ../../../boost/synchro/lockers/strict_locker.hpp]
+
+[import ../../../boost/synchro/queues/synchro_buffer_monitor.hpp]
+[import ../../../boost/synchro/queues/synchro_buffer_family.hpp]
+
+[import ../example/BankAccount.cpp]
+[import ../example/EL_BancAccount.cpp]
+[import ../example/Histogram.cpp]
+[import ../example/HotelReservation.cpp]
+[import ../example/IL_BancAccount.cpp]
+[import ../example/IL_Lockable_BancAccount.cpp]
+[import ../example/IL_Rec_Lockable_BancAccount.cpp]
+[import ../example/Master_Slave.cpp]
+[import ../example/SingleBuf.cpp]
+[import ../example/QualifiedSingleBuf.cpp]
+
+
+
+
+
+[include overview.qbk]
+
+[thread_synchronization_family]
+
+[include users_guide.qbk]
+
+
+[include reference.qbk]
+
+
+[/xinclude autodoc.xml]
+
+
+[include case_studies.qbk]
+
+
+[include appendices.qbk]
+
+

Added: sandbox/synchro/libs/synchro/doc/tutorial.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/tutorial.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,1211 @@
+[/
+ / Copyright (c) 2008 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)
+ /]
+
+
+
+[section:tutorial Tutorial]
+
+Concurrent components may interact in different ways: they may access
+the same shared objects by, for example, executing functions of
+these objects; or they may communicate directly by executing functions of
+each other.
+
+Concurrent execution of objects requires a mechanism
+for synchronizing the access to shared objects, just as direct communication
+between objects may require synchronization. The basic mechanism for synchronization in
+Boost.Threads and Boost.Interprocess are the well known mutex and condition_variables. Mutexes
+and condition variables are, however, only useful for very simple synchronization problems.
+The Synchro Library therefore introduce high-level abstractions for handling more complicated
+synchronization problems, including monitor for guaranteeing exclusive access to an object,
+controling external locking and last a so-called rendezvous mechanism for handling direct communication between
+objects. All the concurrency abstractions being introduced are defined by means of mutexes an conditions.
+
+[include tutorial/lockable.qbk]
+
+[include tutorial/internal_locking.qbk]
+[incude volatile_locking_ptr.qbk]
+[include tutorial/external_locking.qbk]
+[include tutorial/rendezvous.qbk]
+
+[/
+[section Internal Locking--Monitors]
+[section Concurrent execution of components]
+
+From here a component is a model of the Callable concept.
+
+Concurrent execution of a component may be described by means of the boost::thread:
+```boost::thread thread1(S);```
+where `S` is a reference to a component. The meaning of this expression is that execution
+of `S()` will take place concurrently with the execution of the component
+executing the expression.
+
+The following example includes a bank account of a person (Joe) and two
+components, one corresponding to a bank agent depositing money in Joe's
+account, and one representing Joe. Joe will only be withdrawing money from
+the account:
+
+[BankAccount_ussage]
+
+From time to time, the `bankAgent` will deposit $ 500 in `JoesAccount`.
+Joe will similarly withdraw $ 100 from his account. These sentences describe that
+the bankAgent and Joe are executed concurrently.
+
+The above example works well as long as the bankAgent and Joe do not
+access JoesAccount at the same time. There is, however, no guarantee that
+this will not happen. We may use a mutex to guarantee exclusive access to each bank.
+
+[IL_BankAccount_BankAccount_mutex]
+
+Execution of the Deposit and Withdraw operations will no longer be able
+to make simultaneous access to balance.
+
+Mutex is a simple and basic mechanism for obtaining synchronization.
+In the above example it is relatively easy to be convinced that the
+synchronization works correctly. In a system with several concurrent objects
+and several shared objects, it may be difficult to describe synchronization by
+means of mutexes. Programs that make heavy use of mutexes may be
+difficult to read and write. Instead, we shall introduce a number of generic
+classes for handling more complicated forms of synchronization and communication.
+
+With the RAII idion (Boost.Thread lock_guard) we can simplify a lot this using the scoped locks.
+
+[BankAccount_raii]
+
+[endsect]
+
+[section Monitors]
+
+The use of `mutex` and `lockers`, as in `BankAccount`, is a common way of defining objects
+shared by two or more concurrent components. We shall therefore introduce
+an abstraction that makes it easier to define such objects. The following class
+describes a so-called monitor pattern.
+
+[monitor]
+
+Depending on the lock cathegory we have exclusive monitors and shared monitors
+[exclusive_monitor]
+[shared_monitor]
+
+A monitor object behaves like a ExclusiveLockable object but only for the inheriting classes.
+Protected inheritance from make_exclusive_lockable provide to all the derived classes all ExclusiveLockable operations.
+In addition has a protected nested class,
+synchroronizer, used when defining the monitor operations to synchronize the access critical regions.
+The BankAccount may be described using Monitor in the following way:
+
+[BankAccount]
+
+In the following, a monitor means some sub-class of monitor. A synchroronized operation means an operation
+using the synchroronizer guard defined within some monitor. Monitor is one example of a high-level concurrency abstraction
+that can be defined by means of mutexes.
+
+
+[section Monitor Conditions]
+
+It may happen that a component executing an entry operation of a monitor is
+unable to continue execution due to some condition not being fulfilled. Consider,
+for instance, a bounded buffer of characters. Such a buffer may be implemented
+as a monitor with two operations Push and Pull: the Puss operation
+cannot be executed if the buffer is full, and the Pull operation cannot be executed
+if the buffer is empty. A sketch of such a buffer monitor may look as
+follows:
+
+[sync_buffer_schema]
+
+The meaning of a wait is that the calling component is delayed until the condition
+becomes true. We can do that using Boost.Thread condition variables like:
+
+[sync_buffer_boost_thread_style]
+
+The Monitor class replace the nested synchroronizer unique_lock with the class `condition_locker`
+for this purpose:
+
+[condition_locker]
+
+We may now give the complete version of the buffer class. The content
+of the buffer is: `data_[out_+1], data_[out_+2], ... data_R[in_-1]`
+where all the indexes are modulo size. The buffer is full if `in_=out_` and it
+is empty if `in_=(out_+1)%size`.
+
+[sync_buffer_monitor]
+
+Monitors and conditions are useful for describing simple cases of shared objects
+(by simple we mean a limited use of conditions). If the conditions for
+delaying a calling component become complicated, the monitor may similarly
+become difficult to program and read.
+
+[endsect]
+
+[endsect]
+[endsect]
+
+
+[section External Locking -- `strict_locker` and `externally_locked` classes]
+
+
+This tutorial is an adaptation of the article of Andrei Alexandrescu "Multithreading and the C++ Type System"
+to the Boost library.
+
+
+[section Internall locking]
+
+Consider, for example, modeling a bank account class that supports
+simultaneous deposits and withdrawals from multiple locations (arguably
+the "Hello, World" of multithreaded programming). In the code below, guard's
+constructor locks the passed-in object this, and guard's destructor unlocks this.
+
+[IL_BankAccount_BankAccount]
+
+
+The object-level locking idiom doesn't cover the entire richness of a threading model. For example,
+the model above is quite deadlock-prone when you try to coordinate multi-object transactions.
+Nonetheless, object-level locking is useful in many cases, and in combination with other mechanisms
+can provide a satisfactory solution to many threaded access problems in object-oriented programs.
+
+[endsect]
+
+[section Internal and external locking]
+
+The BankAccount class above uses internal locking. Basically, a class that uses internal locking
+guarantees that any concurrent calls to its public member functions don't corrupt an instance of that
+class. This is typically ensured by having each public member function acquire a lock on the object
+upon entry. This way, for any given object of that class, there can be only one member function call
+active at any moment, so the operations are nicely serialized.
+
+This approach is reasonably easy to implement and has an attractive simplicity. Unfortunately,
+"simple" might sometimes morph into "simplistic."
+
+Internal locking is insufficient for many real-world synchronization tasks. Imagine that you want to
+implement an ATM withdrawal transaction with the BankAccount class. The requirements are simple.
+The ATM transaction consists of two withdrawals-one for the actual money and one for the $2 commission.
+The two withdrawals must appear in strict sequence; that is, no other transaction can exist between them.
+
+The obvious implementation is erratic:
+
+[IL_BankAccount_ATMWithdrawal]
+
+
+The problem is that between the two calls above, another thread can perform another operation on the
+account, thus breaking the second design requirement.
+
+In an attempt to solve this problem, let's lock the account from the outside during the two operations:
+
+[IL_BankAccount_ATMWithdrawal_do_not_compile]
+
+
+Notice that the code above do not compiles, the `mtx_` field is private.
+We have two possibilities:
+
+* make `mtx_` public which seams odd
+* make the `BankAccount` lockable by adding the lock/unlock functions
+
+We can add these functions explicitly
+
+[IL_Lockable_BancAccount_BankAccount_explicit]
+
+or inheriting from a class which add these lockable functions.
+
+The `make_exclusive_lockable` class
+
+[make_exclusive_lockable]
+
+The `BankAccount` class result now in
+
+[IL_Lockable_BancAccount_BankAccount_inherit]
+
+and the code that do not comiles becomes
+
+[IL_Lockable_BancAccount_ATMWithdrawal]
+
+
+Notice that now acct is being locked by Withdraw after it has already been locked by guard. When running
+such code, one of two things happens.
+
+* Your mutex implementation might support the so-called recursive mutex semantics. This means that
+ the same thread can lock the same mutex several times successfully. In this case, the implementation
+ works but has a performance overhead due to unnecessary locking. (The locking/unlocking sequence in
+ the two Withdraw calls is not needed but performed anyway-and that costs time.)
+* Your mutex implementation might not support recursive locking, which means that as soon as you try
+ to acquire it the second time, it blocks-so the ATMWithdrawal function enters the dreaded deadlock.
+
+As `boost::mutex` is not recursive, we need to use its recursive version `boost::recursive_mutex`.
+
+[IL_Rec_Lockable_BancAccount_BankAccount]
+
+The caller-ensured locking approach is more flexible and the most efficient, but very dangerous. In an
+implementation using caller-ensured locking, BankAccount still holds a mutex, but its member functions
+don't manipulate it at all. Deposit and Withdraw are not thread-safe anymore. Instead, the client code
+is responsible for locking BankAccount properly.
+
+ class BankAccount
+ : public make_exclusive_lockable<boost:mutex> {
+ int balance_;
+ public:
+ void Deposit(int amount) {
+ balance_ += amount;
+ }
+ void Withdraw(int amount) {
+ balance_ -= amount;
+ }
+ };
+
+Obviously, the caller-ensured locking approach has a safety problem. BankAccount's implementation code
+is finite, and easy to reach and maintain, but there's an unbounded amount of client code that manipulates
+BankAccount objects. In designing applications, it's important to differentiate between requirements
+imposed on bounded code and unbounded code. If your class makes undue requirements on unbounded code,
+that's usually a sign that encapsulation is out the window.
+
+To conclude, if in designing a multithreaded class you settle on internal locking, you expose yourself to
+inefficiency or deadlocks. On the other hand, if you rely on caller-provided locking, you make your class
+error-prone and difficult to use. Finally, external locking completely avoids the issue by leaving it all
+to the client code.
+[endsect]
+
+[section Locks as Permits]
+So what to do? Ideally, the BankAccount class should do the following:
+
+* Support both locking models (internal and external).
+* Be efficient; that is, use no unnecessary locking.
+* Be safe; that is, BankAccount objects cannot be manipulated without appropriate locking.
+
+Let's make a worthwhile observation: Whenever you lock a BankAccount, you do so by using a
+`lock_guard<BankAccount>` object. Turning this statement around, wherever there's a `lock_guard<BankAccount>`,
+there's also a locked `BankAccount` somewhere. Thus, you can think of-and use-a `lock_guard<BankAccount>`
+object as a permit. Owning a `lock_guard<BankAccount>` gives you rights to do certain things.
+The `lock_guard<BankAccount>` object should not be copied or aliased (it's not a transmissible permit).
+
+# As long as a permit is still alive, the `BankAccount` object stays locked.
+# When the `lock_guard<BankAccount>` is destroyed, the `BankAccount`'s mutex is released.
+
+The net effect is that at any point in your code, having access to a `lock_guard<BankAccount>` object
+guarantees that a `BankAccount` is locked. (You don't know exactly which `BankAccount` is locked,
+however-an issue that we'll address soon.)
+
+For now, let's make a couple of enhancements to the `lock_guard` class template defined in Boost.Thread.
+We'll call the enhanced version `strict_locker`. Essentially, a `strict_locker`'s role is only to live on the
+stack as an automatic variable. `strict_locker` must adhere to a non-copy and non-alias policy.
+`strict_locker` disables copying by making the copy constructor and the assignment operator private.
+While we're at it, let's disable operator new and operator delete; `strict_locker` are not intended to be
+allocated on the heap. `strict_locker` avoids aliasing by using a slightly less orthodox and less well-known
+technique: disable address taking.
+
+[strict_locker]
+
+[/ template <typename Lockable>
+ class strict_locker : private boost::noncopyable {
+ public:
+ typedef Lockable lockable_type;
+ typedef typename lock_traits<lockable_type>::lock_error bad_lock;
+ explicit strict_locker(lockable_type& obj) : obj_(obj) {
+ obj.lock();
+ }
+ ~strict_locker() { obj_.unlock(); }
+
+ typedef bool (strict_locker::*bool_type)();
+ operator bool_type() const
+ {
+ return &strict_locker::owns_lock;
+ }
+ bool operator!() const { return false; }
+ bool owns_lock() const { return true; }
+ private:
+ lockable_type& obj_;
+ private:
+ /// disable default constructor
+ strict_locker();
+ /// disable aliasing
+ BOOST_NON_ALIAS(strict_locker);
+ /// disable heap allocation
+ BOOST_NON_HEAP_ALLOCATED();
+ };
+]
+
+Silence can be sometimes louder than words-what's forbidden to do with a `strict_locker` is as important as
+what you can do. Let's see what you can and what you cannot do with a `strict_locker` instantiation:
+
+* You can create a `strict_lock<T>` only starting from a valid T object. Notice that there is no
+ other way you can create a `strict_lock<T>`.
+
+ BankAccount myAccount("John Doe", "123-45-6789");
+ strict_lock<BankAccount> myLock(myAccount); // ok
+
+* You cannot copy `strict_locker`s to one another. In particular, you cannot pass `strict_locker`s by value
+ to functions or have them returned by functions:
+
+ extern strict_lock<BankAccount> Foo(); // compile-time error
+ extern void Bar(strict_lock<BankAccount>); // compile-time error
+
+* However, you still can pass `strict_locker`s by reference to and from functions:
+
+ // ok, Foo returns a reference to strict_lock<BankAccount>
+ extern strict_locker<BankAccount>& Foo();
+ // ok, Bar takes a reference to strict_lock<BankAccount>
+ extern void Bar(strict_locker<BankAccount>&);
+
+* You cannot allocate a `strict_locker` on the heap. However, you still can put `strict_locker`s on the heap
+ if they're members of a class.
+
+ strict_locker<BankAccount>* pL =
+ new strict_lock<BankAccount>(myAcount); //error!
+ // operator new is not accessible
+ class Wrapper {
+ strict_locker memberLock_;
+ ...
+ };
+ Wrapper* pW = new Wrapper; // ok
+
+(Making `strict_locker` a member variable of a class is not recommended. Fortunately, disabling copying
+ and default construction makes `strict_locker` quite an unfriendly member variable.)
+
+* You cannot take the address of a `strict_locker` object. This interesting feature, implemented by
+ disabling unary operator&, makes it very unlikely to alias a `strict_locker` object. Aliasing is still
+ possible by taking references to a `strict_locker`:
+
+ strict_locker<BankAccount> myLock(myAccount); // ok
+ strict_locker<BankAccount>* pAlias = &myLock; // error!
+ // strict_lock<BankAccount>::operator& is not accessible
+ strict_locker<BankAccount>& rAlias = myLock; // ok
+
+Fortunately, references don't engender as bad aliasing as pointers because they're much less
+ versatile (references cannot be copied or reseated).
+
+* You can even make `strict_locker` final; that is, impossible to derive from. This task is left in the
+ form of an exercise to the reader.
+
+All these rules were put in place with one purpose-enforcing that owning a `strict_lock<T>` is a reasonably
+strong guarantee that
+
+# you locked a T object, and
+# that object will be unlocked at a later point.
+
+Now that we have such a strict `strict_locker`, how do we harness its power in defining a safe, flexible
+interface for BankAccount? The idea is as follows:
+
+* Each of BankAccount's interface functions (in our case, Deposit and Withdraw) comes in two
+ overloaded variants.
+* One version keeps the same signature as before, and the other takes an additional argument of
+ type `strict_lock<BankAccount>`. The first version is internally locked; the second one requires
+ external locking. External locking is enforced at compile time by requiring client code to create
+ a `strict_lock<BankAccount>` object.
+* BankAccount avoids code bloating by having the internal locked functions forward to the external
+ locked functions, which do the actual job.
+
+A little code is worth 1,000 words, a (hacked into) saying goes, so here's the new BankAccount class:
+
+ class BankAccount
+ : public make_exclusive_lockable<boost:recursive_mutex>
+ {
+ int balance_;
+ public:
+ void Deposit(int amount, strict_lock<BankAccount>&) {
+ // Externally locked
+ balance_ += amount;
+ }
+ void Deposit(int amount) {
+ strict_lock<boost:mutex> guard(*this); // Internally locked
+ Deposit(amount, guard);
+ }
+ void Withdraw(int amount, strict_lock<BankAccount>&) {
+ // Externally locked
+ balance_ -= amount;
+ }
+ void Withdraw(int amount) {
+ strict_lock<boost:mutex> guard(*this); // Internally locked
+ Withdraw(amount, guard);
+ }
+ };
+
+Now, if you want the benefit of internal locking, you simply call Deposit(int) and Withdraw(int).
+If you want to use external locking, you lock the object by constructing a `strict_lock<BankAccount>` and
+then you call `Deposit(int, strict_lock<BankAccount>&)` and `Withdraw(int, strict_lock<BankAccount>&)`. For
+example, here's the `ATMWithdrawal` function implemented correctly:
+
+ void ATMWithdrawal(BankAccount& acct, int sum) {
+ strict_lock<BankAccount> guard(acct);
+ acct.Withdraw(sum, guard);
+ acct.Withdraw(2, guard);
+ }
+
+This function has the best of both worlds-it's reasonably safe and efficient at the same time.
+
+It's worth noting that `strict_locker` being a template gives extra safety compared to a straight
+polymorphic approach. In such a design, BankAccount would derive from a Lockable interface.
+`strict_locker` would manipulate Lockable references so there's no need for templates. This approach is
+sound; however, it provides fewer compile-time guarantees. Having a `strict_locker` object would only tell
+that some object derived from Lockable is currently locked. In the templated approach, having a
+`strict_lock<BankAccount>` gives a stronger guarantee-it's a `BankAccount` that stays locked.
+
+There's a weasel word in there-I mentioned that ATMWithdrawal is reasonably safe. It's not really
+safe because there's no enforcement that the `strict_lock<BankAccount>` object locks the appropriate
+BankAccount object. The type system only ensures that some BankAccount object is locked. For example,
+consider the following phony implementation of ATMWithdrawal:
+
+ void ATMWithdrawal(BankAccount& acct, int sum) {
+ BankAccount fakeAcct("John Doe", "123-45-6789");
+ strict_lock<BankAccount> guard(fakeAcct);
+ acct.Withdraw(sum, guard);
+ acct.Withdraw(2, guard);
+ }
+
+This code compiles warning-free but obviously doesn't do the right thing-it locks one account and
+uses another.
+
+It's important to understand what can be enforced within the realm of the C++ type system and what
+needs to be enforced at runtime. The mechanism we've put in place so far ensures that some BankAccount
+object is locked during the call to `BankAccount::Withdraw(int, strict_lock<BankAccount>&)`. We must
+enforce at runtime exactly what object is locked.
+
+If our scheme still needs runtime checks, how is it useful? An unwary or malicious programmer can
+easily lock the wrong object and manipulate any BankAccount without actually locking it.
+
+First, let's get the malice issue out of the way. C is a language that requires a lot of attention
+and discipline from the programmer. C++ made some progress by asking a little less of those, while
+still fundamentally trusting the programmer. These languages are not concerned with malice (as Java
+is, for example). After all, you can break any C/C++ design simply by using casts "appropriately"
+(if appropriately is an, er, appropriate word in this context).
+
+The scheme is useful because the likelihood of a programmer forgetting about any locking whatsoever
+is much greater than the likelihood of a programmer who does remember about locking, but locks the
+wrong object.
+
+Using `strict_locker` permits compile-time checking of the most common source of errors, and runtime
+checking of the less frequent problem.
+
+Let's see how to enforce that the appropriate BankAccount object is locked. First, we need to add
+a member function to the `strict_locker` class template. The `strict_lock<T>::get_lockable` function returns
+a reference to the locked object.
+
+ template <class T> class strict_lock {
+ ... as before ...
+ public:
+ T* get_lockable() const { return &obj_; }
+ };
+
+Second, BankAccount needs to compare the locked object against this:
+
+ class BankAccount {
+ : public make_exclusive_lockable<boost::recursive_mutex>
+ int balance_;
+ public:
+ void Deposit(int amount, strict_lock<BankAccount>& guard) {
+ // Externally locked
+ if (!guard.is_locking(*this))
+ throw "Locking Error: Wrong Object Locked";
+ balance_ += amount;
+ }
+ ...
+ };
+
+ The overhead incurred by the test above is much lower than locking a recursive mutex for the second
+ time.
+
+[endsect]
+
+[section Improving External Locking]
+Now let's assume that BankAccount doesn't use its own locking at all, and has only a thread-neutral
+implementation:
+
+ class BankAccount {
+ int balance_;
+ public:
+ void Deposit(int amount) {
+ balance_ += amount;
+ }
+ void Withdraw(int amount) {
+ balance_ -= amount;
+ }
+ };
+
+Now you can use BankAccount in single-threaded and multi-threaded applications alike, but you need to
+provide your own synchronization in the latter case.
+
+Say we have an AccountManager class that holds and manipulates a BankAccount object:
+
+ class AccountManager
+ : public make_exclusive_lockable<boost::mutex>
+ {
+ BankAccount checkingAcct_;
+ BankAccount savingsAcct_;
+ ...
+ };
+
+Let's also assume that, by design, AccountManager must stay locked while accessing its BankAccount members.
+The question is, how can we express this design constraint using the C++ type system? How can we state
+"You have access to this BankAccount object only after locking its parent AccountManager object"?
+
+The solution is to use a little bridge template `externally_locked` that controls access to a BankAccount.
+[c++]
+
+[externally_locked]
+
+`externally_locked` cloaks an object of type T, and actually provides full access to that object through
+the get and set member functions, provided you pass a reference to a `strict_locker<Owner>` object.
+
+Instead of making `checkingAcct_` and `savingsAcct_` of type `BankAccount`, `AccountManager` holds objects of
+type `externally_locked<BankAccount, AccountManager>`:
+
+[AccountManager]
+
+The pattern is the same as before-to access the BankAccount object cloaked by `checkingAcct_`, you need
+to call `get`. To call `get`, you need to pass it a `strict_lock<AccountManager>`. The one thing you have to
+take care of is to not hold pointers or references you obtained by calling `get`. If you do that, make sure
+that you don't use them after the strict_lock has been destroyed. That is, if you alias the cloaked objects,
+you're back from "the compiler takes care of that" mode to "you must pay attention" mode.
+
+Typically, you use `externally_locked` as shown below. Suppose you want to execute an atomic transfer
+from your checking account to your savings account:
+
+[Checking2Savings]
+
+We achieved two important goals. First, the declaration of `checkingAcct_` and `savingsAcct_` makes it
+clear to the code reader that that variable is protected by a lock on an AccountManager. Second,
+the design makes it impossible to manipulate the two accounts without actually locking a BankAccount.
+`externally_locked` is what could be called active documentation.
+[endsect]
+
+[section Allowing other strict lockers]
+Now imagine that the AccountManager function needs to take a `unique_lock` in order to reduce the critical regions.
+And at some time it needs to access to the `checkingAcct_`. As `unique_lock` is not a strict lock the following code do not compiles:
+
+[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE]
+
+We need a way to transfer the ownership from the `unique_lock` to a `strict_lock` the time we are working with `savingsAcct_`
+and then restore the ownership on `unique_lock`.
+
+[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE2]
+
+In order to make this code compilable we need to store either a Lockable or a `unique_lock<Lockable>` reference depending on the constructor.
+Store which kind of reference we have stored,and in the destructor call either to the Lockable `unlock` or restore the ownership.
+
+This seams too complicated to me. Another possibility is to define a nested strict locker class.
+The drawback is that instead of having only one strict locker we have two and we need either
+to duplicate every function taking a `strict\_lock`
+or make these function templates functions.
+The problem with template functions is that we don't profit anymore of
+the C++ type system. We must add some static metafunction that check that the Locker parameter is a strict locker.
+The problem is that we can not really check this or can we?. The `is_strict_locker` metafunction must be specialized by the strict locker
+developer. We need to belive it "sur parolle".
+The advantage is that now we can manage with more than two strict lockers without changing our code. Ths is really nice.
+
+Now we need to state that both classes are `strict_locker`s.
+
+ template <typename Locker>
+ struct is_strict_locker : mpl::false_ {};
+
+ template <typename Lockable>
+ struct is_strict_locker<strict_locker<Lockable> > : mpl::true_ {}
+
+ template <typename Locker>
+ struct is_strict_locker<nested_strict_locker<Locker> > : mpl::true_ {}
+
+
+Well let me show how this `nested_strict_locker` class looks like
+and the impacts on the `externally_locked` class and the `AccountManager::AMoreComplicatedFunction` function.
+
+First `nested_strict_locker` class will store on a temporary lock the `Locker`, and transfer the lock ownership
+on the constructor. On destruction he will restore the ownership. Note also that the Locker needs to have
+already a reference to the mutex otherwise an exception is thrown and the use of the `locker_traits`.
+
+[nested_strict_locker]
+
+The `externally_locked` get function is now a template function taking a Locker as parameters instead of a
+`strict_locker`. We can add test in debug mode that ensure that the Lockable object is locked.
+
+[externally_locked_any]
+
+The `AccountManager::AMoreComplicatedFunction` function needs only to replace the `strict_locker` by a
+`nested_strict_locker`.
+
+[AMoreComplicatedChecking2Savings]
+
+[endsect]
+
+[endsect]
+
+[section Concurrent components]
+
+[section Direct communication between components]
+In the previous section we have described a mechanism for concurrent components
+to communicate through shared objects. In many cases it appears more
+natural for concurrent components to communicate directly instead of using
+shared objects. Consider the following example:
+
+[synchronized_communication_between_components_schema]
+
+
+Here the concurrent components `S` and `R` call operations on each other. The
+state of `S` may, however, not be meaningful when `R` executes `m`, and vice versa.
+In the following sections we will introduce abstractions for making it possible
+to synchronize such communication.
+
+[section Synchrohronized communication between components]
+
+In this section we will introduce the notion of synchronized execution of objects.
+A component `S` may request execution of a member function of a component
+`R`. The component `R` must accept that the request can be fulfilled.
+Synchrohronized communication is described in a generic class concurrent_component.
+A `concurrent_component` defines the notion of a `port` for controlling the communication. A
+`port` has a nested `synchroronizer` class for defining operations controlled by the
+`port`; it also has an accept operation for signaling that an operation associated
+with the `port` can be executed. The `concurrent_component` has the following structure:
+
+[port]
+
+The following object illustrates two communicating `concurrent_component`s:
+
+[synchronized_communication_between_components]
+
+The concurrent_component `S` may execute a request, which is a normal remote procedure call:
+
+```
+ e2 = r_.m(e1);
+```
+
+Since `m` is a synchroronized port operation, the execution of M has to be accepted
+by R before it is executed.
+For M to be accepted, R must execute an accept, which has the following
+form:
+
+```
+ port::accept(p);
+```
+
+The communication is carried out when `S` is executing `r\_.m` and `R` is executing
+`port::accept(p)`. Both `S` and `R` are blocked until the communication takes place. A
+communication has the effect that `S` and `R` together execute the evaluation: `e2 = r\_.m(e1);`
+
+This takes place as follows:
+
+# When S executes `e2 = r\_.m(e1)`, `S` is now ready to execute the
+internals of the `R::m`.
+# When `R` executes `port::accept(p)`, `R` has signaled that the internals of a function
+protected with `port::synchronizer \_(p)`; may be executed. `R` will wait until such an
+execution has taken place.
+# When both `R` and `S` are ready, the internals of `R::m` can be executed.
+# When the internals of `R::m` has been executed, `R` will continue execution. In
+addition, a possible return of `R::m` is assigned to `e2`.
+
+The object `S` executing `r\_.m()` is called the sender, and the object `R` having `m` as
+an operation is called the receiver.
+
+In the following example, two systems `Prod` and `Cons` communicate via
+a single element buffer represented by a `SingleBuf` concurrent_component. The `SingleBuf`
+concurrent_component alternates between accepting a `Push` and a `Pull`:
+
+[SingleBuf]
+
+[endsect]
+[section Ports controlling several operations]
+
+It is possible to associate more than one operation with a port.
+
+The `Master`-concurrent_component transmits a sequence of values to the two
+`Slave`-systems, and each Slave-concurrent_component computes the sum of the values being
+received. Each value is received and accumulated by a synchronous execution
+of `Add`. A Slave object can be used according to the following protocol:
+
+# The `Clear` operation must be used to initiate a new sequence of summations.
+A `Clear` thus terminates any ongoing summation.
+# The `Add` operation accumulates a new value.
+# The `Result` operation returns the current sum.
+In the example, positive numbers are transmitted to `Slave1` and negative numbers
+are transmitted to `Slave2`.
+
+[Master_Slave_Slave]
+
+[Master_Slave_Master]
+
+
+[endsect]
+
+[section Restricted acceptance]
+
+An accept operation on a port signals that any object is allowed to execute
+an operation associated with the port. Sometimes it is desirable to restrict the
+possible objects that are allowed to execute a port operation. The restriction
+may specify that one specific object is allowed to execute a port operation, or
+it may specify that instances of a specific class are allowed to execute a port
+operation. These two types of restrictions are described in the following two
+sections.
+
+[*Object restriction]
+
+It is possible to restrict the sender of an operation by declaring the port as an
+instance of the `object_port` class. The `accept` operation of an `object_port`
+has a parameter which is a reference to the object that is allowed to
+execute a port operation. As C++ do not allows to recover the sender of an operation
+we need pass it as parameter.
+
+The syntax for this is:
+
+ T S; //some component reference
+ object_port request_;
+ void Close(const concurrent_component_base* snd) {
+ object_port::synchronizer _(request_, snd);
+ // ...
+ }
+ //...
+ object_port::accept(request_, sender_); // sender_ has been stored previously
+
+
+The example describes an abstract pattern for handling reservations
+of some kind. The reservations are supposed to be stored in some
+register. The actual way this is done is supposed to be described in subpatterns
+of ReservationHandler. At most, one person at a time is allowed to
+make reservations. An agent making a reservation must perform the following
+steps:
+
+
+# The register must be locked by executing the Lock operation.
+# The agent may then perform one or more reservations using Reserve.
+# The agent terminates the reservation session by executing Close.
+
+The example includes a sketch of a handler for hotel reservations. The concurrent_component
+P describes a scenario of an agent making two hotel reservations.
+
+[ReservationHandler]
+
+[HotelResHandler]
+
+[HotelResHandler_main]
+
+[*Qualified restriction]
+
+The object_port described above makes it possible to ensure that only one
+specific concurrent_component may execute a port operation. It is often desirable to specify
+that a port operation may be executed by a restricted set of `concurrent_component`s. By using a
+port instantiated from `qualified_port`, it is possible to define port operations
+that may be executed by objects of a given class. The syntax for
+this is:
+
+
+Port operations associated with P may now be executed by an object which is
+an instance of T or inherits from T.
+
+The following example illustrates the use of a qualified port. The
+single buffer example is modified such that Push can only be executed by
+Producer objects and Pull can only be executed by Consumer objects.
+
+[QualfiedSingleBuf]
+
+[endsect]
+
+[endsect]
+
+[section Compound concurrent components]
+
+[section Indirect communication between internal concurrent components]
+
+Composition is a fundamental means for organizing objects. We have several
+examples of defining an object as compositions of other objects using part
+objects, references and block structure. We have also seen how the action part of
+an object may be composed of other objects. In this section we shall show how
+to construct compound systems that are concurrent_component objects consisting of several
+internal multiple action sequences.
+
+In Boost.Synchro the actions to be performed by a concurrent_component may be distributed
+among several internal systems. The internal systems may be more or less
+independent, and they may access common data (items in an enclosing concurrent_component),
+communicate with each other, communicate with external systems or
+control communication between external systems, and the enclosing concurrent_component.
+
+In the following, examples of such compound systems are described.
+For compound systems consisting of several internal concurrent systems,
+we are often interested in describing that execution of the outermost concurrent_component
+cannot terminate before execution of all inner systems have terminated. The
+outermost concurrent_component may have to do some initialization before executing the inner
+concurrent_component, and it may have to do some finalization (clean-up) when they
+have finished execution. The concurrent_component class has a concurrent_execution nested class that can
+be used for this purpose. concurrent_component can be used in the following way:
+
+ concurrent_execution<S1,S2, S3)> conc(s1,s2, s3);
+ conc();
+ conc.join();
+
+[Histogram]
+
+[endsect]
+[section Communication with internal systems]
+
+[endsect]
+
+
+[endsect]
+
+[section Readers and writers problem]
+
+
+[endsect]
+
+
+
+
+
+
+
+
+
+
+
+
+
+[endsect]
+
+
+[section `volatile ` and `locking_ptr`]
+
+
+This tutorial is an adaptation of the article of Andrei Alexandrescu "`volatile` - Multithreaded
+Programmer's Best Friend"
+to the Boost library.
+
+[section Just a Little Keyword]
+
+Although both C and C++ Standards are conspicuously silent when it comes to threads, they do make a
+little concession to multithreading, in the form of the volatile keyword.
+
+Just like its better-known counterpart const, volatile is a type modifier. It's intended to be used
+in conjunction with variables that are accessed and modified in different threads. Basically, without
+volatile, either writing multithreaded programs becomes impossible, or the compiler wastes vast
+optimization opportunities. An explanation is in order.
+
+Consider the following code:
+
+ class Gadget
+ {
+ public:
+ void Wait()
+ {
+ while (!flag_)
+ {
+ sleep(1000); // sleeps for 1000 milliseconds
+ }
+ }
+ void Wakeup()
+ {
+ flag_ = true;
+ }
+ ...
+ private:
+ bool flag_;
+ };
+
+The purpose of `Gadget::Wait` above is to check the `flag_` member variable every second and return when that
+variable has been set to true by another thread. At least that's what its programmer intended, but, alas,
+Wait is incorrect. Suppose the compiler figures out that `sleep(1000)` is a call into an external library
+that cannot possibly modify the member variable `flag_`. Then the compiler concludes that it can cache `flag_`
+in a register and use that register instead of accessing the slower on-board memory. This is an excellent
+optimization for single-threaded code, but in this case, it harms correctness: after you call Wait for some
+`Gadget` object, although another thread calls Wakeup, Wait will loop forever. This is because the change of
+`flag_` will not be reflected in the register that caches `flag_`. The optimization is too ... optimistic.
+Caching variables in registers is a very valuable optimization that applies most of the time, so it would
+be a pity to waste it. C and C++ give you the chance to explicitly disable such caching. If you use the
+volatile modifier on a variable, the compiler won't cache that variable in registers -- each access will
+hit the actual memory location of that variable. So all you have to do to make Gadget's Wait/Wakeup combo
+work is to qualify `flag_` appropriately:
+
+ class Gadget
+ {
+ public:
+ ... as above ...
+ private:
+ volatile bool flag_;
+ };
+
+Most explanations of the rationale and usage of `volatile` stop here and advise you to volatile-qualify the
+primitive types that you use in multiple threads. However, there is much more you can do with `volatile`,
+because it is part of C++'s wonderful type system.
+
+[endsect]
+[section Using `volatile` with User-Defined Types]
+
+You can volatile-qualify not only primitive types, but also user-defined types. In that case, `volatile`
+modifies the type in a way similar to const. (You can also apply const and `volatile` to the same type
+simultaneously.) Unlike `const`, `volatile` discriminates between primitive types and user-defined types.
+Namely, unlike classes, primitive types still support all of their operations (addition, multiplication,
+assignment, etc.) when volatile-qualified. For example, you can assign a non-volatile `int` to a `volatile` `int`,
+but you cannot assign a non-volatile object to a `volatile` object. Let's illustrate how `volatile` works on
+user-defined types on an example.
+
+ class Gadget
+ {
+ public:
+ void Foo() volatile;
+ void Bar();
+ ...
+ private:
+ std::tring name_;
+ int state_;
+ };
+ ...
+ Gadget regularGadget;
+ volatile Gadget volatileGadget;
+
+If you think `volatile` is not that useful with objects, prepare for some surprise.
+
+ volatileGadget.Foo(); // ok, volatile fun called for
+ // volatile object
+
+
+ regularGadget.Foo(); // ok, volatile fun called for
+ // non-volatile object
+ volatileGadget.Bar(); // error! Non-volatile function called for
+ // volatile object!
+
+The conversion from a non-qualified type to its `volatile` counterpart is trivial. However, just as with
+const, you cannot make the trip back from `volatile` to non-qualified. You must use a cast:
+
+ Gadget& ref = const_cast<Gadget&>(volatileGadget);
+ ref.Bar(); // ok
+
+A volatile-qualified class gives access only to a subset of its interface, a subset that is under the
+control of the class implementer. Users can gain full access to that type's interface only by using a
+`const_cast`. In addition, just like constness, volatileness propagates from the class to its members
+(for example, `volatileGadget.name_` and `volatileGadget.state_` are `volatile` variables).
+
+[endsect]
+[section `volatile`, Critical Sections, and Race Conditions]
+
+The simplest and the most often-used synchronization device in multithreaded programs is the mutex.
+
+[/A mutex
+exposes the `lock` and `unlock` primitives. Once you call `lock` in some thread, any other thread calling
+`lock` will block. Later, when that thread calls `unlock`, precisely one thread blocked in an `lock` call
+will be released. In other words, for a given mutex, only one thread can get processor time in between a
+call to `lock` and a call to `unlock`. The executing code between a call to `lock` and a call to `unlock`
+is called a critical section. (Windows terminology is a bit confusing because it calls the mutex itself a
+critical section, while "mutex" is actually an inter-process mutex. It would have been nice if they were
+called thread mutex and process mutex.)
+/]
+Mutexes are used to protect data against race conditions. By
+definition, a race condition occurs when the effect of more threads on data depends on how threads are
+scheduled. Race conditions appear when two or more threads compete for using the same data. Because threads
+can interrupt each other at arbitrary moments in time, data can be corrupted or misinterpreted. Consequently,
+changes and sometimes accesses to data must be carefully protected with critical sections. In
+object-oriented programming, this usually means that you store a mutex in a class as a member variable and
+use it whenever you access that class' state. Experienced multithreaded programmers might have yawned
+reading the two paragraphs above, but their purpose is to provide an intellectual workout, because now we
+will link with the `volatile` connection. We do this by drawing a parallel between the C++ types' world and
+the threading semantics world.
+
+* Outside a critical section, any thread might interrupt any other at any time; there is no control, so
+ consequently variables accessible from multiple threads are `volatile`. This is in keeping with the
+ original intent of `volatile` -- that of preventing the compiler from unwittingly caching values used by
+ multiple threads at once.
+* Inside a critical section defined by a mutex, only one thread has access. Consequently, inside a
+ critical section, the executing code has single-threaded semantics. The controlled variable is not
+ `volatile` anymore -- you can remove the `volatile` qualifier.
+
+In short, data shared between threads is conceptually `volatile` outside a critical section, and non-volatile
+inside a critical section. You enter a critical section by locking a mutex. You remove the `volatile`
+qualifier from a type by applying a `const_cast`. If we manage to put these two operations together, we
+create a connection between C++'s type system and an application's threading semantics. We can make the
+compiler check race conditions for us.
+
+[endsect]
+[section `locking_ptr`]
+
+We need a tool that collects a mutex acquisition and a `const_cast`. Let's develop a `locking_ptr` class template
+that you initialize with a volatile object obj and a mutex mtx. During its lifetime, a `locking_ptr` keeps mtx
+acquired. Also, `locking_ptr` offers access to the volatile-stripped obj. The access is offered in a smart
+pointer fashion, through operator-> and operator*. The `const_cast` is performed inside `locking_ptr`. The cast
+is semantically valid because `locking_ptr` keeps the mutex acquired for its lifetime. First, let's define the
+skeleton of a class `mutex` with which `locking_ptr` will work:
+
+ class mutex
+ {
+ public:
+ void lock();
+ void unlock();
+ ...
+ };
+
+`locking_ptr` is templated with the type of the controlled variable and the exclusive lockable type.
+For example, if you want to
+control a Widget, you use a `locking_ptr<Widget> that you initialize with a variable of type `volatile` Widget.
+`locking_ptr`'s definition is very simple. `locking_ptr` implements an unsophisticated smart pointer. It focuses
+solely on collecting a `const_cast` and a critical section.
+
+ template <typename T>
+ class locking_ptr {
+ public:
+ // Constructors/destructors
+ locking_ptr(volatile T& obj, mutex& mtx)
+ : obj_(*const_cast<T*>(&obj)),
+ mtx_(mtx)
+ { mtx_.lock(); }
+ ~locking_ptr()
+ { mtx_->unlock(); }
+ // Pointer behavior
+ T& operator*()
+ { return obj_; }
+ T* operator->()
+ { return &obj_; }
+ private:
+ T& obj_;
+ mutex& mtx_;
+ locking_ptr(const locking_ptr&);
+ locking_ptr& operator=(const locking_ptr&);
+ };
+
+In spite of its simplicity, `locking_ptr` is a very useful aid in writing correct multithreaded code. You
+should define objects that are shared between threads as volatile and never use `const_cast` with them --
+always use `locking_ptr` automatic objects. Let's illustrate this with an example. Say you have two threads
+that share a vector<char> object:
+
+ class SynchroBuf {
+ public:
+ void Thread1();
+ void Thread2();
+ private:
+ typedef vector<char> BufT;
+ volatile BufT buffer_;
+ mutex mtx_; // controls access to buffer_
+ };
+
+Inside a thread function, you simply use a `locking_ptr<BufT>` to get controlled access to the `buffer_`
+member variable:
+
+ void SynchroBuf::Thread1() {
+ locking_ptr<BufT> lpBuf(buffer_, mtx_);
+ BufT::iterator i = lpBuf->begin();
+ for (; i != lpBuf->end(); ++i) {
+ ... use *i ...
+ }
+ }
+
+The code is very easy to write and understand -- whenever you need to use `buffer_`, you must create a
+`locking_ptr<BufT>` pointing to it. Once you do that, you have access to vector's entire interface. The nice
+part is that if you make a mistake, the compiler will point it out:
+
+ void SynchroBuf::Thread2() {
+ // Error! Cannot access 'begin' for a volatile object
+ BufT::iterator i = buffer_.begin();
+ // Error! Cannot access 'end' for a volatile object
+ for (; i != lpBuf->end(); ++i) {
+ ... use *i ...
+ }
+ }
+
+You cannot access any function of `buffer_` until you either apply a `const_cast` or use `locking_ptr`. The
+difference is that `locking_ptr` offers an ordered way of applying `const_cast` to volatile variables.
+`locking_ptr` is remarkably expressive. If you only need to call one function, you can create an unnamed
+temporary `locking_ptr` object and use it directly:
+
+ unsigned int SynchroBuf::Size() {
+ return locking_ptr<BufT>(buffer_, mtx_)->size();
+ }
+
+
+[endsect]
+[section Back to Primitive Types]
+
+We saw how nicely `volatile` protects objects against uncontrolled access and how `locking_ptr` provides a
+simple and effective way of writing thread-safe code. Let's now return to primitive types, which are
+treated differently by `volatile`. Let's consider an example where multiple threads share a variable of
+type int.
+
+ class Counter
+ {
+ public:
+ ...
+ void Increment() { ++ctr_; }
+ void Decrement() { --ctr_; }
+ private:
+ int ctr_;
+ };
+
+If Increment and Decrement are to be called from different threads, the fragment above is buggy. First,
+`ctr_` must be volatile. Second, even a seemingly atomic operation such as `++ctr_` is actually a
+three-stage operation. Memory itself has no arithmetic capabilities. When incrementing a variable, the
+processor:
+
+* Reads that variable in a register
+* Increments the value in the register
+* Writes the result back to memory
+
+This three-step operation is called RMW (Read-Modify-Write). During the Modify part of an RMW operation,
+most processors free the memory bus in order to give other processors access to the memory. If at that
+time another processor performs a RMW operation on the same variable, we have a race condition: the second
+write overwrites the effect of the first. To avoid that, you can rely, again, on `locking_ptr`:
+
+ class Counter
+ {
+ public:
+ ...
+ void Increment() { ++*locking_ptr<int, boost::mutex>(ctr_, mtx_); }
+ void Decrement() { --*locking_ptr<int, boost::mutex>(ctr_, mtx_); }
+ private:
+ volatile int ctr_;
+ boost::mutex mtx_;
+ };
+
+Now the code is correct, but its quality is inferior when compared to SynchroBuf's code. Why? Because with
+Counter, the compiler will not warn you if you mistakenly access `ctr_` directly (without locking it). The
+compiler compiles `++ctr_` if `ctr_` is volatile, although the generated code is simply incorrect. The compiler
+is not your ally anymore, and only your attention can help you avoid race conditions. What should you do
+then? Simply encapsulate the primitive data that you use in higher-level structures and use `volatile` with
+those structures. Paradoxically, it's worse to use `volatile` directly with built-ins, in spite of the fact
+that initially this was the usage intent of `volatile`!
+
+
+[endsect]
+[section `volatile` Member Functions]
+
+So far, we've had classes that aggregate `volatile` data members; now let's think of designing classes that
+in turn will be part of larger objects and shared between threads. Here is where `volatile` member functions
+can be of great help. When designing your class, you volatile-qualify only those member functions that are
+thread safe. You must assume that code from the outside will call the volatile functions from any code at
+any time. Don't forget: `volatile` equals free multithreaded code and no critical section; non-volatile
+equals single-threaded scenario or inside a critical section. For example, you define a class Widget that
+implements an operation in two variants -- a thread-safe one and a fast, unprotected one.
+
+ class Widget
+ {
+ public:
+ void Operation() volatile;
+ void Operation();
+ ...
+ private:
+ boost::mutex mtx_;
+ };
+
+Notice the use of overloading. Now Widget's user can invoke Operation using a uniform syntax either for
+volatile objects and get thread safety, or for regular objects and get speed. The user must be careful
+about defining the shared Widget objects as `volatile`. When implementing a `volatile` member function, the
+first operation is usually to lock this with a `locking_ptr`. Then the work is done by using the non-volatile sibling:
+
+ void Widget::Operation() volatile
+ {
+ locking_ptr<Widget,boost::mutex> lpThis(*this, mtx_);
+ lpThis->Operation(); // invokes the non-volatile function
+ }
+
+[endsect]
+[section Generic `locking_ptr`]
+The `locking_ptr` works with a mutex class. How to use it with other mutexes?
+We can make a more generic `locking_ptr` adding a Lockable template parameter.
+[/As the more common use will be `boos::mutex` this will be the default value]
+
+[locking_ptr]
+
+Every model of the ExclusiveLockable concept can be used as parameter.
+
+[endsect]
+
+[section Specific `locking_ptr` for lockable value types]
+
+When the value type is itself lockable we can simplify the `locking_ptr` as follows:
+
+[locking_ptr_lockable_value_type]
+
+
+
+[endsect]
+[endsect]
+
+]
+[endsect]

Added: sandbox/synchro/libs/synchro/doc/users_guide.qbk
==============================================================================
--- (empty file)
+++ sandbox/synchro/libs/synchro/doc/users_guide.qbk 2009-02-09 18:44:06 EST (Mon, 09 Feb 2009)
@@ -0,0 +1,36 @@
+[/
+[/
+ (C) Copyright 2008 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).
+]
+
+[/==============================]
+[section:users_guide Users'Guide]
+[/==============================]
+
+[include getting_started.qbk]
+[include tutorial.qbk]
+[include references.qbk]
+
+
+[/=======================]
+[section:glosary Glossary]
+[/=======================]
+
+
+[variablelist
+
+[[lockable] [.]]
+[[reentrancy] [.]]
+[[lock] [.]]
+[[locker] [.]]
+[[lifetime] [.]]
+[[scope] [.]]
+[[scope] [.]]
+]
+
+[endsect]
+
+[endsect]
\ No newline at end of file


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