| cannam@147 | 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | 
| cannam@147 | 2 // Licensed under the MIT License: | 
| cannam@147 | 3 // | 
| cannam@147 | 4 // Permission is hereby granted, free of charge, to any person obtaining a copy | 
| cannam@147 | 5 // of this software and associated documentation files (the "Software"), to deal | 
| cannam@147 | 6 // in the Software without restriction, including without limitation the rights | 
| cannam@147 | 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
| cannam@147 | 8 // copies of the Software, and to permit persons to whom the Software is | 
| cannam@147 | 9 // furnished to do so, subject to the following conditions: | 
| cannam@147 | 10 // | 
| cannam@147 | 11 // The above copyright notice and this permission notice shall be included in | 
| cannam@147 | 12 // all copies or substantial portions of the Software. | 
| cannam@147 | 13 // | 
| cannam@147 | 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
| cannam@147 | 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
| cannam@147 | 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
| cannam@147 | 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
| cannam@147 | 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
| cannam@147 | 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
| cannam@147 | 20 // THE SOFTWARE. | 
| cannam@147 | 21 | 
| cannam@147 | 22 #include "memory.h" | 
| cannam@147 | 23 | 
| cannam@147 | 24 #ifndef KJ_REFCOUNT_H_ | 
| cannam@147 | 25 #define KJ_REFCOUNT_H_ | 
| cannam@147 | 26 | 
| cannam@147 | 27 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | 
| cannam@147 | 28 #pragma GCC system_header | 
| cannam@147 | 29 #endif | 
| cannam@147 | 30 | 
| cannam@147 | 31 namespace kj { | 
| cannam@147 | 32 | 
| cannam@147 | 33 class Refcounted: private Disposer { | 
| cannam@147 | 34   // Subclass this to create a class that contains a reference count. Then, use | 
| cannam@147 | 35   // `kj::refcounted<T>()` to allocate a new refcounted pointer. | 
| cannam@147 | 36   // | 
| cannam@147 | 37   // Do NOT use this lightly.  Refcounting is a crutch.  Good designs should strive to make object | 
| cannam@147 | 38   // ownership clear, so that refcounting is not necessary.  All that said, reference counting can | 
| cannam@147 | 39   // sometimes simplify code that would otherwise become convoluted with explicit ownership, even | 
| cannam@147 | 40   // when ownership relationships are clear at an abstract level. | 
| cannam@147 | 41   // | 
| cannam@147 | 42   // NOT THREADSAFE:  This refcounting implementation assumes that an object's references are | 
| cannam@147 | 43   // manipulated only in one thread, because atomic (thread-safe) refcounting is surprisingly slow. | 
| cannam@147 | 44   // | 
| cannam@147 | 45   // In general, abstract classes should _not_ subclass this.  The concrete class at the bottom | 
| cannam@147 | 46   // of the hierarchy should be the one to decide how it implements refcounting.  Interfaces should | 
| cannam@147 | 47   // expose only an `addRef()` method that returns `Own<InterfaceType>`.  There are two reasons for | 
| cannam@147 | 48   // this rule: | 
| cannam@147 | 49   // 1. Interfaces would need to virtually inherit Refcounted, otherwise two refcounted interfaces | 
| cannam@147 | 50   //    could not be inherited by the same subclass.  Virtual inheritance is awkward and | 
| cannam@147 | 51   //    inefficient. | 
| cannam@147 | 52   // 2. An implementation may decide that it would rather return a copy than a refcount, or use | 
| cannam@147 | 53   //    some other strategy. | 
| cannam@147 | 54   // | 
| cannam@147 | 55   // TODO(cleanup):  Rethink above.  Virtual inheritance is not necessarily that bad.  OTOH, a | 
| cannam@147 | 56   //   virtual function call for every refcount is sad in its own way.  A Ref<T> type to replace | 
| cannam@147 | 57   //   Own<T> could also be nice. | 
| cannam@147 | 58 | 
| cannam@147 | 59 public: | 
| cannam@147 | 60   virtual ~Refcounted() noexcept(false); | 
| cannam@147 | 61 | 
| cannam@147 | 62   inline bool isShared() const { return refcount > 1; } | 
| cannam@147 | 63   // Check if there are multiple references to this object. This is sometimes useful for deciding | 
| cannam@147 | 64   // whether it's safe to modify the object vs. make a copy. | 
| cannam@147 | 65 | 
| cannam@147 | 66 private: | 
| cannam@147 | 67   mutable uint refcount = 0; | 
| cannam@147 | 68   // "mutable" because disposeImpl() is const.  Bleh. | 
| cannam@147 | 69 | 
| cannam@147 | 70   void disposeImpl(void* pointer) const override; | 
| cannam@147 | 71   template <typename T> | 
| cannam@147 | 72   static Own<T> addRefInternal(T* object); | 
| cannam@147 | 73 | 
| cannam@147 | 74   template <typename T> | 
| cannam@147 | 75   friend Own<T> addRef(T& object); | 
| cannam@147 | 76   template <typename T, typename... Params> | 
| cannam@147 | 77   friend Own<T> refcounted(Params&&... params); | 
| cannam@147 | 78 }; | 
| cannam@147 | 79 | 
| cannam@147 | 80 template <typename T, typename... Params> | 
| cannam@147 | 81 inline Own<T> refcounted(Params&&... params) { | 
| cannam@147 | 82   // Allocate a new refcounted instance of T, passing `params` to its constructor.  Returns an | 
| cannam@147 | 83   // initial reference to the object.  More references can be created with `kj::addRef()`. | 
| cannam@147 | 84 | 
| cannam@147 | 85   return Refcounted::addRefInternal(new T(kj::fwd<Params>(params)...)); | 
| cannam@147 | 86 } | 
| cannam@147 | 87 | 
| cannam@147 | 88 template <typename T> | 
| cannam@147 | 89 Own<T> addRef(T& object) { | 
| cannam@147 | 90   // Return a new reference to `object`, which must subclass Refcounted and have been allocated | 
| cannam@147 | 91   // using `kj::refcounted<>()`.  It is suggested that subclasses implement a non-static addRef() | 
| cannam@147 | 92   // method which wraps this and returns the appropriate type. | 
| cannam@147 | 93 | 
| cannam@147 | 94   KJ_IREQUIRE(object.Refcounted::refcount > 0, "Object not allocated with kj::refcounted()."); | 
| cannam@147 | 95   return Refcounted::addRefInternal(&object); | 
| cannam@147 | 96 } | 
| cannam@147 | 97 | 
| cannam@147 | 98 template <typename T> | 
| cannam@147 | 99 Own<T> Refcounted::addRefInternal(T* object) { | 
| cannam@147 | 100   Refcounted* refcounted = object; | 
| cannam@147 | 101   ++refcounted->refcount; | 
| cannam@147 | 102   return Own<T>(object, *refcounted); | 
| cannam@147 | 103 } | 
| cannam@147 | 104 | 
| cannam@147 | 105 }  // namespace kj | 
| cannam@147 | 106 | 
| cannam@147 | 107 #endif  // KJ_REFCOUNT_H_ |