SharedArray.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* -*- C++ -*- */
  2. /****************************************************************************
  3. ** Copyright (c) 2001-2014
  4. **
  5. ** This file is part of the QuickFIX FIX Engine
  6. **
  7. ** This file may be distributed under the terms of the quickfixengine.org
  8. ** license as defined by quickfixengine.org and appearing in the file
  9. ** LICENSE included in the packaging of this file.
  10. **
  11. ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  12. ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  13. **
  14. ** See http://www.quickfixengine.org/LICENSE for licensing information.
  15. **
  16. ** Contact ask@quickfixengine.org if any conditions of this licensing are
  17. ** not clear to you.
  18. **
  19. ****************************************************************************/
  20. #ifndef SHARED_ARRAY
  21. #define SHARED_ARRAY
  22. #include "AtomicCount.h"
  23. namespace FIX
  24. {
  25. /// Shared array with atomic reference count
  26. template<typename T>
  27. class shared_array
  28. {
  29. public:
  30. shared_array()
  31. : m_size(0)
  32. , m_buffer(0)
  33. {}
  34. shared_array(const shared_array& rhs)
  35. : m_size(rhs.m_size)
  36. , m_buffer(rhs.m_buffer)
  37. {
  38. rhs.attach();
  39. }
  40. ~shared_array()
  41. { release(); }
  42. shared_array& operator=(const shared_array& rhs)
  43. {
  44. if( &rhs == this )
  45. return *this;
  46. rhs.attach();
  47. release();
  48. m_size = rhs.m_size;
  49. m_buffer = rhs.m_buffer;
  50. return *this;
  51. }
  52. std::size_t size() const
  53. { return m_size; }
  54. bool empty() const
  55. { return m_buffer == 0; }
  56. operator T* () const
  57. { return m_buffer; }
  58. //optimized function to allocate storage for buffer and counter object at once
  59. static shared_array create(const std::size_t nSize)
  60. {
  61. if(nSize <= 0)
  62. return shared_array();
  63. //verify the needed buffer size to allocate counter object and nSize elements
  64. const std::size_t sizeToAllocate = nSize + ( sizeof(atomic_count) / sizeof(T) + 1 );
  65. //allocate and zero-fill the buffer
  66. T* storage = new T[ sizeToAllocate ];
  67. memset(storage, 0, sizeToAllocate * sizeof(T));
  68. // create the counter object at the end of the storage
  69. // with initial reference count set to 1
  70. new (&storage[nSize]) atomic_count( 1 );
  71. return shared_array(storage, nSize);
  72. }
  73. private:
  74. shared_array( T * buff, std::size_t nSize )
  75. : m_size(nSize)
  76. , m_buffer(buff)
  77. {
  78. }
  79. atomic_count* get_counter() const
  80. {
  81. return reinterpret_cast<atomic_count*>( &m_buffer[ size() ] );
  82. }
  83. void increment_reference_count() const
  84. {
  85. atomic_count* counter = get_counter();
  86. ++(*counter);
  87. }
  88. long decrement_reference_count()
  89. {
  90. atomic_count* counter = get_counter();
  91. return --(*counter);
  92. }
  93. void attach() const
  94. {
  95. if( !empty() )
  96. increment_reference_count();
  97. }
  98. void release()
  99. {
  100. if( empty() )
  101. return;
  102. //free object if reference count has decreased to zero
  103. if( decrement_reference_count() == 0)
  104. {
  105. T * tmpBuff = m_buffer;
  106. atomic_count* tmpCounter = get_counter();
  107. m_buffer = 0;
  108. m_size = 0;
  109. //explicitly call destructor for the counter object
  110. tmpCounter->~atomic_count();
  111. delete [] tmpBuff;
  112. }
  113. }
  114. std::size_t m_size;
  115. T * m_buffer;
  116. };
  117. }
  118. #endif