123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- // TmplBlockBuffer.cpp
- //
- #pragma once
- #ifndef ASSERT
- #include <assert.h>
- #define ASSERT assert
- #endif
- #include "TmplBlockBuffer.tlh"
- #define DataNull nullptr
- template <typename T>
- TmplBlockBuffer <T>::TmplBlockBuffer ()
- {
- Init ();
- }
- template <typename T>
- TmplBlockBuffer <T>::~TmplBlockBuffer ()
- {
- if (GetData () == DataNull)
- return;
- if (InterlockedDecrement (&GetData ()->nRefs) <= 0)
- {
- delete m_pMetaData;
- delete m_pObject;
- }
- }
- template <typename T>
- void TmplBlockBuffer <T>::Init (void)
- {
- m_pObject = nullptr;
- m_pMetaData = (MetaData *) DataNull;
- }
- template <typename T>
- TmplBlockBuffer <T>::TmplBlockBuffer (const TmplBlockBuffer <T> & h)
- {
- Init ();
- ShadowCopyFrom (h);
- }
- template <typename T>
- TmplBlockBuffer <T>::TmplBlockBuffer (TmplBlockBuffer <T> && h)
- {
- Init ();
- MoveAssign (h);
- }
- // 从 h 构造一个新的对象, 但是我只要前面的 count 个字符
- // 如果 count 比 h.nCount 大, 那就重新分配然后 memcpy
- template <typename T>
- TmplBlockBuffer <T>::TmplBlockBuffer (TmplBlockBuffer && h, int count)
- {
- Init ();
- // 如果啥都不想要
- if (count <= 0) return;
- // 如果源是 null
- if (h.GetData () == DataNull)
- {
- GetBufferSetCount (count);
- return;
- }
- // 如果要的很少
- if (count <= h.GetData ()->nCount)
- {
- MoveAssign (h);
- ASSERT (m_pMetaData->nCount >= count);
- m_pMetaData->nCount = count;
- return;
- }
- // 如果要的太多了
- {
- auto pDst = GetBufferSetCount (count);
- auto pSrc = h.As ();
- memcpy (pDst, pSrc, h.GetCount ());
- h.Init ();
- return;
- }
- }
- template <typename T>
- TmplBlockBuffer <T>::TmplBlockBuffer (T * object, int count)
- {
- Init ();
- Attach (object, count);
- }
- template <typename T>
- void TmplBlockBuffer <T>::Attach (T * object, int count)
- {
- Release ();
- if (count <= 0) return;
- if (object == nullptr) return;
- m_pObject = object;
- m_pMetaData = new MetaData;
- m_pMetaData->nRefs = 1;
- m_pMetaData->nCount = count;
- }
- // 注意, 有可能无法 Detach 的, 因为对象可能被其他地方引用了
- // 如果 Detach 失败, 数据不受影响
- template <typename T>
- T * TmplBlockBuffer <T>::Detach ()
- {
- if (GetData () == DataNull) return nullptr;
- ASSERT (GetData ()->nRefs != 0);
- if (GetData ()->nRefs > 1) return nullptr;
- long nRef = InterlockedDecrement (&GetData ()->nRefs);
- ASSERT (nRef <= 0);
- if (nRef > 0)
- // 前面已经判断过, 因此不会出现减一后还大于 0 的情况. 以下代码只是以防万一
- {
- Init (); // 前面既然已经减了 1, 我只好变成 Init 了
- return NULL;
- }
- T * object = m_pObject;
- m_pObject = nullptr;
- delete m_pMetaData;
- m_pMetaData = nullptr;
- Init ();
- return object;
- }
- template <typename T>
- void TmplBlockBuffer <T>::Release ()
- {
- T * object = Detach ();
- delete object;
- Init ();
- }
- template <typename T>
- void TmplBlockBuffer <T>::CopyFrom (const TmplBlockBuffer <T> & h)
- {
- Release ();
- if (! h.m_pObject) return;
- int count = h.GetData ()->nCount;
- if (count <= 0) return;
- T * object = new T [count];
- ASSERT (object);
- memcpy (object, h.m_pObject, sizeof (T) * count);
- Attach (object, count);
- }
- template <typename T>
- void TmplBlockBuffer <T>::ShadowCopyFrom (const TmplBlockBuffer <T> & h)
- {
- if (m_pObject == h.m_pObject)
- return;
- if (h.GetData () == DataNull)
- {
- Release ();
- return;
- }
- if (GetData () != DataNull)
- if (GetData ()->nRefs < 0)
- {
- CopyFrom (h);
- return;
- }
- if (h.GetData ()->nRefs < 0)
- {
- CopyFrom (h);
- return;
- }
- // else
- {
- // can just copy references around
- Release ();
- m_pObject = h.m_pObject;
- m_pMetaData = h.m_pMetaData;
- InterlockedIncrement (&GetData ()->nRefs);
- }
- }
- // 移动赋值
- template <typename T>
- TmplBlockBuffer <T> & TmplBlockBuffer <T>::operator = (TmplBlockBuffer <T> && Src)
- {
- MoveAssign (Src);
- return *this;
- }
- // 移动赋值
- template <typename T>
- void TmplBlockBuffer <T>::MoveAssign (TmplBlockBuffer <T> & Src)
- {
- Release ();
- m_pObject = Src.m_pObject;
- m_pMetaData = Src.m_pMetaData;
- Src.Init ();
- }
- template <typename T>
- T * TmplBlockBuffer <T>::GetBufferSetCount (int count)
- {
- Release ();
- if (count <= 0) return nullptr;
- T * object = new T [count];
- ASSERT (object);
- Attach (object, count);
- return object;
- }
- template <typename T>
- void TmplBlockBuffer <T>::CopyFrom (const T * from, int count)
- {
- Release ();
- if (count <= 0) return;
- if (! from) return;
- T * object = new T [count];
- ASSERT (object);
- memcpy (object, from, sizeof (T) * count);
- Attach (object, count);
- }
- template <typename T>
- void TmplBlockBuffer <T>::CopyTo (T * to, int count) const
- {
- if (count <= 0) return;
- if (! to) return;
- if (! m_pObject) return;
- memcpy (to, m_pObject, sizeof (T) * min (count, GetData ()->nCount));
- }
- template <typename T>
- TmplBlockBuffer <T> & TmplBlockBuffer <T>::operator = (const TmplBlockBuffer <T> & h)
- {
- ShadowCopyFrom (h);
- return *this;
- }
- template <typename T>
- TmplBlockBuffer <T>::operator bool () const
- {
- return m_pObject;
- }
- template <typename T>
- TmplBlockBuffer <T>::operator T * ()
- {
- return m_pObject;
- }
- template <typename T>
- TmplBlockBuffer <T>::operator const T * () const
- {
- return m_pObject;
- }
- template <typename T>
- bool TmplBlockBuffer <T>::IsEmpty () const
- {
- return (m_pObject == nullptr);
- }
|