remove \r
[extl.git] / extl / smartptr / shared_array.h
blob120d010c6fdaa551e92c84f51cd03cc0c83f5969
1 /* ///////////////////////////////////////////////////////////////////////
2 * File: shared_array.h
4 * Created: 08.02.25
5 * Updated: 08.05.06
7 * Brief: shared_array class - shared array
9 * [<Home>]
10 * Copyright (c) 2008-2020, Waruqi All rights reserved.
11 * //////////////////////////////////////////////////////////////////// */
12 #ifndef EXTL_SMART_PTR_SHARED_ARRAY_H
13 #define EXTL_SMART_PTR_SHARED_ARRAY_H
15 /*!\file shared_array.h
16 * \brief shared_array class - shared array
18 * - custom thread-safe reference count
19 * - safe implicit conversion to the bool type
20 * - custom deleter
21 * - default deleter: new_allocator<T>::array_deleter_type
22 * - custom deleter function object:
23 * struct deleter
24 * {
25 * void operator()(int *p)
26 * {
27 * delete[] p;
28 * }
29 * };
30 * - usage:
31 * - shared_array<int, deleter > p(new int[10]); - using default deleter
32 * - shared_array<int, deleter > p(new int[10], deleter());
33 * - shared_array<int, deleter > p(new int[10], deleter(...));
36 #ifndef __cplusplus
37 # error shared_array.h need be supported by c++.
38 #endif
40 /* ///////////////////////////////////////////////////////////////////////
41 * Includes
43 #include "prefix.h"
44 #include "../utility/operator_bool.h"
45 #include "../algorithm/algorithm.h" /* for std_swap */
46 #include "../counter/shared_counter.h"
47 #include "../memory/allocator_selector.h"
49 /* ///////////////////////////////////////////////////////////////////////
50 * Warnings
52 #if defined(EXTL_COMPILER_IS_MSVC) && (_MSC_VER <= 1200)
53 # pragma warning(push)
54 # pragma warning(disable:4284) /* odd return type for operator-> */
55 #endif
57 /* ///////////////////////////////////////////////////////////////////////
58 * ::extl namespace
60 EXTL_BEGIN_NAMESPACE
62 /*!\brief shared_array class
64 * \param T The value type
65 * \param D The deleter type
67 * \ingroup extl_group_smart_ptr
69 template< typename_param_k T
70 #ifdef EXTL_TEMPLATE_CLASS_DEFAULT_ARGUMENT_SUPPORT
71 , typename_param_k D = typename_type_def_k new_allocator<T>::array_deleter_type
72 #else
73 , typename_param_k D
74 #endif
76 class shared_array
78 /// \name Types
79 /// @{
80 public:
81 typedef shared_array<T, D> class_type;
82 typedef T value_type;
83 typedef value_type* pointer;
84 typedef value_type const* const_pointer;
85 typedef value_type& reference;
86 typedef value_type const& const_reference;
87 typedef e_long_t index_type;
88 typedef D deleter_type;
90 #ifdef EXTL_TEMPLATE_CLASS_DEFAULT_ARGUMENT_SUPPORT
91 typedef shared_counter< value_type, deleter_type > shared_counter_type;
92 #else
93 typedef shared_counter < value_type
94 , deleter_type
95 , typename_type_k synch_traits_selector::synch_traits_type
96 , typename_type_k allocator_selector< e_byte_t >::allocator_type
97 > shared_counter_type;
98 #endif
99 typedef typename_type_k shared_counter_type::size_type size_type;
100 /// @}
102 /// \name Members
103 /// @{
104 private:
105 pointer m_ptr;
106 shared_counter_type m_shared_counter;
107 /// @}
109 /// \name Constructors
110 /// @{
111 public:
112 /* Constructor and destructor */
113 shared_array()
114 : m_ptr(NULL), m_shared_counter()
118 explicit_k shared_array(pointer p)
119 : m_ptr(p), m_shared_counter(p)
121 EXTL_ASSERT(is_valid());
124 shared_array(pointer p, deleter_type const& del)
125 : m_ptr(p), m_shared_counter(p, del)
127 EXTL_ASSERT(is_valid());
130 shared_array(class_type const& rhs)
131 : m_ptr(rhs.m_ptr), m_shared_counter(rhs.m_shared_counter)
133 EXTL_ASSERT(is_valid());
135 ~shared_array() EXTL_THROW_0()
138 #ifdef EXTL_MEMBER_TEMPLATE_CTOR_OVERLOAD_DISCRIMINATED_SUPPORT
139 template < typename_param_k T1 >
140 explicit_k shared_array(T1* p)
141 : m_ptr(p), m_shared_counter(p)
143 EXTL_ASSERT(is_valid());
146 template < typename_param_k T1, typename_param_k D1 >
147 shared_array(shared_array<T1, D1> const& rhs)
148 : m_ptr(rhs.m_ptr), m_shared_counter(rhs.m_shared_counter)
150 EXTL_ASSERT(is_valid());
152 #endif
153 /// @}
155 public:
156 /// operator=() overload
157 class_type& operator=(class_type const& rhs)
159 EXTL_ASSERT(is_valid());
160 if(this != &rhs) /* Prevent self-assigment */
162 m_ptr = rhs.m_ptr;
163 m_shared_counter = rhs.m_shared_counter;
165 EXTL_ASSERT(is_valid());
166 return *this;
168 #ifdef EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT
169 /// operator=() overload
170 template < typename_param_k T1, typename_param_k D1 >
171 class_type& operator=(shared_array<T1, D1> const& rhs)
173 EXTL_ASSERT(is_valid());
174 if(this != &rhs) /* Prevent self-assigment */
176 m_ptr = rhs.m_ptr;
177 m_shared_counter = rhs.m_shared_counter;
179 EXTL_ASSERT(is_valid());
180 return *this;
182 #endif
184 /// \name Accessors
185 /// @{
186 public:
187 reference operator[](index_type const& index) const
189 EXTL_ASSERT(NULL != m_ptr);
190 EXTL_ASSERT(index >= 0);
191 EXTL_ASSERT(is_valid());
193 return m_ptr[index];
195 const_pointer get_ptr() const
197 EXTL_ASSERT(is_valid());
198 return m_ptr;
201 pointer get_ptr()
203 EXTL_ASSERT(is_valid());
204 return m_ptr;
206 /* Returns the reference count */
207 size_type count() const
209 EXTL_ASSERT(is_valid());
210 return m_shared_counter.count();
212 e_bool_t is_unique() const
214 return m_shared_counter.is_unique();
216 /// @}
218 /// \name Mutators
219 /// @{
220 public:
221 /* swap */
222 void swap(class_type& other)
224 EXTL_ASSERT(is_valid());
225 std_swap(m_ptr, other.m_ptr);
226 m_shared_counter.swap(other.m_shared_counter);
227 EXTL_ASSERT(is_valid());
229 #ifdef EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT
230 template < typename_param_k T1, typename_param_k D1 >
231 void swap(shared_array<T1, D1>& other)
233 EXTL_ASSERT(is_valid());
234 std_swap(m_ptr, other.m_ptr);
235 m_shared_counter.swap(other.m_shared_counter);
236 EXTL_ASSERT(is_valid());
238 #endif
240 /* Reset the pointer */
241 void reset()
243 class_type().swap(*this);
245 void reset(pointer p)
247 EXTL_ASSERT(p != m_ptr);
248 class_type(p).swap(*this);
251 #ifdef EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT
252 template < typename_param_k T1 >
253 void reset(T1* p)
255 EXTL_ASSERT(p != m_ptr);
256 class_type(p).swap(*this);
258 #endif
259 /// @}
261 public:
262 /// safe implicit conversion to the bool type
263 EXTL_OPERATOR_BOOL_DEFINE_TYPE_T(class_type, safe_bool_type);
264 operator safe_bool_type() const
266 return EXTL_OPERATOR_BOOL_RETURN_RESULT(m_ptr != NULL);
269 e_bool_t operator !() const { return (m_ptr == NULL); }
271 /// less than
272 e_bool_t lt(class_type const & rhs) const { return m_ptr < rhs.m_ptr; }
273 #ifdef EXTL_MEMBER_TEMPLATE_FUNC_OVERLOAD_DISCRIMINATED_SUPPORT
274 /// less than
275 template < typename_param_k T1, typename_param_k D1 >
276 e_bool_t lt(shared_array<T1, D1> const & rhs) const { return m_ptr < rhs.m_ptr; }
277 #endif
279 private:
280 inline e_bool_t is_valid() const
282 if((NULL == m_ptr) != m_shared_counter.is_zero())
284 return e_false_v;
286 if((NULL != m_ptr) && (m_shared_counter.count() < 1))
288 return e_false_v;
290 return e_true_v;
294 /* ///////////////////////////////////////////////////////////////////////
295 * Operators overload
297 template< typename_param_k T, typename_param_k D >
298 inline e_bool_t operator==(shared_array<T, D> const& lhs, shared_array<T, D> const& rhs)
300 return lhs.get_ptr() == rhs.get_ptr();
303 template< typename_param_k T, typename_param_k D >
304 inline e_bool_t operator!=(shared_array<T, D> const& lhs, shared_array<T, D> const& rhs)
306 return lhs.get_ptr() != rhs.get_ptr();
309 /* VC6.0: p != NULL */
310 #if defined(EXTL_COMPILER_IS_MSVC) && (_MSC_VER == 1200)
311 template< typename_param_k T, typename_param_k D >
312 inline e_bool_t operator==(shared_array<T, D> const& lhs, void* rhs)
314 return lhs.get_ptr() == static_cast<T*>(rhs);
317 template< typename_param_k T, typename_param_k D >
318 inline e_bool_t operator!=(shared_array<T, D> const& lhs, void* rhs)
320 return lhs.get_ptr() != static_cast<T*>(rhs);
322 #endif
324 template< typename_param_k T, typename_param_k D >
325 inline e_bool_t operator<(shared_array<T, D> const& lhs, shared_array<T, D> const& rhs)
327 return lhs.lt(rhs);
329 /// swap
330 template< typename_param_k T, typename_param_k D >
331 inline void swap(shared_array<T, D>& lhs, shared_array<T, D>& rhs)
333 lhs.swap(rhs);
335 /// get pointer shim
336 template< typename_param_k T, typename_param_k D >
337 inline T const* get_ptr(shared_array<T, D> const& p)
339 return p.get_ptr();
342 /* ///////////////////////////////////////////////////////////////////////
343 * Unit-testing
345 #ifdef EXTL_SHARED_ARRAY_TEST_ENABLE
346 # include "unit_test/shared_array_test.h"
347 #endif
349 /* ///////////////////////////////////////////////////////////////////////
350 * ::extl namespace
352 EXTL_END_NAMESPACE
354 /* ///////////////////////////////////////////////////////////////////////
355 * Warnings
357 #if defined(EXTL_COMPILER_IS_MSVC) && (_MSC_VER <= 1200)
358 # pragma warning(pop)
359 #endif
361 /* ///////////////////////////////////////////////////////////////////////
362 * std::swap
364 #if !defined(EXTL_NO_STL) && \
365 !defined(EXTL_NO_NAMESPACE)
366 /* ::std namespace */
367 EXTL_STD_BEGIN_NAMESPACE
369 template< typename_param_k T, typename_param_k D >
370 inline void swap(EXTL_NS(shared_array)<T, D>& lhs, EXTL_NS(shared_array)<T, D>& rhs)
372 lhs.swap(rhs);
374 /* ::std namespace */
375 EXTL_STD_END_NAMESPACE
376 #endif
378 /* //////////////////////////////////////////////////////////////////// */
379 #endif /* EXTL_SMART_PTR_SHARED_ARRAY_H */
380 /* //////////////////////////////////////////////////////////////////// */