Fixed UBsan warning "call to function through pointer to incorrect function type"
[libcds.git] / cds / urcu / general_buffered.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef CDSLIB_URCU_GENERAL_BUFFERED_H
32 #define CDSLIB_URCU_GENERAL_BUFFERED_H
33
34 #include <cds/urcu/details/gpb.h>
35
36 namespace cds { namespace urcu {
37
38     /// User-space general-purpose RCU with deferred buffered reclamation
39     /** @anchor cds_urcu_general_buffered_gc
40
41         This is a wrapper around \p general_buffered class.
42
43         Template arguments:
44         - \p Buffer - lock-free queue or lock-free bounded queue.
45             Default is \p cds::container::VyukovMPMCCycleQueue< retired_ptr >
46         - \p Lock - mutex type, default is \p std::mutex
47         - \p Backoff - back-off schema, default is \p cds::backoff::Default
48     */
49     template <
50 #ifdef CDS_DOXGEN_INVOKED
51         class Buffer = cds::container::VyukovMPMCCycleQueue< retired_ptr >
52         ,class Lock = std::mutex
53         ,class Backoff = cds::backoff::Default
54 #else
55         class Buffer
56        ,class Lock
57        ,class Backoff
58 #endif
59     >
60     class gc< general_buffered< Buffer, Lock, Backoff > >: public details::gc_common
61     {
62     public:
63         typedef general_buffered< Buffer, Lock, Backoff >  rcu_implementation   ;    ///< Wrapped URCU implementation
64
65         typedef typename rcu_implementation::rcu_tag     rcu_tag     ;   ///< URCU tag
66         typedef typename rcu_implementation::thread_gc   thread_gc   ;   ///< Thread-side RCU part
67         typedef typename rcu_implementation::scoped_lock scoped_lock ;   ///< Access lock class
68
69         using details::gc_common::atomic_marked_ptr;
70
71     public:
72         /// Creates URCU \p %general_buffered singleton.
73         gc( size_t nBufferCapacity = 256 )
74         {
75             rcu_implementation::Construct( nBufferCapacity );
76         }
77
78         /// Destroys URCU \p %general_instant singleton
79         ~gc()
80         {
81             rcu_implementation::Destruct( true );
82         }
83
84     public:
85         /// Waits to finish a grace period and clears the buffer
86         /**
87             After grace period finished the function frees all retired pointer
88             from internal buffer.
89         */
90         static void synchronize()
91         {
92             rcu_implementation::instance()->synchronize();
93         }
94
95         /// Places retired pointer <\p p, \p pFunc> to internal buffer
96         /**
97             If the buffer is full, \ref synchronize function is invoked.
98         */
99         template <typename T>
100         static void retire_ptr( T * p, free_retired_ptr_func pFunc )
101         {
102             retired_ptr rp( p, pFunc );
103             retire_ptr( rp );
104         }
105
106         /// Places retired pointer \p p with \p Disposer to internal buffer
107         /**
108             If the buffer is full, \ref synchronize function is invoked.
109         */
110         template <typename Disposer, typename T>
111         static void retire_ptr( T * p )
112         {
113             retire_ptr( p, cds::details::static_functor<Disposer, T>::call );
114         }
115
116         /// Places retired pointer \p p to internal buffer
117         /**
118             If the buffer is full, \ref synchronize function is invoked.
119         */
120         static void retire_ptr( retired_ptr& p )
121         {
122             rcu_implementation::instance()->retire_ptr(p);
123         }
124
125         /// Frees chain [ \p itFirst, \p itLast) in one synchronization cycle
126         template <typename ForwardIterator>
127         static void batch_retire( ForwardIterator itFirst, ForwardIterator itLast )
128         {
129             rcu_implementation::instance()->batch_retire( itFirst, itLast );
130         }
131
132         /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
133         template <typename Func>
134         static void batch_retire( Func e )
135         {
136             rcu_implementation::instance()->batch_retire( e );
137         }
138
139          /// Acquires access lock (so called RCU reader-side lock)
140         /**
141             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
142         */
143         static void access_lock()
144         {
145             thread_gc::access_lock();
146         }
147
148         /// Releases access lock (so called RCU reader-side lock)
149         /**
150             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
151         */
152         static void access_unlock()
153         {
154             thread_gc::access_unlock();
155         }
156
157         /// Returns the threshold of internal buffer
158         static size_t capacity()
159         {
160             return rcu_implementation::instance()->capacity();
161         }
162
163         /// Checks if the thread is inside read-side critical section (i.e. the lock is acquired)
164         /**
165             Usually, this function is used internally to be convinced
166             that subsequent remove action is not lead to a deadlock.
167         */
168         static bool is_locked()
169         {
170             return thread_gc::is_locked();
171         }
172
173         /// Forces retired object removal
174         /**
175             This function calls \ref synchronize
176         */
177         static void force_dispose()
178         {
179             synchronize();
180         }
181     };
182
183     //@cond
184     template<>
185     class gc< general_buffered_stripped >: public gc< general_buffered<>>
186     {};
187     //@endcond
188
189 }} // namespace cds::urcu
190
191 #endif // #ifndef CDSLIB_URCU_GENERAL_BUFFERED_H