lockfree.qbk 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. [library Boost.Lockfree
  2. [quickbook 1.4]
  3. [authors [Blechmann, Tim]]
  4. [copyright 2008-2011 Tim Blechmann]
  5. [category algorithms]
  6. [purpose
  7. lockfree concurrent data structures
  8. ]
  9. [id lockfree]
  10. [dirname lockfree]
  11. [license
  12. Distributed under the Boost Software License, Version 1.0.
  13. (See accompanying file LICENSE_1_0.txt or copy at
  14. [@http://www.boost.org/LICENSE_1_0.txt])
  15. ]
  16. ]
  17. [c++]
  18. [/ Images ]
  19. [def _note_ [$images/note.png]]
  20. [def _alert_ [$images/caution.png]]
  21. [def _detail_ [$images/note.png]]
  22. [def _tip_ [$images/tip.png]]
  23. [/ Links ]
  24. [def _lockfree_ [^boost.lockfree]]
  25. [section Introduction & Motivation]
  26. [h2 Introduction & Terminology]
  27. The term *non-blocking* denotes concurrent data structures, which do not use traditional synchronization primitives like
  28. guards to ensure thread-safety. Maurice Herlihy and Nir Shavit (compare [@http://books.google.com/books?id=pFSwuqtJgxYC
  29. "The Art of Multiprocessor Programming"]) distinguish between 3 types of non-blocking data structures, each having different
  30. properties:
  31. * data structures are *wait-free*, if every concurrent operation is guaranteed to be finished in a finite number of
  32. steps. It is therefore possible to give worst-case guarantees for the number of operations.
  33. * data structures are *lock-free*, if some concurrent operations are guaranteed to be finished in a finite number of
  34. steps. While it is in theory possible that some operations never make any progress, it is very unlikely to happen in
  35. practical applications.
  36. * data structures are *obstruction-free*, if a concurrent operation is guaranteed to be finished in a finite number of
  37. steps, unless another concurrent operation interferes.
  38. Some data structures can only be implemented in a lock-free manner, if they are used under certain restrictions. The
  39. relevant aspects for the implementation of _lockfree_ are the number of producer and consumer threads. *Single-producer*
  40. (*sp*) or *multiple producer* (*mp*) means that only a single thread or multiple concurrent threads are allowed to add
  41. data to a data structure. *Single-consumer* (*sc*) or *Multiple-consumer* (*mc*) denote the equivalent for the removal
  42. of data from the data structure.
  43. [h2 Properties of Non-Blocking Data Structures]
  44. Non-blocking data structures do not rely on locks and mutexes to ensure thread-safety. The synchronization is done completely in
  45. user-space without any direct interaction with the operating system [footnote Spinlocks do not
  46. directly interact with the operating system either. However it is possible that the owning thread is preempted by the
  47. operating system, which violates the lock-free property.]. This implies that they are not prone to issues like priority
  48. inversion (a low-priority thread needs to wait for a high-priority thread).
  49. Instead of relying on guards, non-blocking data structures require *atomic operations* (specific CPU instructions executed
  50. without interruption). This means that any thread either sees the state before or after the operation, but no
  51. intermediate state can be observed. Not all hardware supports the same set of atomic instructions. If it is not
  52. available in hardware, it can be emulated in software using guards. However this has the obvious drawback of losing the
  53. lock-free property.
  54. [h2 Performance of Non-Blocking Data Structures]
  55. When discussing the performance of non-blocking data structures, one has to distinguish between *amortized* and
  56. *worst-case* costs. The definition of 'lock-free' and 'wait-free' only mention the upper bound of an operation. Therefore
  57. lock-free data structures are not necessarily the best choice for every use case. In order to maximise the throughput of an
  58. application one should consider high-performance concurrent data structures [footnote
  59. [@http://threadingbuildingblocks.org/ Intel's Thread Building Blocks library] provides many efficient concurrent data structures,
  60. which are not necessarily lock-free.].
  61. Lock-free data structures will be a better choice in order to optimize the latency of a system or to avoid priority inversion,
  62. which may be necessary in real-time applications. In general we advise to consider if lock-free data structures are necessary or if
  63. concurrent data structures are sufficient. In any case we advice to perform benchmarks with different data structures for a
  64. specific workload.
  65. [h2 Sources of Blocking Behavior]
  66. Apart from locks and mutexes (which we are not using in _lockfree_ anyway), there are three other aspects, that could violate
  67. lock-freedom:
  68. [variablelist
  69. [[Atomic Operations]
  70. [Some architectures do not provide the necessary atomic operations in natively in hardware. If this is not
  71. the case, they are emulated in software using spinlocks, which by itself is blocking.
  72. ]
  73. ]
  74. [[Memory Allocations]
  75. [Allocating memory from the operating system is not lock-free. This makes it impossible to implement true
  76. dynamically-sized non-blocking data structures. The node-based data structures of _lockfree_ use a memory pool to allocate the
  77. internal nodes. If this memory pool is exhausted, memory for new nodes has to be allocated from the operating system. However
  78. all data structures of _lockfree_ can be configured to avoid memory allocations (instead the specific calls will fail).
  79. This is especially useful for real-time systems that require lock-free memory allocations.
  80. ]
  81. ]
  82. [[Exception Handling]
  83. [The C++ exception handling does not give any guarantees about its real-time behavior. We therefore do
  84. not encourage the use of exceptions and exception handling in lock-free code.]
  85. ]
  86. ]
  87. [h2 Data Structures]
  88. _lockfree_ implements three lock-free data structures:
  89. [variablelist
  90. [[[classref boost::lockfree::queue]]
  91. [a lock-free multi-produced/multi-consumer queue]
  92. ]
  93. [[[classref boost::lockfree::stack]]
  94. [a lock-free multi-produced/multi-consumer stack]
  95. ]
  96. [[[classref boost::lockfree::spsc_queue]]
  97. [a wait-free single-producer/single-consumer queue (commonly known as ringbuffer)]
  98. ]
  99. ]
  100. [h3 Data Structure Configuration]
  101. The data structures can be configured with [@boost:/libs/parameter/doc/html/index.html Boost.Parameter]-style templates:
  102. [variablelist
  103. [[[classref boost::lockfree::fixed_sized]]
  104. [Configures the data structure as *fixed sized*. The internal nodes are stored inside an array and they are addressed by
  105. array indexing. This limits the possible size of the queue to the number of elements that can be addressed by the index
  106. type (usually 2**16-2), but on platforms that lack double-width compare-and-exchange instructions, this is the best way
  107. to achieve lock-freedom.
  108. ]
  109. ]
  110. [[[classref boost::lockfree::capacity]]
  111. [Sets the *capacity* of a data structure at compile-time. This implies that a data structure is fixed-sized.
  112. ]
  113. ]
  114. [[[classref boost::lockfree::allocator]]
  115. [Defines the allocator. _lockfree_ supports stateful allocator and is compatible with [@boost:/libs/interprocess/index.html Boost.Interprocess] allocators.]
  116. ]
  117. ]
  118. [endsect]
  119. [section Examples]
  120. [h2 Queue]
  121. The [classref boost::lockfree::queue boost::lockfree::queue] class implements a multi-writer/multi-reader queue. The
  122. following example shows how integer values are produced and consumed by 4 threads each:
  123. [import ../examples/queue.cpp]
  124. [queue_example]
  125. The program output is:
  126. [pre
  127. produced 40000000 objects.
  128. consumed 40000000 objects.
  129. ]
  130. [h2 Stack]
  131. The [classref boost::lockfree::stack boost::lockfree::stack] class implements a multi-writer/multi-reader stack. The
  132. following example shows how integer values are produced and consumed by 4 threads each:
  133. [import ../examples/stack.cpp]
  134. [stack_example]
  135. The program output is:
  136. [pre
  137. produced 4000000 objects.
  138. consumed 4000000 objects.
  139. ]
  140. [h2 Waitfree Single-Producer/Single-Consumer Queue]
  141. The [classref boost::lockfree::spsc_queue boost::lockfree::spsc_queue] class implements a wait-free single-producer/single-consumer queue. The
  142. following example shows how integer values are produced and consumed by 2 separate threads:
  143. [import ../examples/spsc_queue.cpp]
  144. [spsc_queue_example]
  145. The program output is:
  146. [pre
  147. produced 10000000 objects.
  148. consumed 10000000 objects.
  149. ]
  150. [endsect]
  151. [section Rationale]
  152. [section Data Structures]
  153. The implementations are implementations of well-known data structures. The queue is based on
  154. [@http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.3574 Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms by Michael Scott and Maged Michael],
  155. the stack is based on [@http://books.google.com/books?id=YQg3HAAACAAJ Systems programming: coping with parallelism by R. K. Treiber]
  156. and the spsc_queue is considered as 'folklore' and is implemented in several open-source projects including the linux kernel. All
  157. data structures are discussed in detail in [@http://books.google.com/books?id=pFSwuqtJgxYC "The Art of Multiprocessor Programming" by Herlihy & Shavit].
  158. [endsect]
  159. [section Memory Management]
  160. The lock-free [classref boost::lockfree::queue] and [classref boost::lockfree::stack] classes are node-based data structures,
  161. based on a linked list. Memory management of lock-free data structures is a non-trivial problem, because we need to avoid that
  162. one thread frees an internal node, while another thread still uses it. _lockfree_ uses a simple approach not returning any memory
  163. to the operating system. Instead they maintain a *free-list* in order to reuse them later. This is done for two reasons:
  164. first, depending on the implementation of the memory allocator freeing the memory may block (so the implementation would not
  165. be lock-free anymore), and second, most memory reclamation algorithms are patented.
  166. [endsect]
  167. [section ABA Prevention]
  168. The ABA problem is a common problem when implementing lock-free data structures. The problem occurs when updating an atomic
  169. variable using a =compare_exchange= operation: if the value A was read, thread 1 changes it to say C and tries to update
  170. the variable, it uses =compare_exchange= to write C, only if the current value is A. This might be a problem if in the meanwhile
  171. thread 2 changes the value from A to B and back to A, because thread 1 does not observe the change of the state. The common way to
  172. avoid the ABA problem is to associate a version counter with the value and change both atomically.
  173. _lockfree_ uses a =tagged_ptr= helper class which associates a pointer with an integer tag. This usually requires a double-width
  174. =compare_exchange=, which is not available on all platforms. IA32 did not provide the =cmpxchg8b= opcode before the pentium
  175. processor and it is also lacking on many RISC architectures like PPC. Early X86-64 processors also did not provide a =cmpxchg16b=
  176. instruction.
  177. On 64bit platforms one can work around this issue, because often not the full 64bit address space is used. On X86_64 for example,
  178. only 48bit are used for the address, so we can use the remaining 16bit for the ABA prevention tag. For details please consult the
  179. implementation of the =boost::lockfree::detail::tagged_ptr= class.
  180. For lock-free operations on 32bit platforms without double-width =compare_exchange=, we support a third approach: by using a
  181. fixed-sized array to store the internal nodes we can avoid the use of 32bit pointers, but instead 16bit indices into the array
  182. are sufficient. However this is only possible for fixed-sized data structures, that have an upper bound of internal nodes.
  183. [endsect]
  184. [section Interprocess Support]
  185. The _lockfree_ data structures have basic support for [@boost:/libs/interprocess/index.html Boost.Interprocess]. The only
  186. problem is the blocking emulation of lock-free atomics, which in the current implementation is not guaranteed to be interprocess-safe.
  187. [endsect]
  188. [endsect]
  189. [xinclude autodoc.xml]
  190. [section Appendices]
  191. [section Supported Platforms & Compilers]
  192. _lockfree_ has been tested on the following platforms:
  193. * g++ 4.4, 4.5 and 4.6, linux, x86 & x86_64
  194. * clang++ 3.0, linux, x86 & x86_64
  195. [endsect]
  196. [section Future Developments]
  197. * More data structures (set, hash table, dequeue)
  198. * Backoff schemes (exponential backoff or elimination)
  199. [endsect]
  200. [section References]
  201. # [@http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.3574 Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms by Michael Scott and Maged Michael],
  202. In Symposium on Principles of Distributed Computing, pages 267–275, 1996.
  203. # [@http://books.google.com/books?id=pFSwuqtJgxYC M. Herlihy & Nir Shavit. The Art of Multiprocessor Programming], Morgan Kaufmann Publishers, 2008
  204. [endsect]
  205. [endsect]