Move libcds 1.6.0 from SVN
[libcds.git] / cds / urcu / details / gpi.h
1 //$$CDS-header$$
2
3 #ifndef _CDS_URCU_DETAILS_GPI_H
4 #define _CDS_URCU_DETAILS_GPI_H
5
6 #include <cds/urcu/details/gp.h>
7 #include <cds/backoff_strategy.h>
8 #include <cds/lock/scoped_lock.h>
9
10 #include <cds/details/std/mutex.h>
11
12 namespace cds { namespace urcu {
13
14     /// User-space general-purpose RCU with immediate reclamation
15     /**
16         @headerfile cds/urcu/general_instant.h
17
18         This is simplest general-purpose RCU implementation. When a thread calls \ref retire_ptr function
19         the RCU \p synchronize function is called that waits until all reader/updater threads end up
20         their read-side critical sections, i.e. until the RCU quiescent state will come.
21         After that the retired object is freed immediately.
22         Thus, the implementation blocks for any retired object
23
24         There is a wrapper \ref cds_urcu_general_instant_gc "gc<general_instant>" for \p %general_instant class
25         that provides unified RCU interface. You should use this wrapper class instead \p %general_instant
26
27         Template arguments:
28         - \p Lock - mutex type, default is \p std::mutex
29         - \p Backoff - back-off schema, default is cds::backoff::Default
30     */
31     template <
32         class Lock = cds_std::mutex
33        ,class Backoff = cds::backoff::Default
34     >
35     class general_instant: public details::gp_singleton< general_instant_tag >
36     {
37         //@cond
38         typedef details::gp_singleton< general_instant_tag > base_class;
39         //@endcond
40
41     public:
42         typedef general_instant_tag rcu_tag ;   ///< RCU tag
43         typedef Lock    lock_type   ;           ///< Lock type
44         typedef Backoff back_off    ;           ///< Back-off schema type
45
46         typedef typename base_class::thread_gc  thread_gc ;   ///< Thread-side RCU part
47         typedef typename thread_gc::scoped_lock scoped_lock ; ///< Access lock class
48
49         static bool const c_bBuffered = false ; ///< This RCU does not buffer disposed elements
50
51     protected:
52         //@cond
53         typedef details::gp_singleton_instance< rcu_tag >    singleton_ptr;
54         //@endcond
55
56     protected:
57         //@cond
58         lock_type   m_Lock;
59         //@endcond
60
61     public:
62         /// Returns singleton instance
63         static general_instant * instance()
64         {
65             return static_cast<general_instant *>( base_class::instance() );
66         }
67
68         /// Checks if the singleton is created and ready to use
69         static bool isUsed()
70         {
71             return singleton_ptr::s_pRCU != null_ptr<singleton_vtbl *>();
72         }
73
74     protected:
75         //@cond
76         general_instant()
77         {}
78         ~general_instant()
79         {}
80
81         void flip_and_wait()
82         {
83             back_off bkoff;
84             base_class::flip_and_wait( bkoff );
85         }
86         //@endcond
87
88     public:
89         /// Creates singleton object
90         static void Construct()
91         {
92             if ( !singleton_ptr::s_pRCU )
93                 singleton_ptr::s_pRCU = new general_instant();
94         }
95
96         /// Destroys singleton object
97         static void Destruct( bool bDetachAll = false )
98         {
99             if ( isUsed() ) {
100                 if ( bDetachAll )
101                     instance()->m_ThreadList.detach_all();
102                 delete instance();
103                 singleton_ptr::s_pRCU = null_ptr<singleton_vtbl *>();
104             }
105         }
106
107     public:
108         /// Retires \p p pointer
109         /**
110             The method calls \ref synchronize to wait for the end of grace period
111             and calls \p p disposer.
112         */
113         virtual void retire_ptr( retired_ptr& p )
114         {
115             synchronize();
116             if ( p.m_p )
117                 p.free();
118         }
119
120         /// Retires the pointer chain [\p itFirst, \p itLast)
121         template <typename ForwardIterator>
122         void batch_retire( ForwardIterator itFirst, ForwardIterator itLast )
123         {
124             if ( itFirst != itLast ) {
125                 synchronize();
126                 while ( itFirst != itLast ) {
127                     retired_ptr p( *itFirst );
128                     ++itFirst;
129                     if ( p.m_p )
130                         p.free();
131                 }
132             }
133         }
134
135         /// Waits to finish a grace period
136         void synchronize()
137         {
138             CDS_ATOMIC::atomic_thread_fence( CDS_ATOMIC::memory_order_acquire );
139             {
140                 cds::lock::scoped_lock<lock_type> sl( m_Lock );
141                 flip_and_wait();
142                 flip_and_wait();
143             }
144             CDS_ATOMIC::atomic_thread_fence( CDS_ATOMIC::memory_order_release );
145         }
146
147         //@cond
148         // Added for uniformity
149         size_t CDS_CONSTEXPR capacity() const
150         {
151             return 1;
152         }
153         //@endcond
154     };
155
156 }} // namespace cds::urcu
157
158 #endif // #ifndef _CDS_URCU_DETAILS_GPI_H