SharedArray.h
Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 /****************************************************************************
00004 ** Copyright (c) 2001-2014
00005 **
00006 ** This file is part of the QuickFIX FIX Engine
00007 **
00008 ** This file may be distributed under the terms of the quickfixengine.org
00009 ** license as defined by quickfixengine.org and appearing in the file
00010 ** LICENSE included in the packaging of this file.
00011 **
00012 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014 **
00015 ** See http://www.quickfixengine.org/LICENSE for licensing information.
00016 **
00017 ** Contact ask@quickfixengine.org if any conditions of this licensing are
00018 ** not clear to you.
00019 **
00020 ****************************************************************************/
00021 
00022 #ifndef SHARED_ARRAY
00023 #define SHARED_ARRAY
00024 
00025 #include "AtomicCount.h"
00026 
00027 namespace FIX
00028 {
00030   template<typename T>
00031   class shared_array
00032   {
00033   public:
00034     shared_array()
00035     : m_size(0)
00036     , m_buffer(0)
00037     {}
00038 
00039     shared_array(const shared_array& rhs)
00040     : m_size(rhs.m_size)
00041     , m_buffer(rhs.m_buffer)
00042     {
00043       rhs.attach();
00044     }
00045 
00046     ~shared_array()
00047     { release(); }
00048 
00049     shared_array& operator=(const shared_array& rhs)
00050     {
00051       if( &rhs == this )
00052         return *this;
00053 
00054       rhs.attach();
00055       release();
00056 
00057       m_size = rhs.m_size;
00058       m_buffer = rhs.m_buffer;
00059 
00060       return *this;
00061     }
00062 
00063     std::size_t size() const
00064     { return m_size; }
00065 
00066     bool empty() const
00067     { return m_buffer == 0; }
00068 
00069     operator T* () const
00070     { return m_buffer; }
00071 
00072     //optimized function to allocate storage for buffer and counter object at once
00073     static shared_array create(const std::size_t nSize)
00074     {
00075       if(nSize <= 0)
00076         return shared_array();
00077 
00078       //verify the needed buffer size to allocate counter object and nSize elements
00079       const std::size_t sizeToAllocate = nSize + ( sizeof(atomic_count) / sizeof(T) + 1 );
00080 
00081       //allocate and zero-fill the buffer
00082       T* storage = new T[ sizeToAllocate ];
00083       memset(storage, 0, sizeToAllocate * sizeof(T));
00084 
00085       // create the counter object at the end of the storage
00086       // with initial reference count set to 1
00087       new (&storage[nSize]) atomic_count( 1 );
00088 
00089       return shared_array(storage, nSize);
00090     }
00091 
00092   private:
00093 
00094     shared_array( T * buff, std::size_t nSize )
00095     : m_size(nSize)
00096     , m_buffer(buff)
00097     {
00098 
00099     }
00100 
00101     atomic_count* get_counter() const
00102     {
00103       return reinterpret_cast<atomic_count*>( &m_buffer[ size() ] );
00104     }
00105 
00106     void increment_reference_count() const
00107     {
00108       atomic_count* counter = get_counter();
00109       ++(*counter);
00110     }
00111 
00112     long decrement_reference_count() 
00113     {
00114       atomic_count* counter = get_counter();
00115       return --(*counter);
00116     }
00117 
00118     void attach() const
00119     {
00120       if( !empty() )
00121         increment_reference_count();
00122     }
00123 
00124     void release()
00125     {
00126       if( empty() )
00127         return;
00128 
00129       //free object if reference count has decreased to zero
00130       if( decrement_reference_count() == 0)
00131       {
00132         T * tmpBuff = m_buffer;
00133         atomic_count* tmpCounter = get_counter();
00134 
00135         m_buffer = 0;
00136         m_size = 0;
00137 
00138         //explicitly call destructor for the counter object
00139         tmpCounter->~atomic_count();
00140 
00141         delete [] tmpBuff;
00142       }
00143     }
00144 
00145     std::size_t m_size;
00146     T * m_buffer;
00147   };
00148 }
00149 
00150 #endif

Generated on Mon Jun 23 2014 23:49:38 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001