1 /*
2  *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef WEBRTC_BASE_REFCOUNT_H_
12 #define WEBRTC_BASE_REFCOUNT_H_
13 
14 #include <string.h>
15 
16 #include "webrtc/base/atomicops.h"
17 
18 namespace rtc {
19 
20 // Reference count interface.
21 class RefCountInterface {
22  public:
23   virtual int AddRef() const = 0;
24   virtual int Release() const = 0;
25  protected:
~RefCountInterface()26   virtual ~RefCountInterface() {}
27 };
28 
29 template <class T>
30 class RefCountedObject : public T {
31  public:
RefCountedObject()32   RefCountedObject() : ref_count_(0) {
33   }
34 
35   template<typename P>
RefCountedObject(P p)36   explicit RefCountedObject(P p) : T(p), ref_count_(0) {
37   }
38 
39   template<typename P1, typename P2>
RefCountedObject(P1 p1,P2 p2)40   RefCountedObject(P1 p1, P2 p2) : T(p1, p2), ref_count_(0) {
41   }
42 
43   template<typename P1, typename P2, typename P3>
RefCountedObject(P1 p1,P2 p2,P3 p3)44   RefCountedObject(P1 p1, P2 p2, P3 p3) : T(p1, p2, p3), ref_count_(0) {
45   }
46 
47   template<typename P1, typename P2, typename P3, typename P4>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4)48   RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4)
49       : T(p1, p2, p3, p4), ref_count_(0) {
50   }
51 
52   template<typename P1, typename P2, typename P3, typename P4, typename P5>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)53   RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
54       : T(p1, p2, p3, p4, p5), ref_count_(0) {
55   }
56 
57   template<typename P1, typename P2, typename P3, typename P4, typename P5,
58            typename P6>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)59   RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
60       : T(p1, p2, p3, p4, p5, p6), ref_count_(0) {
61   }
62 
63   template<typename P1, typename P2, typename P3, typename P4, typename P5,
64            typename P6, typename P7>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7)65   RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
66       : T(p1, p2, p3, p4, p5, p6, p7), ref_count_(0) {
67   }
68 
69   template<typename P1, typename P2, typename P3, typename P4, typename P5,
70            typename P6, typename P7, typename P8>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8)71   RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
72       : T(p1, p2, p3, p4, p5, p6, p7, p8), ref_count_(0) {
73   }
74 
75   template<typename P1, typename P2, typename P3, typename P4, typename P5,
76            typename P6, typename P7, typename P8, typename P9>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8,P9 p9)77   RefCountedObject(
78       P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9)
79   : T(p1, p2, p3, p4, p5, p6, p7, p8, p9), ref_count_(0) {
80   }
81 
82   template<typename P1, typename P2, typename P3, typename P4, typename P5,
83            typename P6, typename P7, typename P8, typename P9, typename P10>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8,P9 p9,P10 p10)84   RefCountedObject(
85       P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10)
86   : T(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), ref_count_(0) {
87   }
88 
89   template<typename P1, typename P2, typename P3, typename P4, typename P5,
90            typename P6, typename P7, typename P8, typename P9, typename P10,
91            typename P11>
RefCountedObject(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7,P8 p8,P9 p9,P10 p10,P11 p11)92   RefCountedObject(
93       P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10,
94       P11 p11)
95   : T(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), ref_count_(0) {
96   }
97 
AddRef()98   virtual int AddRef() const {
99     return AtomicOps::Increment(&ref_count_);
100   }
101 
Release()102   virtual int Release() const {
103     int count = AtomicOps::Decrement(&ref_count_);
104     if (!count) {
105       delete this;
106     }
107     return count;
108   }
109 
110   // Return whether the reference count is one. If the reference count is used
111   // in the conventional way, a reference count of 1 implies that the current
112   // thread owns the reference and no other thread shares it. This call
113   // performs the test for a reference count of one, and performs the memory
114   // barrier needed for the owning thread to act on the object, knowing that it
115   // has exclusive access to the object.
HasOneRef()116   virtual bool HasOneRef() const {
117     return AtomicOps::AcquireLoad(&ref_count_) == 1;
118   }
119 
120  protected:
~RefCountedObject()121   virtual ~RefCountedObject() {
122   }
123 
124   mutable volatile int ref_count_;
125 };
126 
127 }  // namespace rtc
128 
129 #endif  // WEBRTC_BASE_REFCOUNT_H_
130