1 #pragma once
2
3 #if defined(_WIN32)
4
5 #define WIN32_LEAN_AND_MEAN
6 #include <windows.h>
7 //#include <assert.h>
8 #else
9 #include <atomic>
10 #endif
11
13
15
16 #if defined(_WINDOWS) || defined(WINDOWS)
17
19 inline long _inc(counter_t& v) {
return InterlockedIncrement((LPLONG)&v); }
20 inline long _inc(counter_t& v,
long by) {
return InterlockedExchangeAdd((LPLONG)&v,by); }
21 inline long _dec(counter_t& v) {
return InterlockedDecrement((LPLONG)&v); }
22 inline long _set(counter_t& v,
long nv) {
return InterlockedExchange((LPLONG)&v, nv); }
23 inline long _set_when_eq(counter_t& v,
long to_set,
long eq_to) {
return InterlockedCompareExchange ((LPLONG)&v,to_set,eq_to); }
24
25 #elif defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8) )
26
28 inline long _inc(counter_t& v) {
return __sync_add_and_fetch(&v,1); }
29 inline long _inc(counter_t& v,
long by) {
return __sync_add_and_fetch(&v,by); }
30 inline long _dec(counter_t& v) {
return __sync_add_and_fetch(&v,-1); }
31 inline long _set(counter_t& v,
long nv) {
return __sync_lock_test_and_set(&v,nv); }
32 inline long _set_when_eq(counter_t& v,
long to_set,
long eq_to) {
return __sync_val_compare_and_swap(&v,eq_to,to_set);
33 /*long t(v); if(t == eq_to) v = to_set; return t;*/ }
34 #else
35
37 inline long _inc(counter_t& v) {
return ++v; }
38 inline long _inc(counter_t& v,
long by) {
return v += by; }
39 inline long _dec(counter_t& v) {
return --v; }
40 inline long _set(counter_t& v,
long nv) {
return v.exchange(nv); }
41 inline long _set_when_eq(counter_t& v,
long to_set,
long eq_to) {
long t(v); v.compare_exchange_strong(eq_to,to_set);
return t; }
42
43 #endif
44
46 {
51 operator long()
const {
return cv; }
54 };
55 } // atomic
56
57
58 // COM::IUnknown alike thing:
60 public:
61 // mandatory:
62 virtual long add_ref() = 0;
63 virtual long release() = 0;
64 // optional:
65 virtual bool get_interface(
const char* name,
iasset** out) = 0;
66 };
67
68
69 // intrusive add_ref/release counter
71 {
73 public:
76
78 {
79 assert ( _ref_cntr == 0 );
80 }
81
83 {
84 assert(_ref_cntr > 0);
85 long t = --_ref_cntr;
86 if(t == 0)
87 finalize();
88 return t;
89 }
90 virtual long add_ref() {
return ++_ref_cntr; }
91
92 // "name" here is an arbitrary name that includes domain name in reversed order:
93 // "element.dom.sciter.com"
94 // "video-renderer.dom.sciter.com"
96
98 {
99 delete this;
100 }
101 };
102
103 //asset - yet another shared_ptr
104 // R here is something derived from the asset above
105 template <class R>
107 {
108 protected:
110
111 public:
113
117
119 operator R*()
const {
return p; }
121
123 operator bool()
const {
return p != 0; }
126
127 // release the interface and set it to NULL
128 void release() {
if (p) { R* pt = p; p = 0; pt->release(); }}
129
130 // attach to an existing interface (does not AddRef)
131 void attach(R* p2) { release(); p = p2; }
132 // detach the interface (does not Release)
133 R*
detach() { R* pt = p; p = 0;
return pt; }
134
136 {
138 if (pp) pp->release();
139 pp = lp;
140 return lp;
141 }
142
143 R*
operator=(R* lp) {
if(p != lp)
return assign(p, lp);
return p; }
145
147
148 };
149
150 }
151
152 #if defined(_WINDOWS)
153
154 namespace com {
155
156 //asset - yet another smart pointer
157 template <class T>
158 class ptr
159 {
160 protected:
161 T* p;
162
163 public:
165
166 ptr():p(0) {}
167 ptr(T* lp):p(0) { if (lp) (p = lp)->AddRef(); }
168 ptr(const ptr<T>& cp):p(0) { if (cp.p) (p = cp.p)->AddRef(); }
169
170 ~ptr()
171 {
172 ULONG c = 0;
173 if (p)
174 c = p->Release();
175 }
176 operator T*() const { return p; }
177 T* operator->() const { assert(p != 0); return p; }
178
179 // used as target T** pointer to pointer - in places receiving newly created objects (initially add-refed)
180 T** target() { release(); return &p; }
181
182 bool operator!() const { return p == 0; }
183 operator bool() const { return p != 0; }
184 bool operator!=(T* pT) const { return p != pT; }
185 bool operator==(T* pT) const { return p == pT; }
186
187 // release the interface and set it to NULL
188 void release() { if (p) { T* pt = p; p = 0; pt->Release(); }}
189
190 // attach to an existing interface (does not AddRef)
191 void attach(T* p2) { release(); p = p2; }
192 // detach the interface (does not Release)
193 T* detach() { T* pt = p; p = 0; return pt; }
194
195 static T* assign(T* &pp, T* lp)
196 {
197 if (lp != 0) lp->AddRef();
198 if (pp) pp->Release();
199 pp = lp;
200 return lp;
201 }
202
203 T*
operator=(T* lp) {
if(p != lp)
return assign(p, lp);
return p; }
204 T*
operator=(
const ptr<T>& lp) {
if(p != lp)
return assign(p, lp.p);
return p; }
205
206 T* acquire() { if( p ) p->AddRef(); return p; }
207
208 HRESULT CoCreateInstance (REFCLSID classUUID, DWORD dwClsContext = CLSCTX_INPROC_SERVER)
209 {
210 HRESULT hr = ::CoCreateInstance (classUUID, 0, dwClsContext, __uuidof (T), (void**) target());
211 assert (hr != CO_E_NOTINITIALIZED); // You haven't called CoInitialize for the current thread!
212 return hr;
213 }
214
215 template <class OTHER_COM_CLASS>
216 HRESULT QueryInterface (REFCLSID classUUID, ptr<OTHER_COM_CLASS>& dest_object) const
217 {
218 if (p == 0)
219 return E_POINTER;
220 return p->QueryInterface (classUUID, (void**) dest_object.target());
221 }
222
223 template <class OTHER_COM_CLASS>
224 HRESULT QueryInterface (ptr<OTHER_COM_CLASS>& dest_object) const
225 {
226 return this->QueryInterface (__uuidof (OTHER_COM_CLASS), dest_object);
227 }
228
229 };
230
231 }
232
233 #endif
long _set(counter_t &v, long nv)
R * operator=(const asset_ptr< R > &lp)
static R * assign(R *&pp, R *lp)
counter & operator=(long nv)
std::atomic< long > counter_t
asset_ptr(const asset_ptr< R > &cp)
bool operator==(R *pR) const
virtual bool get_interface(const char *name, iasset **out)
bool operator!=(R *pR) const
long _set_when_eq(counter_t &v, long to_set, long eq_to)