Fixed some CppCheck warnings in new HP and DHP implementations
[libcds.git] / cds / gc / details / hp_common.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_GC_DETAILS_HP_COMMON_H
32 #define CDSLIB_GC_DETAILS_HP_COMMON_H
33
34 #include <cds/algo/atomic.h>
35 #include <cds/gc/details/retired_ptr.h>
36
37 #ifdef CDS_ENABLE_HPSTAT
38 #   define CDS_HPSTAT( expr ) expr
39 #else
40 #   define CDS_HPSTAT( expr )
41 #endif
42
43 //@cond
44 namespace cds { namespace gc { namespace hp { namespace common {
45
46     /// Hazard pointer type
47     typedef void*   hazard_ptr;
48
49     /// Retired pointer
50     using cds::gc::details::retired_ptr;
51     using cds::gc::make_retired_ptr;
52
53     /// Hazard pointer guard
54     class guard
55     {
56     public:
57         guard() noexcept
58             : hp_( nullptr )
59             , next_( nullptr )
60         {}
61
62         template <typename T>
63         T* operator=( T* ptr ) noexcept
64         {
65             set( ptr );
66             return ptr;
67         }
68
69         std::nullptr_t operator=( std::nullptr_t ) noexcept
70         {
71             clear();
72             return nullptr;
73         }
74
75         hazard_ptr get() const noexcept
76         {
77             return hp_.load( atomics::memory_order_acquire );
78         }
79
80         hazard_ptr get( atomics::memory_order order ) const noexcept
81         {
82             return hp_.load( order );
83         }
84
85         template <typename T>
86         T* get_as() const noexcept
87         {
88             return reinterpret_cast<T*>( get() );
89         }
90
91         template <typename T>
92         void set( T* ptr ) noexcept
93         {
94             hp_.store( reinterpret_cast<hazard_ptr>( ptr ), atomics::memory_order_release );
95         }
96
97         void clear( atomics::memory_order order ) noexcept
98         {
99             hp_.store( nullptr, order );
100         }
101
102         void clear() noexcept
103         {
104             clear( atomics::memory_order_release );
105         }
106
107     private:
108         atomics::atomic<hazard_ptr>   hp_;
109
110     public:
111         guard* next_;   // free guard list
112     };
113
114     /// Array of guards
115     template <size_t Capacity>
116     class guard_array
117     {
118     public:
119         static size_t const c_nCapacity = Capacity;
120
121     public:
122         guard_array()
123             : arr_{ nullptr }
124         {}
125
126         static constexpr size_t capacity()
127         {
128             return c_nCapacity;
129         }
130
131         guard* operator[]( size_t idx ) const noexcept
132         {
133             assert( idx < capacity() );
134             return arr_[idx];
135         }
136
137         template <typename T>
138         void set( size_t idx, T* ptr ) noexcept
139         {
140             assert( idx < capacity());
141             assert( arr_[idx] != nullptr );
142
143             arr_[idx]->set( ptr );
144         }
145
146         void clear( size_t idx ) noexcept
147         {
148             assert( idx < capacity() );
149             assert( arr_[idx] != nullptr );
150
151             arr_[idx]->clear();
152         }
153
154         guard* release( size_t idx ) noexcept
155         {
156             assert( idx < capacity() );
157
158             guard* g = arr_[idx];
159             arr_[idx] = nullptr;
160             return g;
161         }
162
163         void reset( size_t idx, guard* g ) noexcept
164         {
165             assert( idx < capacity() );
166             assert( arr_[idx] == nullptr );
167
168             arr_[idx] = g;
169         }
170
171     private:
172         guard*  arr_[c_nCapacity];
173     };
174
175
176     /// Retired pointer disposer
177     typedef void ( *disposer_func )( void* );
178
179 }}}} // namespace cds::gc::hp::common
180 //@endcond
181
182 #endif // #ifndef CDSLIB_GC_DETAILS_HP_COMMON_H
183
184