blob: 46c727789fa8057dc4404ceb21a97ee5bef316e2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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 */
|