barrier.qbk 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. [/
  2. (C) Copyright 2007-8 Anthony Williams.
  3. (C) Copyright 2013 Oliver Kowalke.
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt).
  7. ]
  8. [section:barriers Barriers]
  9. A barrier is a concept also known as a __rendezvous__, it is a synchronization
  10. point between multiple contexts of execution (fibers). The barrier is
  11. configured for a particular number of fibers (`n`), and as fibers reach the
  12. barrier they must wait until all `n` fibers have arrived. Once the `n`-th
  13. fiber has reached the barrier, all the waiting fibers can proceed, and the
  14. barrier is reset.
  15. The fact that the barrier automatically resets is significant. Consider a case
  16. in which you launch some number of fibers and want to wait only until the
  17. first of them has completed. You might be tempted to use a `barrier(2)` as the
  18. synchronization mechanism, making each new fiber call its [member_link
  19. barrier..wait] method, then calling `wait()` in the launching fiber to wait
  20. until the first other fiber completes.
  21. That will in fact unblock the launching fiber. The unfortunate part is that it
  22. will continue blocking the ['remaining] fibers.
  23. Consider the following scenario:
  24. # Fiber ["main] launches fibers A, B, C and D, then calls `barrier::wait()`.
  25. # Fiber C finishes first and likewise calls `barrier::wait()`.
  26. # Fiber ["main] is unblocked, as desired.
  27. # Fiber B calls `barrier::wait()`. Fiber B is ['blocked!]
  28. # Fiber A calls `barrier::wait()`. Fibers A and B are unblocked.
  29. # Fiber D calls `barrier::wait()`. Fiber D is blocked indefinitely.
  30. (See also [link wait_first_simple_section when_any, simple completion].)
  31. [note It is unwise to tie the lifespan of a barrier to any one of its
  32. participating fibers. Although conceptually all waiting fibers awaken
  33. ["simultaneously,] because of the nature of fibers, in practice they will
  34. awaken one by one in indeterminate order.[footnote The current implementation
  35. wakes fibers in FIFO order: the first to call `wait()` wakes first, and so
  36. forth. But it is perilous to rely on the order in which the various fibers
  37. will reach the `wait()` call.] The rest of the waiting fibers will
  38. still be blocked in `wait()`, which must, before returning, access data
  39. members in the barrier object.]
  40. [class_heading barrier]
  41. #include <boost/fiber/barrier.hpp>
  42. namespace boost {
  43. namespace fibers {
  44. class barrier {
  45. public:
  46. explicit barrier( std::size_t);
  47. barrier( barrier const&) = delete;
  48. barrier & operator=( barrier const&) = delete;
  49. bool wait();
  50. };
  51. }}
  52. Instances of __barrier__ are not copyable or movable.
  53. [heading Constructor]
  54. explicit barrier( std::size_t initial);
  55. [variablelist
  56. [[Effects:] [Construct a barrier for `initial` fibers.]]
  57. [[Throws:] [`fiber_error`]]
  58. [[Error Conditions:] [
  59. [*invalid_argument]: if `initial` is zero.]]
  60. ]
  61. [member_heading barrier..wait]
  62. bool wait();
  63. [variablelist
  64. [[Effects:] [Block until `initial` fibers have called `wait` on `*this`. When
  65. the `initial`-th fiber calls `wait`, all waiting fibers are unblocked, and
  66. the barrier is reset. ]]
  67. [[Returns:] [`true` for exactly one fiber from each batch of waiting fibers,
  68. `false` otherwise.]]
  69. [[Throws:] [__fiber_error__]]
  70. ]
  71. [endsect]