1 /*
2  *  RefCount.h
3  *  Apto
4  *
5  *  Created by David on 11/12/08.
6  *  Copyright 2008-2011 David Michael Bryson. All rights reserved.
7  *  http://programerror.com/software/apto
8  *
9  *  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
10  *  following conditions are met:
11  *
12  *  1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the
13  *      following disclaimer.
14  *  2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
15  *      following disclaimer in the documentation and/or other materials provided with the distribution.
16  *  3.  Neither the name of David Michael Bryson, nor the names of contributors may be used to endorse or promote
17  *      products derived from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY DAVID MICHAEL BRYSON AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  *  DISCLAIMED. IN NO EVENT SHALL DAVID MICHAEL BRYSON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  *  Authors: David M. Bryson <david@programerror.com>
28  *
29  */
30 
31 #ifndef AptoCoreRefCount_h
32 #define AptoCoreRefCount_h
33 
34 #include "apto/core/Atomic.h"
35 
36 
37 namespace Apto {
38 
39   // RefCountObject - Internal reference counted object
40   // --------------------------------------------------------------------------------------------------------------
41 
42   class RefCountObject
43   {
44   private:
45     int m_ref_count;
46 
47   public:
RefCountObject()48     RefCountObject() : m_ref_count(1) { ; }
RefCountObject(const RefCountObject &)49     RefCountObject(const RefCountObject&) : m_ref_count(1) { ; }
50     virtual ~RefCountObject() = 0;
51 
52     RefCountObject& operator=(const RefCountObject&) { return *this; }
53 
AddReference()54     void AddReference() { m_ref_count++; }
RemoveReference()55     void RemoveReference() { if (!--m_ref_count) delete this; }
56 
IsExclusive()57     bool IsExclusive() { return (m_ref_count == 1); }
58   };
59 
60 
61   // MTRefCountObject - Thread safe internal reference counted object
62   // --------------------------------------------------------------------------------------------------------------
63 
64   class MTRefCountObject
65   {
66   private:
67     volatile int m_ref_count;
68 
69   public:
MTRefCountObject()70     MTRefCountObject() { Atomic::Set(&m_ref_count, 1); }
MTRefCountObject(const MTRefCountObject &)71     MTRefCountObject(const MTRefCountObject&) { Atomic::Set(&m_ref_count, 1); }
72     virtual ~MTRefCountObject() = 0;
73 
74     MTRefCountObject& operator=(const MTRefCountObject&) { return *this; }
75 
AddReference()76     void AddReference() { Atomic::Inc(&m_ref_count); }
RemoveReference()77     void RemoveReference() { if (Atomic::DecAndTest(&m_ref_count)) delete this; }
78   };
79 
80   struct ThreadSafe {
81     enum { UseThreadSafe = true };
82   };
83 
84   struct SingleThreaded {
85     enum { UseThreadSafe = false };
86   };
87 };
88 
89 #endif
90