1 /* ///////////////////////////////////////////////////////////////////////
7 * Brief: shared_array class - shared array
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
21 * - default deleter: new_allocator<T>::array_deleter_type
22 * - custom deleter function object:
25 * void operator()(int *p)
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(...));
37 # error shared_array.h need be supported by c++.
40 /* ///////////////////////////////////////////////////////////////////////
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 /* ///////////////////////////////////////////////////////////////////////
52 #if defined(EXTL_COMPILER_IS_MSVC) && (_MSC_VER <= 1200)
53 # pragma warning(push)
54 # pragma warning(disable:4284) /* odd return type for operator-> */
57 /* ///////////////////////////////////////////////////////////////////////
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
81 typedef shared_array
<T
, D
> class_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
;
93 typedef shared_counter
< value_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
;
99 typedef typename_type_k
shared_counter_type::size_type size_type
;
106 shared_counter_type m_shared_counter
;
109 /// \name Constructors
112 /* Constructor and destructor */
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());
156 /// operator=() overload
157 class_type
& operator=(class_type
const& rhs
)
159 EXTL_ASSERT(is_valid());
160 if(this != &rhs
) /* Prevent self-assigment */
163 m_shared_counter
= rhs
.m_shared_counter
;
165 EXTL_ASSERT(is_valid());
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 */
177 m_shared_counter
= rhs
.m_shared_counter
;
179 EXTL_ASSERT(is_valid());
187 reference
operator[](index_type
const& index
) const
189 EXTL_ASSERT(NULL
!= m_ptr
);
190 EXTL_ASSERT(index
>= 0);
191 EXTL_ASSERT(is_valid());
195 const_pointer
get_ptr() const
197 EXTL_ASSERT(is_valid());
203 EXTL_ASSERT(is_valid());
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();
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());
240 /* Reset the pointer */
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
>
255 EXTL_ASSERT(p
!= m_ptr
);
256 class_type(p
).swap(*this);
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
); }
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
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
; }
280 inline e_bool_t
is_valid() const
282 if((NULL
== m_ptr
) != m_shared_counter
.is_zero())
286 if((NULL
!= m_ptr
) && (m_shared_counter
.count() < 1))
294 /* ///////////////////////////////////////////////////////////////////////
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
);
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
)
330 template< typename_param_k T
, typename_param_k D
>
331 inline void swap(shared_array
<T
, D
>& lhs
, shared_array
<T
, D
>& rhs
)
336 template< typename_param_k T
, typename_param_k D
>
337 inline T
const* get_ptr(shared_array
<T
, D
> const& p
)
342 /* ///////////////////////////////////////////////////////////////////////
345 #ifdef EXTL_SHARED_ARRAY_TEST_ENABLE
346 # include "unit_test/shared_array_test.h"
349 /* ///////////////////////////////////////////////////////////////////////
354 /* ///////////////////////////////////////////////////////////////////////
357 #if defined(EXTL_COMPILER_IS_MSVC) && (_MSC_VER <= 1200)
358 # pragma warning(pop)
361 /* ///////////////////////////////////////////////////////////////////////
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
)
374 /* ::std namespace */
375 EXTL_STD_END_NAMESPACE
378 /* //////////////////////////////////////////////////////////////////// */
379 #endif /* EXTL_SMART_PTR_SHARED_ARRAY_H */
380 /* //////////////////////////////////////////////////////////////////// */