update ~fifo docs
[boost_lockfree.git] / libs / lockfree / doc / lockfree.qbk
blobe2ca4a14e40d892e7acd57673f8bfed6022e58b8
1 [library Boost.Lockfree
2     [quickbook 1.4]
3     [authors [Blechmann, Tim]]
4     [copyright 2008-2009 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     ]
18 [c++]
21 [/  Images   ]
23 [def _note_                         [$images/note.png]]
24 [def _alert_                        [$images/caution.png]]
25 [def _detail_                       [$images/note.png]]
26 [def _tip_                          [$images/tip.png]]
28 [/  Links   ]
30 [def _lockfree_                      [^boost.lockfree]]
32 [/  unspecified stuff   ]
33 [def __unspecified_int__ /unspecified-int-type/]
34 [def __unspecified_bool__ /unspecified-bool-type/]
36 [section:disclaimer Disclaimer]
37 _lockfree_ is NOT a boost library!
38 [endsect]
40 [section Introduction]
42 [h2 What is _lockfree_?]
44 _lockfree_ provides implementations of lock-free data structures. Lock-free data structures can be accessed by multiple
45 threads without the necessity of blocking synchronization primitives such as guards. Lock-free data structures can be
46 used in real-time systems, where blocking algorithms may lead to high worst-case execution times, to avoid priority
47 inversion, or to increase the scalability for multi-processor machines.
49 The following data structures are provided:
51 * [classref boost::lockfree::fifo], a lock-free fifo queue
52 * [classref boost::lockfree::stack], a lock-free stack
53 * [classref boost::lockfree::atomic_int], an atomic integer class
55 [endsect]
58 [section Examples]
60 [h2 Atomic Integers]
62 The [classref boost::lockfree::atomic_int boost::lockfree::atomic_int] class implements fully synchronized atomic
63 integers numbers.
66 #include <boost/thread/thread.hpp>
67 #include <boost/lockfree/atomic_int.hpp>
68 #include <iostream>
70 boost::lockfree::atomic_int<int> counter(0);
72 const int iterations = 10000000;
74 void increment_counter(void)
76     for (int i = 0; i != iterations; ++i)
77         ++counter;
80 void decrement_counter(void)
82     for (int i = 0; i != iterations; ++i)
83         --counter;
86 int main(int argc, char* argv[])
88     // incrementing counter in one thread, decrementing in another
89     boost::thread thrd_inc(increment_counter);
90     boost::thread thrd_dec(decrement_counter);
92     thrd_inc.join();
93     thrd_dec.join();
95     std::cout << "counter value is " << counter << "." << std::endl;
99 This program outputs the following:
101 [pre
102 Counter value is 0.
107 [h2 Fifo]
109 The [classref boost::lockfree::fifo boost::lockfree::fifo] class implements a multi-writer/multi-reader fifo queue. The
110 following example shows how integer values are produced and consumed by 2 threads each:
113 #include <boost/thread/thread.hpp>
114 #include <boost/lockfree/atomic_int.hpp>
115 #include <boost/lockfree/fifo.hpp>
116 #include <iostream>
118 boost::lockfree::atomic_int<int> producer_count(0);
119 boost::lockfree::atomic_int<int> consumer_count(0);
121 boost::lockfree::fifo<int> fifo;
123 const int iterations = 1000000;
125 void producer(void)
127     for (int i = 0; i != iterations; ++i) {
128         int value = ++producer_count;
129         fifo.enqueue(value);
130     }
133 void consumer(void)
135     int value;
136     while (producer_count != 2*iterations) {
137         while (fifo.dequeue(&value))
138             ++consumer_count;
139     }
141     while (fifo.dequeue(&value))
142         ++consumer_count;
145 int main(int argc, char* argv[])
147     boost::thread thrd_p1(producer);
148     boost::thread thrd_p2(producer);
149     boost::thread thrd_c1(consumer);
150     boost::thread thrd_c2(consumer);
152     thrd_p1.join();
153     thrd_p2.join();
154     thrd_c1.join();
155     thrd_c2.join();
157     std::cout << "produced " << producer_count << " objects." << std::endl;
158     std::cout << "consumed " << consumer_count << " objects." << std::endl;
162 The program output is:
164 [pre
165 produced 2000000 objects.
166 consumed 2000000 objects.
170 [h2 Stack]
172 The [classref boost::lockfree::stack boost::lockfree::stack] class implements a multi-writer/multi-reader stack. The
173 following example shows how integer values are produced and consumed by 2 threads each:
176 #include <boost/thread/thread.hpp>
177 #include <boost/lockfree/atomic_int.hpp>
178 #include <boost/lockfree/stack.hpp>
179 #include <iostream>
181 boost::lockfree::atomic_int<int> producer_count(0);
182 boost::lockfree::atomic_int<int> consumer_count(0);
184 boost::lockfree::stack<int> stack;
186 const int iterations = 1000000;
188 void producer(void)
190     for (int i = 0; i != iterations; ++i) {
191         int value = ++producer_count;
192         stack.push(value);
193     }
196 void consumer(void)
198     int value;
199     while (producer_count != 2*iterations) {
200         while (stack.pop(&value))
201             ++consumer_count;
202     }
204     while (stack.pop(&value))
205         ++consumer_count;
209 int main(int argc, char* argv[])
211     boost::thread thrd_p1(producer);
212     boost::thread thrd_p2(producer);
213     boost::thread thrd_c1(consumer);
214     boost::thread thrd_c2(consumer);
216     thrd_p1.join();
217     thrd_p2.join();
218     thrd_c1.join();
219     thrd_c2.join();
221     std::cout << "produced " << producer_count << " objects." << std::endl;
222     std::cout << "consumed " << consumer_count << " objects." << std::endl;
225 The program output is:
227 [pre
228 produced 2000000 objects.
229 consumed 2000000 objects.
234 [endsect]
237 [section Reference]
239 [section boost::lockfree::fifo]
241 [classref boost::lockfree::fifo boost::lockfree::fifo] provides a multi-writer/multi-reader lockfree fifo class,
242 enqueueing and dequeueing is lockfree, construction/destruction has to be synchronized. A specialized [classref
243 boost::lockfree::fifo fifo] class for pointer-arguments is provided, which supports dequeueing to stl/boost-style smart
244 pointers. Its used type argument is limited to PODs.
246 It uses a freelist for memory management, freed nodes are pushed to the freelist, but not returned to the os. This may
247 result in leaking memory.
249 [section Synopsis]
251 [c++]
255 namespace boost {
256 namespace lockfree {
258 template <typename T, typename freelist_t = caching_freelist_t, typename Alloc = std::allocator<T> >
259 class fifo:
260     boost::noncopyable
262 public:
263     fifo(void);
264     explicit fifo(std::size_t initial_nodes);
265     ~fifo(void);
267     bool empty(void) const;
269     bool enqueue(T const & t);
270     bool dequeue(T * ret);
273 template <typename T, typename freelist_t = caching_freelist_t, typename Alloc = std::allocator<T> >
274 class fifo<T*>:
275     boost::noncopyable
277 public:
278     fifo(void);
279     explicit fifo(std::size_t initial_nodes);
280     ~fifo(void);
282     bool empty(void) const;
284     bool enqueue(T * t);
286     bool dequeue (T ** ret);
287     bool dequeue (std::auto_ptr<T> & ret);
288     bool dequeue (boost::scoped_ptr<T> & ret);
289     bool dequeue (boost::shared_ptr<T> & ret);
292 } /* namespace lockfree */
293 } /* namespace boost */
296 [endsect]
298 [section Members]
300 [heading Constructors]
302     fifo(void);
304 Default Constructor
306     explicit fifo(std::size_t initial_nodes);
308 Construct fifo with a number of initially allocated fifo nodes.
310 [heading Destructor]
312     ~fifo(void);
314 Destroys stored nodes and fifo, free all nodes from freelist.
316 [warning Not thread-safe, no enqueue/dequeue operation is allowed, when the destructor is running]
318 [heading Empty]
320     bool empty(void) const;
322 Returns: true, if fifo is empty.
324 [warning Not thread-safe, use for debugging purposes only]
327 [heading Enqueue]
329     bool enqueue(T const & t);
331 Enqueues object t to the fifo. Enqueueing may fail, if the freelist is not able to allocate a new fifo node.
333 Returns: true, if the enqueue operation is successful.
335 [note Thread-safe and non-blocking]
336 [important May block if node needs to be allocated from the operating system]
338 [heading Dequeue]
340     bool dequeue (T * ret);
342 Dequeue object from fifo.
344 Returns: true, if the dequeue operation is successful, false if fifo was empty.
346 Effect: if dequeue operation is successful, object is written to memory location denoted by ret.
348 [note Thread-safe and non-blocking]
350     bool dequeue (std::auto_ptr<T> & ret);
351     bool dequeue (boost::scoped_ptr<T> & ret);
352     bool dequeue (boost::shared_ptr<T> & ret);
354 The specialized class for pointer objects provides an api for dequeuing objects directly to smart pointers.
356 [endsect]
358 [section Memory Management]
360 The memory management of the fifo can be controlled via its `freelist_t` template argument. Two different freelists can
361 be used. `struct caching_freelist_t` selects a caching freelist, which can allocate more nodes from the operating
362 system, and `struct static_freelist_t` uses a fixed-sized freelist. With a fixed-sized freelist, the enqueue operation
363 may fail, while with a caching freelist, the enqueue operation may block.
365 [endsect]
368 [endsect]
370 [section boost::lockfree::stack]
372 [classref boost::lockfree::stack boost::lockfree::stack] provides a multi-writer/multi-reader lockfree stack class,
373 push and pop is lockfree, construction/destruction has to be synchronized.
375 It uses a caching freelist for memory management, freed nodes are pushed to the freelist. This may result in leaking
376 memory.
378 [section Synopsis]
380 [c++]
384 namespace boost {
385 namespace lockfree {
387 template <typename T, typename Alloc = std::allocator<T> >
388 class stack:
389     boost::noncopyable
391 public:
392     stack(void);
393     explicit stack(std::size_t n);
395     bool empty(void) const;
397     bool push(T const & v);
398     bool pop(T * ret);
401 } /* namespace lockfree */
402 } /* namespace boost */
405 [endsect]
407 [section Members]
409 [heading Constructors]
411     stack(void);
413 Default Constructor
415     explicit stack(std::size_t initial_nodes);
417 Construct stack with a number of initially allocated stack nodes.
420 [heading Destructor]
422     ~stack(void);
424 Destroys stack, free all nodes from freelist.
426 [heading Empty]
428     bool empty(void) const;
430 Returns: true, if stack is empty.
432 [warning Not thread-safe, use for debugging purposes only]
435 [heading Push]
437     bool push(T const & t);
439 Pushes object t to the stack. Pushing may fail, if the freelist is not able to allocate a new stack node.
441 [note Thread-safe and non-blocking]
442 [important May block, if node needs to be allocated from the operating system]
444 [heading Pop]
446     bool pop (T * ret);
448 Pop object from stack.
450 Returns: true, if the pop operation is successful, false if stack was empty.
451 Effect: if pop operation is successful, object is written to memory location denoted by ret.
453 [note Thread-safe and non-blocking]
455 [endsect]
457 [section Memory Management]
459 The memory management of the stack can be controlled via its `freelist_t` template argument. Two different freelists can
460 be used. `struct caching_freelist_t` selects a caching freelist, which can allocate more nodes from the operating
461 system, and `struct static_freelist_t` uses a fixed-sized freelist. With a fixed-sized freelist, the push operation
462 may fail, while with a caching freelist, the push operation may block.
464 [endsect]
466 [endsect]
468 [section boost::lockfree::atomic_int]
470 [classref boost::lockfree::atomic_int boost::lockfree::atomic_int] provides an implementation for atomic integers. It
471 does not provide the full interface of integer numbers, but a limited subset, that can be implemented with atomic
472 operations. Modifying an atomic integer acts as full memory barrier.
474 [section Synposis]
477 namespace boost {
478 namespace lockfree {
480 template <typename T>
481 class boost::lockfree::atomic_int:
483 public:
484     explicit atomic_int(T v = 0);
486     operator T(void) const;
487     void operator =(T v);
489     T operator +=(T v);
490     T operator -=(T v);
492     T operator ++(void);
493     T operator --(void);
495     T operator ++(int);
496     T operator --(int);
499 } /* namespace lockfree */
500 } /* namespace boost */
503 [endsect]
505 [section Members]
507 [heading Constructor]
509     explicit atomic_int(T v = 0);
511 Initializes atomic_int to value v
514 [heading Conversion]
515     operator T(void) const;
517 Returns: Integer value of atomic_int
519 [heading In-Place Operators]
521     T operator +=(T v);
523 Returns: T(*this) + v
525 Effect: T(*this) = T(*this) + v
527     T operator -=(T v);
529 Returns: T(*this) - v
531 Effect: T(*this) = T(*this) - v
534 [heading Prefix Operators]
536     T operator ++(void);
538 Effect: increments value
540 Returns: value before incrementing
542     T operator --(void);
544 Effect: decrements value
546 Returns: value before decrementing
548 [heading Postfix Operators]
550     T operator ++(int);
552 Effect: increments value
554 Returns: value after incrementing
556     T operator --(int);
558 Effect: decrements value
560 Returns: value after decrementing
563 [endsect]
565 [endsect]
567 [endsect]
571 [section Building blocks]
572 The _lockfree_ library provides several building blocks, used in lockfree algorithms.
575 [section tagged_ptr]
577 Tagged pointer implementation as smart pointer class, as it is required by several lockfree algorithms.
579 [section Synposis]
581 namespace boost
583 namespace lockfree
586 template <class T>
587 class tagged_ptr
589 public:
590     typedef __unspecified_int__ tag_t;
592     tagged_ptr(void);
593     tagged_ptr(tagged_ptr const & p);
594     explicit tagged_ptr(T * p, tag_t t = 0);
596     void operator= (tagged_ptr const & p);
597     void atomic_set(tagged_ptr const & p);
598     void atomic_set(T * p, tag_t t);
600     void set(tagged_ptr const & p);
601     void set(T * p, tag_t t);
603     bool operator== (tagged_ptr const & p) const;
604     bool operator!= (tagged_ptr const & p) const;
606     T * get_ptr() const;
607     void set_ptr(T * p);
609     tag_t get_tag() const;
610     void set_tag(tag_t t);
612     bool cas(tagged_ptr const & oldval, T * newptr);
613     bool cas(tagged_ptr const & oldval, T * newptr, tag_t t);
615     T & operator*() const;
616     T * operator->() const;
618     operator __unspecified_bool__(void) const;
621 } /* namespace lockfree */
622 } /* namespace boost */
625 [endsect]
627 [section Members]
629 [heading tag_t]
631     typedef __unspecified_int__ tag_t;
633 Type of ABA-prevention tag
635 [heading Constructors]
637     tagged_ptr(void);
639 Uninitialized constructor
641     tagged_ptr(tagged_ptr const & p);
643 Copy Constructor
645     explicit tagged_ptr(T * p, tag_t t = 0);
647 Construct tagged_ptr from pointer and tag
650 [heading Atomically Set]
652     void operator= (tagged_ptr const & p);
653     void atomic_set(tagged_ptr const & p);
655 Atomically set from tagged_ptr.
657     void atomic_set(T * p, tag_t t);
659 Atomically set from pointer and tag
661 [heading Set]
662     void set(tagged_ptr const & p);
664 Set from tagged_ptr
666     void set(T * p, tag_t t);
668 Set from pointer and tag
670 [heading Comparison]
671     bool operator== (tagged_ptr const & p) const;
672     bool operator!= (tagged_ptr const & p) const;
674 Returns: (get_ptr() == p.get_ptr()) && (get_tag() == p.get_tag())
676 [heading Pointer access]
678     T * get_ptr() const;
680 Get pointer
682     void set_ptr(T * p);
684 Set pointer
687 [heading Tag access]
689     tag_t get_tag() const;
691 Get tag
693     void set_tag(tag_t t);
695 Set tag
697 [heading Compare-And-Swap]
699     bool cas(tagged_ptr const & oldval, T * newptr);
701 if (*this == oldval) {
702     this->set(newptr, oldval.get_tag() + 1);
703     return true;
705 else
706     return false;
708     bool cas(tagged_ptr const & oldval, T * newptr, tag_t t);
710 if (*this == oldval) {
711     this->set(newptr, t);
712     return true;
714 else
715     return false;
717 [heading Indirection]
718     T & operator*() const;
720 Returns: reference to object, undefined if get_ptr() == 0
722     T * operator->() const;
724 Returns: pointer to object
726 [heading Conversion]
728     operator __unspecified_bool__(void) const;
730 Returns: get_ptr() != 0
733 [endsect]
735 [endsect]
737 [section Freelists]
739 [section Freelist Concept]
742 template <typename T, typename Alloc = std::allocator<T> >
743 concept freelist
745 public:
746     freelist(void);
747     explicit freelist(std::size_t initial_nodes);
748     ~freelist(void);
750     T * allocate (void);
751     void deallocate (T * n);
755 [endsect]
758 [section Members]
761 [heading Constructors]
763     freelist(void);
765 Default Constructor
767     explicit freelist(std::size_t initial_nodes);
769 Construct freelist, allocate a number of initial nodes
772 [heading Destructor]
774     ~freelist(void);
776 Free all nodes from the freelist to the OS
779 [heading Allocation]
781     T * allocate (void);
783 Allocate memory for one object.
786 [heading Deallocation]
788     void deallocate (T * n);
790 Deallocate object to freelist
792 [endsect]
794 [section Freelist Implementations]
796     template <typename T, typename Alloc = std::allocator<T> >
797     class caching_freelist;
799 Caching freelist class. Uses an internal lockfree stack to cache objects. Deallocation never frees objects.
801     template <typename T, std::size_t max_size = 64,
802               typename Alloc = std::allocator<T> >
803     class freelist;
805 Freelist class, with a maximum size of max_size. Uses an lockfree stack to cache max_size objects.
807 [endsect]
808 [endsect]
809 [endsect]
815 [section Primitives]
816 The _lockfree_ library provides platform-specific wrappers for low-level operations.
818 [section Memory Barriers]
819     void boost::lockfree::detail::memory_barrier(void);
821 Full Memory Barrier.
823 [endsect]
825 [section Compare-and-Swap]
827 Lockfree on supported platforms, otherwise blocking emulation.
829     template <class C>
830     inline bool boost::lockfree::detail::atomic_cas(volatile C * addr, C old, C nw);
832 Single-word compare-and-swap
834     template <class C, class D, class E>
835     inline bool boost::lockfree::detail::atomic_cas2(volatile C * addr, D old1, E old2, D new1, E new2);
837 Double-word compare-and-swap
839 [endsect]
841 [endsect]
845 [section Portability]
847 Most data structures of _lockfree_ are written to use of Compare-And-Swap instructions. In order to implement the
848 tagged_ptr, CAS instructions are required, that can operate on one pointer and one integer type. For non-supported
849 platforms, a blocking emulation of the atomic instructions is provided.
851 Tested architectures:
853 * x86
854 * x86_64
856 Tested compilers:
858 * gcc-4.2, gcc-4.3, gcc-4.4
861 [endsect]
863 [section Acknowledgements]
865 Thanks for suggestions, porting, testing:
867 * Thomas Grill, original win32/osx code pieces
868 * Shiwei Xu, api suggestions
869 * Stefan Eilemann, bug fixes
870 * Mignon Belongie, bug fix
871 * Anthony Williams, found fifo race condition
872 * Casey McCandless, msvc/icc fixes
873 * Mark Bulas, msvc/x64 fixes
874 * Anteru, api/documentation suggestions
876 [endsect]
878 [section References]
880 # Maged M. Michael and Michael L. Scott. Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms. In Symposium on Principles of Distributed Computing, pages 267–275, 1996.
881 # M. Herlihy, V. Luchangco, P. Martin, and M. Moir. Nonblocking memory management support for dynamic-sized data
882 structures. ACM Transactions on Computer Systems (TOCS), 23(2):146–196, 2005.
885 [endsect]
888 [section Todo]
890 # Compare-And-Swap instructions return the old value, one can make use of this in order to avoid an additional memory
891 access (suggested by Cory Nelson).
892 # Adapt algorithms to be lockfree on architectures with load-linked/store-conditional instructions.
894 [endsect]