From: khizmax Date: Sat, 27 Sep 2014 14:29:35 +0000 (+0400) Subject: Move cds/intrusive/base.h to cds/intrusive/details directory X-Git-Tag: v2.0.0~284 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=8be59b70a3697023d33f7a7d3831d2875658645a;p=libcds.git Move cds/intrusive/base.h to cds/intrusive/details directory --- diff --git a/cds/container/base.h b/cds/container/base.h index bd6ed3e0..0a8372fa 100644 --- a/cds/container/base.h +++ b/cds/container/base.h @@ -3,7 +3,7 @@ #ifndef __CDS_CONTAINER_BASE_H #define __CDS_CONTAINER_BASE_H -#include +#include #include namespace cds { diff --git a/cds/intrusive/base.h b/cds/intrusive/base.h deleted file mode 100644 index 8fa8e4f6..00000000 --- a/cds/intrusive/base.h +++ /dev/null @@ -1,160 +0,0 @@ -//$$CDS-header$$ - -#ifndef __CDS_INTRUSIVE_BASE_H -#define __CDS_INTRUSIVE_BASE_H - -#include -#include -#include - -namespace cds { - -/// Intrusive containers -/** - @ingroup cds_intrusive_containers - The namespace cds::intrusive contains intrusive lock-free containers. - The idea comes from \p boost::intrusive library, see http://boost.org/doc/ as a good introduction to intrusive approach. - The intrusive containers of libcds library is developed as close to boost::intrusive - - In terms of lock-free approach, the main advantage of intrusive containers is - that no memory allocation is performed to maintain container items. - However, additional requirements is imposed for types and values that can be stored in intrusive container. - See the container documentation for details. - - Restriction for Gidenstam's garbage collector cds::gc::HRC: - the Gidenstam's garbage collector makes additional requirements to type of item in intrusive container. - Therefore, for this GC only \p base_hook is allowed as the value of opt::hook option. - - \anchor cds_intrusive_item_destroying - \par Destroying items - - It should be very careful when destroying an item removed from intrusive container. - In other threads the references to popped item may exists some time after removing. - To destroy the removed item in thread-safe manner you should call static function \p retire - of garbage collector you use, for example: - \code - struct destroyer { - void operator ()( my_type * p ) - { - delete p; - } - }; - - typedef cds::intrusive::TreiberStack< cds::gc::HP, my_type, cds::opt::disposer< destroyer > > stack; - stack s; - - // .... - - my_type * p = s.pop(); - - if ( p ) { - // It is wrong - // delete p; - - // It is correct - cds::gc:HP::retire< destroyer >( p ); - } - \endcode - The situation becomes even more complicated when you want store items in different intrusive containers. - In this case the best way is using reference counting: - \code - struct my_type { - ... - std::atomic nRefCount; - - my_type() - : nRefCount(0) - {} - }; - - struct destroyer { - void operator ()( my_type * p ) - { - if ( --p->nRefCount == 0 ) - delete p ; // delete only after no reference pointing to p - } - }; - - typedef cds::intrusive::TreiberStack< cds::gc::HP, my_type, cds::opt::disposer< destroyer > > stack; - typedef cds::intrusive::MSQueue< cds::gc::HP, my_type, cds::opt::disposer< destroyer > > queue; - stack s; - queue q; - - my_type * v = new my_type(); - - v.nRefCount++ ; // increment counter before pushing the item to the stack - s.push(v); - - v.nRefCount++ ; // increment counter before pushing the item to the queue - q.push(v); - - // .... - - my_type * ps = s.pop(); - if ( ps ) { - // It is wrong - // delete ps; - - // It is correct - cds::gc:HP::retire< destroyer >( ps ); - } - - my_type * pq = q.pop(); - if ( pq ) { - // It is wrong - // delete pq; - - // It is correct - cds::gc:HP::retire< destroyer >( pq ); - } - \endcode - Violation of these rules may lead to a crash. - - \par Intrusive containers and Hazard Pointer-like garbage collectors - - If you develop your intrusive container based on libcds library framework, you should - take in the account the following. - The main idea of garbage collectors (GC) based on Hazard Pointer schema is protecting a shared pointer - by publishing it as a "hazard" one i.e. as a pointer that is changing at the current time and cannot be - deleted at this moment. In intrusive container paradigm, the pointer to the node of the container - and the pointer to the item stored in the container are not equal in the general case. - However, any pointer to the node should be castable to the appropriate pointer to the container's item. - In general, any item can be placed to some different intrusive containers simultaneously, - and each of those container holds a unique pointer to its node that refers to the same item. - When we protect a pointer, we want to protect an item pointer that is the invariant - for any container stored that item. In your intrusive container, instead of protecting by GC's guard a pointer to an node - you should convert it to the pointer to the item and then protect resulting item pointer. - Otherwise an unpredictable result may occur. - -*/ -namespace intrusive { - - /// @defgroup cds_intrusive_containers Intrusive containers - /** @defgroup cds_intrusive_helper Helper structs for intrusive containers - @ingroup cds_intrusive_containers - */ - /** @defgroup cds_intrusive_stack Stack - @ingroup cds_intrusive_containers - */ - /** @defgroup cds_intrusive_queue Queue - @ingroup cds_intrusive_containers - */ - /** @defgroup cds_intrusive_priority_queue Priority queue - @ingroup cds_intrusive_containers - */ - /** @defgroup cds_intrusive_deque Deque - @ingroup cds_intrusive_containers - */ - /** @defgroup cds_intrusive_map Set - @ingroup cds_intrusive_containers - */ - /** @defgroup cds_intrusive_tree Tree - @ingroup cds_intrusive_containers - */ - /** @defgroup cds_intrusive_list List - @ingroup cds_intrusive_containers - */ - -}} // namespace cds::intrusuve - -#endif // #ifndef __CDS_INTRUSIVE_BASE_H diff --git a/cds/intrusive/basket_queue.h b/cds/intrusive/basket_queue.h index 3a2d4aed..331127a0 100644 --- a/cds/intrusive/basket_queue.h +++ b/cds/intrusive/basket_queue.h @@ -4,7 +4,7 @@ #define __CDS_INTRUSIVE_BASKET_QUEUE_H #include -#include +#include #include #include #include diff --git a/cds/intrusive/cuckoo_set.h b/cds/intrusive/cuckoo_set.h index 790a7852..87404c7a 100644 --- a/cds/intrusive/cuckoo_set.h +++ b/cds/intrusive/cuckoo_set.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/cds/intrusive/details/base.h b/cds/intrusive/details/base.h new file mode 100644 index 00000000..0845569c --- /dev/null +++ b/cds/intrusive/details/base.h @@ -0,0 +1,160 @@ +//$$CDS-header$$ + +#ifndef __CDS_INTRUSIVE_DETAILS_BASE_H +#define __CDS_INTRUSIVE_DETAILS_BASE_H + +#include +#include +#include + +namespace cds { + +/// Intrusive containers +/** + @ingroup cds_intrusive_containers + The namespace cds::intrusive contains intrusive lock-free containers. + The idea comes from \p boost::intrusive library, see http://boost.org/doc/ as a good introduction to intrusive approach. + The intrusive containers of libcds library is developed as close to boost::intrusive + + In terms of lock-free approach, the main advantage of intrusive containers is + that no memory allocation is performed to maintain container items. + However, additional requirements is imposed for types and values that can be stored in intrusive container. + See the container documentation for details. + + Restriction for Gidenstam's garbage collector cds::gc::HRC: + the Gidenstam's garbage collector makes additional requirements to type of item in intrusive container. + Therefore, for this GC only \p base_hook is allowed as the value of opt::hook option. + + \anchor cds_intrusive_item_destroying + \par Destroying items + + It should be very careful when destroying an item removed from intrusive container. + In other threads the references to popped item may exists some time after removing. + To destroy the removed item in thread-safe manner you should call static function \p retire + of garbage collector you use, for example: + \code + struct destroyer { + void operator ()( my_type * p ) + { + delete p; + } + }; + + typedef cds::intrusive::TreiberStack< cds::gc::HP, my_type, cds::opt::disposer< destroyer > > stack; + stack s; + + // .... + + my_type * p = s.pop(); + + if ( p ) { + // It is wrong + // delete p; + + // It is correct + cds::gc:HP::retire< destroyer >( p ); + } + \endcode + The situation becomes even more complicated when you want store items in different intrusive containers. + In this case the best way is using reference counting: + \code + struct my_type { + ... + std::atomic nRefCount; + + my_type() + : nRefCount(0) + {} + }; + + struct destroyer { + void operator ()( my_type * p ) + { + if ( --p->nRefCount == 0 ) + delete p ; // delete only after no reference pointing to p + } + }; + + typedef cds::intrusive::TreiberStack< cds::gc::HP, my_type, cds::opt::disposer< destroyer > > stack; + typedef cds::intrusive::MSQueue< cds::gc::HP, my_type, cds::opt::disposer< destroyer > > queue; + stack s; + queue q; + + my_type * v = new my_type(); + + v.nRefCount++ ; // increment counter before pushing the item to the stack + s.push(v); + + v.nRefCount++ ; // increment counter before pushing the item to the queue + q.push(v); + + // .... + + my_type * ps = s.pop(); + if ( ps ) { + // It is wrong + // delete ps; + + // It is correct + cds::gc:HP::retire< destroyer >( ps ); + } + + my_type * pq = q.pop(); + if ( pq ) { + // It is wrong + // delete pq; + + // It is correct + cds::gc:HP::retire< destroyer >( pq ); + } + \endcode + Violation of these rules may lead to a crash. + + \par Intrusive containers and Hazard Pointer-like garbage collectors + + If you develop your intrusive container based on libcds library framework, you should + take in the account the following. + The main idea of garbage collectors (GC) based on Hazard Pointer schema is protecting a shared pointer + by publishing it as a "hazard" one i.e. as a pointer that is changing at the current time and cannot be + deleted at this moment. In intrusive container paradigm, the pointer to the node of the container + and the pointer to the item stored in the container are not equal in the general case. + However, any pointer to the node should be castable to the appropriate pointer to the container's item. + In general, any item can be placed to some different intrusive containers simultaneously, + and each of those container holds a unique pointer to its node that refers to the same item. + When we protect a pointer, we want to protect an item pointer that is the invariant + for any container stored that item. In your intrusive container, instead of protecting by GC's guard a pointer to an node + you should convert it to the pointer to the item and then protect resulting item pointer. + Otherwise an unpredictable result may occur. + +*/ +namespace intrusive { + + /// @defgroup cds_intrusive_containers Intrusive containers + /** @defgroup cds_intrusive_helper Helper structs for intrusive containers + @ingroup cds_intrusive_containers + */ + /** @defgroup cds_intrusive_stack Stack + @ingroup cds_intrusive_containers + */ + /** @defgroup cds_intrusive_queue Queue + @ingroup cds_intrusive_containers + */ + /** @defgroup cds_intrusive_priority_queue Priority queue + @ingroup cds_intrusive_containers + */ + /** @defgroup cds_intrusive_deque Deque + @ingroup cds_intrusive_containers + */ + /** @defgroup cds_intrusive_map Set + @ingroup cds_intrusive_containers + */ + /** @defgroup cds_intrusive_tree Tree + @ingroup cds_intrusive_containers + */ + /** @defgroup cds_intrusive_list List + @ingroup cds_intrusive_containers + */ + +}} // namespace cds::intrusuve + +#endif // #ifndef __CDS_INTRUSIVE_DETAILS_BASE_H diff --git a/cds/intrusive/details/ellen_bintree_base.h b/cds/intrusive/details/ellen_bintree_base.h index f35ac11b..644c5b76 100644 --- a/cds/intrusive/details/ellen_bintree_base.h +++ b/cds/intrusive/details/ellen_bintree_base.h @@ -4,7 +4,7 @@ #define __CDS_INTRUSIVE_DETAILS_ELLEN_BINTREE_BASE_H #include -#include +#include #include #include #include diff --git a/cds/intrusive/details/single_link_struct.h b/cds/intrusive/details/single_link_struct.h index d3e3cc85..86363980 100644 --- a/cds/intrusive/details/single_link_struct.h +++ b/cds/intrusive/details/single_link_struct.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H #define __CDS_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H -#include +#include #include #include #include diff --git a/cds/intrusive/lazy_list_base.h b/cds/intrusive/lazy_list_base.h index 3afdef67..c4c12cbd 100644 --- a/cds/intrusive/lazy_list_base.h +++ b/cds/intrusive/lazy_list_base.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_LAZY_LIST_BASE_H #define __CDS_INTRUSIVE_LAZY_LIST_BASE_H -#include +#include #include #include #include diff --git a/cds/intrusive/michael_list_base.h b/cds/intrusive/michael_list_base.h index 68427162..33861c60 100644 --- a/cds/intrusive/michael_list_base.h +++ b/cds/intrusive/michael_list_base.h @@ -4,7 +4,7 @@ #define __CDS_INTRUSIVE_MICHAEL_LIST_BASE_H #include -#include +#include #include #include #include diff --git a/cds/intrusive/michael_set_base.h b/cds/intrusive/michael_set_base.h index f68b5a3b..f0fe5946 100644 --- a/cds/intrusive/michael_set_base.h +++ b/cds/intrusive/michael_set_base.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_MICHAEL_SET_BASE_H #define __CDS_INTRUSIVE_MICHAEL_SET_BASE_H -#include +#include #include #include #include diff --git a/cds/intrusive/mspriority_queue.h b/cds/intrusive/mspriority_queue.h index bd94dab3..ffe3adb2 100644 --- a/cds/intrusive/mspriority_queue.h +++ b/cds/intrusive/mspriority_queue.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_MSPRIORITY_QUEUE_H #define __CDS_INTRUSIVE_MSPRIORITY_QUEUE_H -#include +#include #include #include #include diff --git a/cds/intrusive/optimistic_queue.h b/cds/intrusive/optimistic_queue.h index e1d57948..d0d3cc9e 100644 --- a/cds/intrusive/optimistic_queue.h +++ b/cds/intrusive/optimistic_queue.h @@ -4,7 +4,7 @@ #define __CDS_INTRUSIVE_OPTIMISTIC_QUEUE_H #include -#include +#include #include #include #include diff --git a/cds/intrusive/segmented_queue.h b/cds/intrusive/segmented_queue.h index 2376e489..36e8abf1 100644 --- a/cds/intrusive/segmented_queue.h +++ b/cds/intrusive/segmented_queue.h @@ -4,7 +4,7 @@ #define __CDS_INTRUSIVE_SEGMENTED_QUEUE_H #include -#include +#include #include #include #include diff --git a/cds/intrusive/skip_list_base.h b/cds/intrusive/skip_list_base.h index 5e046961..5419dc4e 100644 --- a/cds/intrusive/skip_list_base.h +++ b/cds/intrusive/skip_list_base.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_SKIP_LIST_BASE_H #define __CDS_INTRUSIVE_SKIP_LIST_BASE_H -#include +#include #include #include #include diff --git a/cds/intrusive/split_list_base.h b/cds/intrusive/split_list_base.h index c8c99ed3..1c86abcc 100644 --- a/cds/intrusive/split_list_base.h +++ b/cds/intrusive/split_list_base.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_SPLIT_LIST_BASE_H #define __CDS_INTRUSIVE_SPLIT_LIST_BASE_H -#include +#include #include #include #include diff --git a/cds/intrusive/striped_set.h b/cds/intrusive/striped_set.h index f038f311..61feae6f 100644 --- a/cds/intrusive/striped_set.h +++ b/cds/intrusive/striped_set.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_STRIPED_SET_H #define __CDS_INTRUSIVE_STRIPED_SET_H -#include +#include #include #include diff --git a/cds/intrusive/tsigas_cycle_queue.h b/cds/intrusive/tsigas_cycle_queue.h index aeb22f56..5d6108ca 100644 --- a/cds/intrusive/tsigas_cycle_queue.h +++ b/cds/intrusive/tsigas_cycle_queue.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_TSIGAS_CYCLE_QUEUE_H #define __CDS_INTRUSIVE_TSIGAS_CYCLE_QUEUE_H -#include +#include #include #include #include diff --git a/cds/intrusive/vyukov_mpmc_cycle_queue.h b/cds/intrusive/vyukov_mpmc_cycle_queue.h index 9355e0e0..165cdb46 100644 --- a/cds/intrusive/vyukov_mpmc_cycle_queue.h +++ b/cds/intrusive/vyukov_mpmc_cycle_queue.h @@ -3,7 +3,7 @@ #ifndef __CDS_INTRUSIVE_VYUKOV_MPMC_CYCLE_QUEUE_H #define __CDS_INTRUSIVE_VYUKOV_MPMC_CYCLE_QUEUE_H -#include +#include #include namespace cds { namespace intrusive { diff --git a/projects/Win/vc12/cds.vcxproj b/projects/Win/vc12/cds.vcxproj index b1f56060..bcd93d76 100644 --- a/projects/Win/vc12/cds.vcxproj +++ b/projects/Win/vc12/cds.vcxproj @@ -736,6 +736,7 @@ + @@ -916,7 +917,6 @@ - diff --git a/projects/Win/vc12/cds.vcxproj.filters b/projects/Win/vc12/cds.vcxproj.filters index 27e6442c..ebbbe23d 100644 --- a/projects/Win/vc12/cds.vcxproj.filters +++ b/projects/Win/vc12/cds.vcxproj.filters @@ -542,9 +542,6 @@ Header Files\cds\opt - - Header Files\cds\intrusive - Header Files\cds\intrusive @@ -1277,5 +1274,8 @@ Header Files\cds\intrusive\details + + Header Files\cds\intrusive\details + \ No newline at end of file diff --git a/tests/test-hdr/queue/hdr_intrusive_msqueue.h b/tests/test-hdr/queue/hdr_intrusive_msqueue.h index 2bac05fa..0b3cb860 100644 --- a/tests/test-hdr/queue/hdr_intrusive_msqueue.h +++ b/tests/test-hdr/queue/hdr_intrusive_msqueue.h @@ -1,7 +1,7 @@ //$$CDS-header$$ #include "cppunit/cppunit_proxy.h" -#include +#include namespace queue { namespace ci = cds::intrusive; diff --git a/tests/test-hdr/queue/hdr_intrusive_segmented_queue.h b/tests/test-hdr/queue/hdr_intrusive_segmented_queue.h index 2881b521..a448c3ee 100644 --- a/tests/test-hdr/queue/hdr_intrusive_segmented_queue.h +++ b/tests/test-hdr/queue/hdr_intrusive_segmented_queue.h @@ -4,7 +4,7 @@ #define __CDSHDR_QUEUE_INTRUSIVE_SEGMENTED_QUEUE_H #include "cppunit/cppunit_proxy.h" -#include +#include #include "size_check.h" namespace queue { diff --git a/tests/test-hdr/queue/hdr_segmented_queue.h b/tests/test-hdr/queue/hdr_segmented_queue.h index d1e42919..633358b9 100644 --- a/tests/test-hdr/queue/hdr_segmented_queue.h +++ b/tests/test-hdr/queue/hdr_segmented_queue.h @@ -4,7 +4,7 @@ #define __CDSHDR_QUEUE_SEGMENTED_QUEUE_H #include "cppunit/cppunit_proxy.h" -#include +#include #include #include "size_check.h"