mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-29 09:29:10 +00:00
(svn r4987) Feature: Merged YAPF into trunk. Thanks to devs for continuous support and users for testing.
This commit is contained in:
82
yapf/autocopyptr.hpp
Normal file
82
yapf/autocopyptr.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef AUTOCOPYPTR_HPP
|
||||
#define AUTOCOPYPTR_HPP
|
||||
|
||||
/** CAutoCopyPtrT - kind of CoW (Copy on Write) pointer.
|
||||
It is non-invasive smart pointer (reference counter is held outside
|
||||
of Tdata).
|
||||
When copied, its new copy shares the same underlaying structure Tdata.
|
||||
When dereferenced, its behavior depends on 2 factors:
|
||||
- whether the data is shared (used by more than one pointer)
|
||||
- type of access (read/write)
|
||||
When shared pointer is dereferenced for write, new clone of Tdata
|
||||
is made first.
|
||||
Can't be used for polymorphic data types (interfaces).
|
||||
*/
|
||||
template <class Tdata_>
|
||||
class CAutoCopyPtrT {
|
||||
protected:
|
||||
typedef Tdata_ Tdata;
|
||||
|
||||
struct CItem {
|
||||
int m_ref_cnt; ///< reference counter
|
||||
Tdata m_data; ///< custom data itself
|
||||
|
||||
FORCEINLINE CItem() : m_ref_cnt(1) {};
|
||||
FORCEINLINE CItem(const Tdata& data) : m_ref_cnt(1), m_data(data) {};
|
||||
FORCEINLINE CItem(const CItem& src) : m_ref_cnt(1), m_data(src.m_data) {};
|
||||
};
|
||||
|
||||
mutable CItem* m_pI; ///< points to the ref-counted data
|
||||
|
||||
public:
|
||||
FORCEINLINE CAutoCopyPtrT() : m_pI(NULL) {};
|
||||
FORCEINLINE CAutoCopyPtrT(const Tdata& data) : m_pI(new CItem(data)) {};
|
||||
FORCEINLINE CAutoCopyPtrT(const CAutoCopyPtrT& src) : m_pI(src.m_pI) {if (m_pI != NULL) m_pI->m_ref_cnt++;}
|
||||
FORCEINLINE ~CAutoCopyPtrT() {if (m_pI == NULL || (--m_pI->m_ref_cnt) > 0) return; delete m_pI; m_pI = NULL;}
|
||||
|
||||
/** data accessor (read only) */
|
||||
FORCEINLINE const Tdata& GetDataRO() const {if (m_pI == NULL) m_pI = new CItem(); return m_pI->m_data;}
|
||||
/** data accessor (read / write) */
|
||||
FORCEINLINE Tdata& GetDataRW() {CloneIfShared(); if (m_pI == NULL) m_pI = new CItem(); return m_pI->m_data;}
|
||||
|
||||
/** clone data if it is shared */
|
||||
FORCEINLINE void CloneIfShared()
|
||||
{
|
||||
if (m_pI != NULL && m_pI->m_ref_cnt > 1) {
|
||||
// we share data item with somebody, clone it to become an exclusive owner
|
||||
CItem* pNewI = new CItem(*m_pI);
|
||||
m_pI->m_ref_cnt--;
|
||||
m_pI = pNewI;
|
||||
}
|
||||
}
|
||||
|
||||
/** assign pointer from the other one (maintaining ref counts) */
|
||||
FORCEINLINE void Assign(const CAutoCopyPtrT& src)
|
||||
{
|
||||
if (m_pI == src.m_pI) return;
|
||||
if (m_pI != NULL && (--m_pI->m_ref_cnt) <= 0) delete m_pI;
|
||||
m_pI = src.m_pI;
|
||||
if (m_pI != NULL) m_pI->m_ref_cnt++;
|
||||
}
|
||||
|
||||
/** dereference operator (read only) */
|
||||
FORCEINLINE const Tdata* operator -> () const {return &GetDataRO();}
|
||||
/** dereference operator (read / write) */
|
||||
FORCEINLINE Tdata* operator -> () {return &GetDataRW();}
|
||||
|
||||
/** assignment operator */
|
||||
FORCEINLINE CAutoCopyPtrT& operator = (const CAutoCopyPtrT& src) {Assign(src); return *this;}
|
||||
|
||||
/** forwarding 'lower then' operator to the underlaying items */
|
||||
FORCEINLINE bool operator < (const CAutoCopyPtrT& other) const
|
||||
{
|
||||
assert(m_pI != NULL);
|
||||
assert(other.m_pI != NULL);
|
||||
return (m_pI->m_data) < (other.m_pI->m_data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* AUTOCOPYPTR_HPP */
|
Reference in New Issue
Block a user