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 
28 namespace 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:
41  shared_array()
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>
157  class shared_array
158  {
159  public:
160  shared_array()
161  : m_size(0)
162  , m_buffer(0)
163  , m_pCtr(0)
164  {}
165 
166  shared_array(const shared_array& rhs)
167  : m_size(rhs.m_size)
168  , m_buffer(rhs.m_buffer)
169  {
170  rhs.attach();
171  }
172 
173  ~shared_array()
174  { release(); }
175 
176  shared_array& operator=(const shared_array& rhs)
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 
233  atomic_count* get_counter() const
234  {
235  return reinterpret_cast<atomic_count*>( m_pCtr );
236  }
237 
238  void increment_reference_count() const
239  {
240  atomic_count* counter = get_counter();
241  ++(*counter);
242  }
243 
244  long decrement_reference_count() const
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;
278  T * m_buffer;
279  void * m_pCtr;
280  };
281 #endif
282 }
283 
284 #endif
FIX::shared_array::~shared_array
~shared_array()
Definition: SharedArray.h:207
FIX::shared_array::operator=
shared_array & operator=(const shared_array &rhs)
Definition: SharedArray.h:210
FIX::shared_array
Shared array with atomic reference count.
Definition: SharedArray.h:174
FIX::shared_array::create
static shared_array create(const std::size_t nSize)
Definition: SharedArray.h:235
FIX::atomic_count
Atomic count class - consider using interlocked functions.
Definition: AtomicCount.h:143
FIX::shared_array::get_counter
atomic_count * get_counter() const
Definition: SharedArray.h:267
FIX::shared_array::increment_reference_count
void increment_reference_count() const
Definition: SharedArray.h:272
FIX::shared_array::decrement_reference_count
long decrement_reference_count() const
Definition: SharedArray.h:278
FIX::shared_array::m_size
std::size_t m_size
Definition: SharedArray.h:311
FIX::shared_array::m_buffer
T * m_buffer
Definition: SharedArray.h:312
AtomicCount.h
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint_msvc.h:120
FIX::shared_array::m_pCtr
void * m_pCtr
Definition: SharedArray.h:313
FIX::shared_array::shared_array
shared_array()
Definition: SharedArray.h:194
FIX
Definition: Acceptor.cpp:34
FIX::shared_array::attach
void attach() const
Definition: SharedArray.h:284
FIX::shared_array::release
void release()
Definition: SharedArray.h:290
config-all.h
FIX::shared_array::empty
bool empty() const
Definition: SharedArray.h:228
FIX::shared_array::size
std::size_t size() const
Definition: SharedArray.h:225

Generated on Wed Apr 29 2020 19:41:30 for QuickFIX by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2001