1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 // -*- c++ -*- 19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 20 21 // O S C L _ R E F C O U N T E R 22 23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 24 25 /*! \addtogroup osclbase OSCL Base 26 * 27 * @{ 28 */ 29 30 31 32 /** 33 * @file oscl_refcounter.h 34 * @brief A general purpose reference counter to object lifetimes. 35 * 36 */ 37 38 #ifndef OSCL_REFCOUNTER_H_INCLUDED 39 #define OSCL_REFCOUNTER_H_INCLUDED 40 41 #ifndef OSCL_ASSERT_H_INCLUDED 42 #include "oscl_assert.h" 43 #endif 44 45 #ifndef OSCL_DEFALLOC_H_INCLUDED 46 #include "oscl_defalloc.h" 47 #endif 48 49 /** 50 * Interface class for OsclRefCounter implementations 51 */ 52 class OsclRefCounter 53 { 54 public: 55 /** 56 * Add to the reference count 57 */ 58 virtual void addRef() = 0; 59 60 /** 61 * Delete from reference count 62 */ 63 virtual void removeRef() = 0; 64 65 /** 66 * Gets the current number of references 67 */ 68 virtual uint32 getCount() = 0; 69 ~OsclRefCounter()70 virtual ~OsclRefCounter() {} 71 }; 72 73 74 /** 75 * Implementation of an OsclRefCounter that uses a dynamically 76 * created deallocator. 77 */ 78 class OsclRefCounterDA : public OsclRefCounter 79 { 80 public: 81 82 /** 83 * Constructor 84 * Takes a pointer to the buffer to track, and a pointer 85 * to the deallocator object which will be used to delete 86 * the buffer. 87 * 88 * When the reference count reaches zero, the buffer will 89 * be deleted by the deallocator. Also, the OsclRefCounter 90 * object (this) will self-destruct when the reference count 91 * is zero. In some cases the OsclRefCounter object will 92 * be part of the buffer being deleted. For such cases, 93 * the object pointer must be equal to the buffer pointer 94 * given at construction. If the object is not part of the 95 * buffer being deleted, it will self-destruct with a call 96 * to delete(). 97 * 98 * @param p pointer to the buffer to track 99 * @param dealloc pointer to the deallocator to use when 100 * deleting the buffer 101 */ OsclRefCounterDA(OsclAny * p,OsclDestructDealloc * dealloc)102 OsclRefCounterDA(OsclAny *p, OsclDestructDealloc *dealloc): 103 ptr(p), deallocator(dealloc), refcnt(1) 104 { 105 OSCL_ASSERT(ptr != NULL && deallocator != NULL); 106 } 107 108 /** 109 * Destructor 110 * empty 111 */ ~OsclRefCounterDA()112 virtual ~OsclRefCounterDA() {} 113 114 /** 115 * Add to the reference count 116 */ addRef()117 void addRef() 118 { 119 ++refcnt; 120 } 121 122 /** 123 * Remove from the reference count 124 */ removeRef()125 void removeRef() 126 { 127 if (--refcnt == 0) 128 { 129 if (ptr == this) 130 { 131 // buffer is part of the refcounter 132 deallocator->destruct_and_dealloc(this); 133 } 134 else 135 { 136 // delete the buffer and the refcounter object 137 deallocator->destruct_and_dealloc(ptr); 138 delete(this); 139 } 140 } 141 } 142 143 /** 144 * Gets the current number of references 145 */ getCount()146 uint32 getCount() 147 { 148 return refcnt; 149 } 150 151 private: 152 OsclRefCounterDA(); 153 OsclRefCounterDA(const OsclRefCounterDA& x); 154 OsclRefCounterDA& operator=(const OsclRefCounterDA& x); 155 156 OsclAny *ptr; 157 OsclDestructDealloc *deallocator; 158 uint32 refcnt; 159 }; 160 161 162 /** 163 * Implementation of an OsclRefCounter that uses a statically 164 * created deallocator. 165 */ 166 template<class DeallocType> 167 class OsclRefCounterSA : public OsclRefCounter 168 { 169 public: 170 /** 171 * Constructor 172 * Takes a pointer to the buffer to track. 173 * 174 * When the reference count reaches zero, the buffer will 175 * be deleted by the deallocator. Also, the OsclRefCounter 176 * object (this) will self-destruct when the reference count 177 * is zero. In some cases the OsclRefCounter object will 178 * be part of the buffer being deleted. For such cases, 179 * the object pointer must be equal to the buffer pointer 180 * given at construction. If the object is not part of the 181 * buffer being deleted, it will self-destruct with a call 182 * to delete(). 183 * 184 * @param p pointer to the buffer to track 185 */ OsclRefCounterSA(OsclAny * p)186 OsclRefCounterSA(OsclAny *p) : 187 ptr(p), refcnt(1) 188 { 189 OSCL_ASSERT(ptr != NULL); 190 } 191 192 /** 193 * Destructor 194 * empty 195 */ ~OsclRefCounterSA()196 virtual ~OsclRefCounterSA() {} 197 198 /** 199 * Add to the reference count 200 */ addRef()201 void addRef() 202 { 203 ++refcnt; 204 } 205 206 /** 207 * Remove from the reference count 208 */ removeRef()209 void removeRef() 210 { 211 if (--refcnt == 0) 212 { 213 if (ptr == this) 214 { 215 216 // buffer is part of the refcounter 217 DeallocType deallocator; 218 deallocator.destruct_and_dealloc(this); 219 } 220 else 221 { 222 223 // delete the buffer and the recounter object 224 DeallocType deallocator; 225 deallocator.destruct_and_dealloc(ptr); 226 delete(this); 227 } 228 } 229 } 230 231 /** 232 * Gets the current number of references 233 */ getCount()234 uint32 getCount() 235 { 236 return refcnt; 237 } 238 239 private: 240 OsclRefCounterSA(); 241 OsclRefCounterSA(const OsclRefCounterSA<DeallocType>& x); 242 OsclRefCounterSA<DeallocType>& operator=(const OsclRefCounterSA<DeallocType>& x); 243 244 OsclAny *ptr; 245 uint32 refcnt; 246 }; 247 248 /** 249 * Implementation of OsclRefCounterDA for multi-threaded use. 250 * A templated lock class must be specified. 251 */ 252 template<class LockType> 253 class OsclRefCounterMTDA : public OsclRefCounter 254 { 255 public: 256 257 /** 258 * Constructor 259 * Takes a pointer to the buffer to track, and a pointer 260 * to the deallocator object which will be used to delete 261 * the buffer. 262 * 263 * When the reference count reaches zero, the buffer will 264 * be deleted by the deallocator. Also, the OsclRefCounter 265 * object (this) will self-destruct when the reference count 266 * is zero. In some cases the OsclRefCounter object will 267 * be part of the buffer being deleted. For such cases, 268 * the object pointer must be equal to the buffer pointer 269 * given at construction. If the object is not part of the 270 * buffer being deleted, it will self-destruct with a call 271 * to delete(). 272 * 273 * @param p pointer to the buffer to track 274 * @param dealloc pointer to the deallocator to use when 275 * deleting the buffer 276 */ OsclRefCounterMTDA(OsclAny * p,OsclDestructDealloc * dealloc)277 OsclRefCounterMTDA(OsclAny *p, OsclDestructDealloc *dealloc) : 278 ptr(p), deallocator(dealloc), refcnt(1) 279 { 280 OSCL_ASSERT(ptr != NULL && deallocator != NULL); 281 } 282 283 /** 284 * Destructor 285 * empty 286 */ ~OsclRefCounterMTDA()287 virtual ~OsclRefCounterMTDA() {} 288 289 /** 290 * Add to the reference count 291 */ addRef()292 void addRef() 293 { 294 lock.Lock(); 295 ++refcnt; 296 lock.Unlock(); 297 } 298 299 /** 300 * Remove from the reference count 301 */ removeRef()302 void removeRef() 303 { 304 lock.Lock(); 305 if (--refcnt == 0) 306 { 307 if (ptr == this) 308 { 309 310 // buffer is part of the refcounter 311 deallocator->destruct_and_dealloc(this); 312 } 313 else 314 { 315 // delete the buffer and the refcounter object 316 deallocator->destruct_and_dealloc(ptr); 317 delete(this); 318 } 319 } 320 else 321 { 322 lock.Unlock(); 323 } 324 } 325 326 /** 327 * Gets the current number of references 328 */ getCount()329 uint32 getCount() 330 { 331 return refcnt; 332 } 333 334 private: 335 OsclRefCounterMTDA(); 336 OsclRefCounterMTDA(const OsclRefCounterMTDA<LockType>& x); 337 OsclRefCounterMTDA<LockType>& operator=(const OsclRefCounterMTDA<LockType>& x); 338 339 OsclAny *ptr; 340 OsclDestructDealloc *deallocator; 341 LockType lock; 342 uint32 refcnt; 343 }; 344 345 346 /** 347 * Implementation of OsclRefCounterSA for multi-threaded use. 348 * A templated lock class must be specified. 349 */ 350 template<class DeallocType, class LockType> 351 class OsclRefCounterMTSA : public OsclRefCounter 352 { 353 public: 354 /** 355 * Constructor 356 * Takes a pointer to the buffer to track. 357 * 358 * When the reference count reaches zero, the buffer will 359 * be deleted by the deallocator. Also, the OsclRefCounter 360 * object (this) will self-destruct when the reference count 361 * is zero. In some cases the OsclRefCounter object will 362 * be part of the buffer being deleted. For such cases, 363 * the object pointer must be equal to the buffer pointer 364 * given at construction. If the object is not part of the 365 * buffer being deleted, it will self-destruct with a call 366 * to delete(). 367 * 368 * @param p pointer to the buffer to track 369 */ OsclRefCounterMTSA(OsclAny * p)370 OsclRefCounterMTSA(OsclAny *p) : 371 ptr(p), refcnt(1) 372 { 373 OSCL_ASSERT(ptr != NULL); 374 } 375 376 /** 377 * Destructor 378 * empty 379 */ ~OsclRefCounterMTSA()380 virtual ~OsclRefCounterMTSA() {} 381 382 /** 383 * Add to the reference count 384 */ addRef()385 void addRef() 386 { 387 lock.Lock(); 388 ++refcnt; 389 lock.Unlock(); 390 } 391 392 /** 393 * Remove from the reference count 394 */ removeRef()395 void removeRef() 396 { 397 lock.Lock(); 398 if (--refcnt == 0) 399 { 400 if (ptr == this) 401 { 402 // buffer is part of the refcounter 403 DeallocType deallocator; 404 deallocator.destruct_and_dealloc(this); 405 } 406 else 407 { 408 409 // delete the buffer and the recounter object 410 DeallocType deallocator; 411 deallocator.destruct_and_dealloc(ptr); 412 delete(this); 413 } 414 } 415 else 416 { 417 lock.Unlock(); 418 } 419 } 420 421 /** 422 * Gets the current number of references 423 */ getCount()424 uint32 getCount() 425 { 426 return refcnt; 427 } 428 429 private: 430 OsclRefCounterMTSA(); 431 OsclRefCounterMTSA(const OsclRefCounterMTSA<DeallocType, LockType>& x); 432 OsclRefCounterMTSA<DeallocType, LockType>& operator=(const OsclRefCounterMTSA<DeallocType, LockType>& x); 433 434 OsclAny *ptr; 435 LockType lock; 436 uint32 refcnt; 437 }; 438 439 /** 440 Implementation of an Oscl_DefAlloc class with a 441 built-in ref counter. 442 */ 443 template<class DefAlloc> 444 class Oscl_DefAllocWithRefCounter: public OsclRefCounter, public DefAlloc 445 { 446 public: 447 /** Create object 448 */ New()449 static Oscl_DefAllocWithRefCounter* New() 450 { 451 DefAlloc alloc; 452 OsclAny* p = alloc.ALLOCATE(sizeof(Oscl_DefAllocWithRefCounter)); 453 return new(p) Oscl_DefAllocWithRefCounter(); 454 } 455 456 /** Delete object 457 */ Delete()458 void Delete() 459 { 460 removeRef(); 461 } 462 addRef()463 void addRef() 464 { 465 refcount++; 466 } 467 removeRef()468 void removeRef() 469 { 470 --refcount; 471 if (refcount == 0) 472 DefAlloc::deallocate(this); 473 } 474 getCount()475 uint32 getCount() 476 { 477 return refcount; 478 } 479 480 private: Oscl_DefAllocWithRefCounter()481 Oscl_DefAllocWithRefCounter(): refcount(1) 482 {} 483 uint32 refcount; 484 }; 485 486 /*! @} */ 487 488 489 #endif 490