diff --git a/build/Jamfile b/build/Jamfile
index a9391ac6..0ad9a350 100644
--- a/build/Jamfile
+++ b/build/Jamfile
@@ -39,7 +39,7 @@ if $(NT)
# Base names of the source files for libboost_thread
CPP_SOURCES =
- condition mutex recursive_mutex semaphore thread tss xtime once ;
+ condition mutex recursive_mutex thread tss xtime once exceptions ;
lib libboost_thread : ../src/$(CPP_SOURCES).cpp
# requirements
diff --git a/doc/faq.html b/doc/faq.html
index 8cf2754d..d4b71303 100644
--- a/doc/faq.html
+++ b/doc/faq.html
@@ -54,8 +54,7 @@
take advantage of prior art to reduce errors) or had excessive
dependencies on library components unrelated to threading. Existing C
libraries couldn't meet our C++ requirements, and were also missing
- certain features. For instance, POSIX threads doesn't support a
- maximum value for semaphores. The WIN32 thread API lacks condition
+ certain features. For instance, the WIN32 thread API lacks condition
variables, even though these are critical for the important Monitor
pattern [Schmidt 00].
Dangerous features, or features which
may be misused, are identified as such in the
documentation to make users aware of potential
- pitfalls. For example, see Semaphore.
The Boost.Threads library supplies a set of low level primitives for
- writing multi-threaded programs, such as semaphores, mutexes and
- condition variables. In fact, the first release of Boost.Threads
- supports only these low level primitives. However, computer science
- research has shown that use of these primitives is difficult since
- there's no way to mathematically prove that a usage pattern is
- correct, meaning it doesn't result in race conditions or deadlocks.
- There are several algebras (such as CSP, CCS and Join calculus) that
- have been developed to help write provably correct parallel processes.
- In order to prove the correctness these processes must be coded using
- higher level abstractions. So why does Boost.Threads support the lower
- level concepts?
+ writing multi-threaded programs, such as mutexes and condition variables.
+ In fact, the first release of Boost.Threads supports only these low level
+ primitives. However, computer science research has shown that use of these
+ primitives is difficult since there's no way to mathematically prove
+ that a usage pattern is correct, meaning it doesn't result in race
+ conditions or deadlocks. There are several algebras (such as CSP, CCS and
+ Join calculus) that have been developed to help write provably correct
+ parallel processes. In order to prove the correctness these processes must
+ be coded using higher level abstractions. So why does Boost.Threads support
+ the lower level concepts?
The reason is simple: the higher level concepts need to be
implemented using at least some of the lower level concepts. So having
diff --git a/doc/semaphore.html b/doc/semaphore.html
deleted file mode 100644
index b2399ad8..00000000
--- a/doc/semaphore.html
+++ /dev/null
@@ -1,242 +0,0 @@
-
-
The semaphore class defines a classic synchronization
- primitive invented by the Dutch computer scientist Edsger W. Dijkstra.
- A semaphore manages an internal counter. This counter never goes below
- zero, or above a specified maximum value. When calling
- semaphore::down the calling thread will block until the value is
- non-zero and then decrement the value in a single atomic operation.
- When calling semaphore::up the calling thread will increment
- the value in a single atomic operation, failing if the value has
- already reached the specified maximum.
-
-
Rationale: The semaphore is the simplest synchronization
- primitive available and is generally the primitive used to build other
- synchronization concepts at some level of implementation. For this
- reason Boost.Threads defines the semaphore type in the
- classic form. This simplifies usage and implementation, but it means
- that the interface is not as safe as other Boost.Threads
- interfaces.
-
-
Danger: Unlike the mutex models supplied by Boost.Threads,
- there is no lock_concept for the
- semaphore to help ensure proper usage. Great care must be taken when
- using a semaphore object to ensure deadlock or race conditions do not occur.
-
-
The dangers are spelled out by [Andrews-83] (function names
- updated, see historical note below):
-
-
-
Although semaphores can be used to program almost any kind of
- synchronization, down() and up() are rather
- unstructured primitives, and so it is easy to err when using them.
- Execution of each critical section must begin with a down()
- and end with a up() (on the same semaphore). Omitting a
- down() or up(), or accidentally coding a down()
- on one semaphore and a up() on another can have disastrous
- effects, since mutually exclusive execution would no longer be
- ensured. Also, when using semaphores, a programmer can forget to
- include in critical sections all statements that reference shared
- objects. This, too, could destroy the mutual exclusion required
- within critical sections. A second difficulty with using semaphores
- is that both condition synchronization and mutual exclusion are
- programmed using the same pair of primitives. This makes it
- difficult to identify the purpose of a given down() or
- up() operation without looking at the other operations on the
- corresponding semaphore. Since mutual exclusion and condition
- synchronization are distinct concepts, they should have distinct
- notations.
-
-
-
Historical note: Dijkstra's original name for
- down() was P (short for the Dutch "passeren",
- "to pass"), and for up() was V (short for the
- Dutch "vrygeven", "to release").