SharedArray.h
Go to the documentation of this file.
1/* -*- C++ -*- */
2
3/****************************************************************************
4** Copyright (c) 2001-2014
5**
6** This file is part of the QuickFIX FIX Engine
7**
8** This file may be distributed under the terms of the quickfixengine.org
9** license as defined by quickfixengine.org and appearing in the file
10** LICENSE included in the packaging of this file.
11**
12** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14**
15** See http://www.quickfixengine.org/LICENSE for licensing information.
16**
17** Contact ask@quickfixengine.org if any conditions of this licensing are
18** not clear to you.
19**
20****************************************************************************/
21
22#ifndef SHARED_ARRAY
23#define SHARED_ARRAY
24
25#include "config-all.h"
26#include "AtomicCount.h"
27
28namespace FIX
29{
31#ifndef NO_UNALIGNED_ACCESS
32 template<typename T>
33 class shared_array
34 {
35 enum
36 {
37 data_offset = ( sizeof(atomic_count) / sizeof(T) + 1 )
38 };
39
40 public:
42 : m_size(0)
43 , m_buffer(0)
44 {}
45
46 shared_array(const shared_array& rhs)
47 : m_size(rhs.m_size)
48 , m_buffer(rhs.m_buffer)
49 {
50 rhs.attach();
51 }
52
54 { release(); }
55
57 {
58 if( &rhs == this )
59 return *this;
60
61 rhs.attach();
62 release();
63
64 m_size = rhs.m_size;
65 m_buffer = rhs.m_buffer;
66
67 return *this;
68 }
69
70 std::size_t size() const
71 { return m_size; }
72
73 bool empty() const
74 { return m_buffer == 0; }
75
76 operator T* () const
77 { return &m_buffer[data_offset]; }
78
79 //optimized function to allocate storage for buffer and counter object at once
80 static shared_array create(const std::size_t nSize)
81 {
82 if(nSize == 0)
83 return shared_array();
84
85 //verify the needed buffer size to allocate counter object and nSize elements
86 const std::size_t sizeToAllocate = data_offset + nSize;
87
88 //allocate and zero-fill the buffer
89 T* storage = new T[ sizeToAllocate ];
90 memset(storage, 0, sizeToAllocate * sizeof(T));
91
92 // create the counter object at the end of the storage
93 // with initial reference count set to 1
94 new (storage) atomic_count( 1 );
95
96 return shared_array(storage, nSize);
97 }
98
99 private:
100
101 shared_array( T * buff, std::size_t nSize )
102 : m_size(nSize)
103 , m_buffer(buff)
104 {
105
106 }
107
108 atomic_count* get_counter() const
109 {
110 return reinterpret_cast<atomic_count*>( m_buffer );
111 }
112
113 void increment_reference_count() const
114 {
115 atomic_count* counter = get_counter();
116 ++(*counter);
117 }
118
119 long decrement_reference_count() const
120 {
121 atomic_count* counter = get_counter();
122 return --(*counter);
123 }
124
125 void attach() const
126 {
127 if( !empty() )
129 }
130
131 void release()
132 {
133 if( empty() )
134 return;
135
136 //free object if reference count has decreased to zero
137 if( decrement_reference_count() == 0)
138 {
139 T * tmpBuff = m_buffer;
140 atomic_count* tmpCounter = get_counter();
141
142 m_buffer = 0;
143 m_size = 0;
144
145 //explicitly call destructor for the counter object
146 tmpCounter->~atomic_count();
147
148 delete [] tmpBuff;
149 }
150 }
151
152 std::size_t m_size;
153 T * m_buffer;
154 };
155#else
156 template<typename T>
158 {
159 public:
161 : m_size(0)
162 , m_buffer(0)
163 , m_pCtr(0)
164 {}
165
167 : m_size(rhs.m_size)
168 , m_buffer(rhs.m_buffer)
169 {
170 rhs.attach();
171 }
172
174 { release(); }
175
177 {
178 if( &rhs == this )
179 return *this;
180
181 rhs.attach();
182 release();
183
184 m_size = rhs.m_size;
185 m_buffer = rhs.m_buffer;
186 m_pCtr = rhs.m_pCtr;
187
188 return *this;
189 }
190
191 std::size_t size() const
192 { return m_size; }
193
194 bool empty() const
195 { return m_buffer == 0; }
196
197 operator T* () const
198 { return m_buffer; }
199
200 //optimized function to allocate storage for buffer and counter object at once
201 static shared_array create(const std::size_t nSize)
202 {
203 if(nSize <= 0)
204 return shared_array();
205
206 //verify the needed buffer size to allocate counter object and nSize elements
207 const std::size_t sizeToAllocate = (nSize * sizeof(T)) + sizeof(atomic_count) + 15;
208
209 //allocate and zero-fill the buffer
210 void * buf = std::malloc(sizeToAllocate);
211 memset(buf, 0, sizeToAllocate);
212
213 // create the counter object at the end of the storage
214 // with initial reference count set to 1
215 /* round up to multiple of alignment : add (alignment - 1) and then round down by masking */
216 void *ptr = (void *) (((uintptr_t)(buf) + nSize * sizeof(T) + 15) & ~ (uintptr_t)0x0F);
217 new (ptr) atomic_count( 1 );
218
219 T* storage = reinterpret_cast<T*>(buf);
220 return shared_array(storage, nSize, ptr);
221 }
222
223 private:
224
225 shared_array( T * buff, std::size_t nSize, void * pCtr )
226 : m_size(nSize)
227 , m_buffer(buff)
228 , m_pCtr(pCtr)
229 {
230
231 }
232
234 {
235 return reinterpret_cast<atomic_count*>( m_pCtr );
236 }
237
239 {
240 atomic_count* counter = get_counter();
241 ++(*counter);
242 }
243
245 {
246 atomic_count* counter = get_counter();
247 return --(*counter);
248 }
249
250 void attach() const
251 {
252 if( !empty() )
254 }
255
256 void release()
257 {
258 if( empty() )
259 return;
260
261 //free object if reference count has decreased to zero
262 if( decrement_reference_count() == 0)
263 {
264 T * tmpBuff = m_buffer;
265 atomic_count* tmpCounter = get_counter();
266
267 m_buffer = 0;
268 m_size = 0;
269
270 //explicitly call destructor for the counter object
271 tmpCounter->~atomic_count();
272
273 std::free(tmpBuff);
274 }
275 }
276
277 std::size_t m_size;
279 void * m_pCtr;
280 };
281#endif
282}
283
284#endif
Atomic count class - consider using interlocked functions.
Shared array with atomic reference count.
void increment_reference_count() const
shared_array(T *buff, std::size_t nSize, void *pCtr)
std::size_t size() const
std::size_t m_size
shared_array(const shared_array &rhs)
bool empty() const
static shared_array create(const std::size_t nSize)
shared_array & operator=(const shared_array &rhs)
void attach() const
long decrement_reference_count() const
atomic_count * get_counter() const
_W64 unsigned int uintptr_t

Generated on Sun Mar 31 2024 07:07:24 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001