• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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