123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- /* -*- C++ -*- */
- /****************************************************************************
- ** Copyright (c) 2001-2014
- **
- ** This file is part of the QuickFIX FIX Engine
- **
- ** This file may be distributed under the terms of the quickfixengine.org
- ** license as defined by quickfixengine.org and appearing in the file
- ** LICENSE included in the packaging of this file.
- **
- ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- **
- ** See http://www.quickfixengine.org/LICENSE for licensing information.
- **
- ** Contact ask@quickfixengine.org if any conditions of this licensing are
- ** not clear to you.
- **
- ****************************************************************************/
- #ifndef SHARED_ARRAY
- #define SHARED_ARRAY
- #include "AtomicCount.h"
- namespace FIX
- {
- /// Shared array with atomic reference count
- template<typename T>
- class shared_array
- {
- public:
- shared_array()
- : m_size(0)
- , m_buffer(0)
- {}
- shared_array(const shared_array& rhs)
- : m_size(rhs.m_size)
- , m_buffer(rhs.m_buffer)
- {
- rhs.attach();
- }
- ~shared_array()
- { release(); }
- shared_array& operator=(const shared_array& rhs)
- {
- if( &rhs == this )
- return *this;
- rhs.attach();
- release();
- m_size = rhs.m_size;
- m_buffer = rhs.m_buffer;
- return *this;
- }
- std::size_t size() const
- { return m_size; }
- bool empty() const
- { return m_buffer == 0; }
- operator T* () const
- { return m_buffer; }
- //optimized function to allocate storage for buffer and counter object at once
- static shared_array create(const std::size_t nSize)
- {
- if(nSize <= 0)
- return shared_array();
- //verify the needed buffer size to allocate counter object and nSize elements
- const std::size_t sizeToAllocate = nSize + ( sizeof(atomic_count) / sizeof(T) + 1 );
- //allocate and zero-fill the buffer
- T* storage = new T[ sizeToAllocate ];
- memset(storage, 0, sizeToAllocate * sizeof(T));
- // create the counter object at the end of the storage
- // with initial reference count set to 1
- new (&storage[nSize]) atomic_count( 1 );
- return shared_array(storage, nSize);
- }
- private:
- shared_array( T * buff, std::size_t nSize )
- : m_size(nSize)
- , m_buffer(buff)
- {
- }
- atomic_count* get_counter() const
- {
- return reinterpret_cast<atomic_count*>( &m_buffer[ size() ] );
- }
- void increment_reference_count() const
- {
- atomic_count* counter = get_counter();
- ++(*counter);
- }
- long decrement_reference_count()
- {
- atomic_count* counter = get_counter();
- return --(*counter);
- }
- void attach() const
- {
- if( !empty() )
- increment_reference_count();
- }
- void release()
- {
- if( empty() )
- return;
- //free object if reference count has decreased to zero
- if( decrement_reference_count() == 0)
- {
- T * tmpBuff = m_buffer;
- atomic_count* tmpCounter = get_counter();
- m_buffer = 0;
- m_size = 0;
- //explicitly call destructor for the counter object
- tmpCounter->~atomic_count();
- delete [] tmpBuff;
- }
- }
- std::size_t m_size;
- T * m_buffer;
- };
- }
- #endif
|