Leviathan  0.8.0.0
Leviathan game engine
ReferenceCounted.h
Go to the documentation of this file.
1 // Leviathan Game Engine
2 // Copyright (c) 2012-2018 Henri Hyyryläinen
3 #pragma once
4 #include "Define.h"
5 // ------------------------------------ //
6 #include <atomic>
7 #include <cstdint>
8 
9 #ifdef LEVIATHAN_USING_BOOST
10 #include <boost/intrusive_ptr.hpp>
11 #endif // LEVIATHAN_USING_BOOST
12 
13 
14 namespace Leviathan {
15 
16 #ifdef LEVIATHAN_USING_BOOST
17 #define REFERENCE_COUNTED_PTR_TYPE(x) \
18  using pointer = boost::intrusive_ptr<x>; \
19  using const_pointer = boost::intrusive_ptr<const x>; \
20  static constexpr auto ANGELSCRIPT_TYPE = \
21  #x "@"; // Appended @ because these are handle types
22 #define REFERENCE_COUNTED_PTR_TYPE_NAMED(x, y) \
23  using pointer = boost::intrusive_ptr<x>; \
24  using const_pointer = boost::intrusive_ptr<const x>; \
25  static constexpr auto ANGELSCRIPT_TYPE = \
26  #y "@"; // Appended @ because these are handle types
27 #else
28 #define REFERENCE_COUNTED_PTR_TYPE(x)
29 #define REFERENCE_COUNTED_PTR_TYPE_NAMED(x, y)
30 #endif // LEVIATHAN_USING_BOOST
31 
32 
37 public:
38 #ifdef LEVIATHAN_USING_BOOST
39  // This needs to added with the REFERENCE_COUNTED_PTR_TYPE to any child class
40  // using pointer = boost::intrusive_ptr<use REFERENCE_COUNTED_PTR_TYPE>;
41  // static constexpr auto ANGELSCRIPT_TYPE = "...";
42  using basepointer = boost::intrusive_ptr<ReferenceCounted>;
43  using refcountedpointer = boost::intrusive_ptr<ReferenceCounted>;
44 #endif // LEVIATHAN_USING_BOOST
45 
46  // Prevent directly using this class
47 protected:
48  DLLEXPORT inline ReferenceCounted() : RefCount(1) {}
50 
51 public:
52  // Cannot be easily copied because of the reference count
53  ReferenceCounted(const ReferenceCounted& other) = delete;
54  ReferenceCounted& operator=(const ReferenceCounted& other) = delete;
55 
56  FORCE_INLINE void AddRef() const
57  {
59  }
60 
62  FORCE_INLINE void Release() const
63  {
65  }
66 
68  {
70  }
71 
73  {
75  }
76 
77 #ifdef LEVIATHAN_USING_BOOST
78  template<class ActualType>
82  static inline boost::intrusive_ptr<ActualType> WrapPtr(ActualType* ptr)
83  {
84  if(!ptr)
85  return nullptr;
86 
87  boost::intrusive_ptr<ActualType> newptr(ptr);
88  ptr->Release();
89 
90  return newptr;
91  }
92 
93  // Copy this comment to any protected constructors that are meant to be
94  // accessed through this:
95  // These are protected for only constructing properly reference
96  // counted instances through MakeShared
97  // friend ReferenceCounted;
98  // Uncomment the above line after pasting
99 
102  template<class ActualType, class... Args>
103  static boost::intrusive_ptr<ActualType> MakeShared(Args&&... args)
104  {
105  boost::intrusive_ptr<ActualType> ptr(new ActualType(std::forward<Args>(args)...));
106  ptr->Release();
107 
108  return ptr;
109  }
110 
111 #endif // LEVIATHAN_USING_BOOST
112 
115  int32_t GetRefCount() const
116  {
117  return RefCount.load(std::memory_order_acquire);
118  }
119 
120 
121 protected:
122  friend void intrusive_ptr_add_ref(const ReferenceCounted* obj)
123  {
124  obj->RefCount.fetch_add(1, std::memory_order_relaxed);
125  }
126 
127  friend void intrusive_ptr_release(const ReferenceCounted* obj)
128  {
129  if(obj->RefCount.fetch_sub(1, std::memory_order_release) == 1) {
130  std::atomic_thread_fence(std::memory_order_acquire);
131  delete obj;
132  }
133  }
134 
135 private:
136  mutable std::atomic_int_fast32_t RefCount;
137 };
138 } // namespace Leviathan
boost::intrusive_ptr< ReferenceCounted > basepointer
FORCE_INLINE void Release() const
removes a reference and deletes the object if reference count reaches zero
ReferenceCounted & operator=(const ReferenceCounted &other)=delete
#define FORCE_INLINE
Definition: Include.h:95
boost::intrusive_ptr< ReferenceCounted > refcountedpointer
int32_t GetRefCount() const
Returns the reference count.
FORCE_INLINE void AddRef()
FORCE_INLINE void Release()
virtual DLLEXPORT ~ReferenceCounted()
friend void intrusive_ptr_release(const ReferenceCounted *obj)
FORCE_INLINE void AddRef() const
static boost::intrusive_ptr< ActualType > MakeShared(Args &&... args)
Constructs a new instance and wraps it.
#define DLLEXPORT
Definition: Include.h:84
friend void intrusive_ptr_add_ref(const ReferenceCounted *obj)
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
static boost::intrusive_ptr< ActualType > WrapPtr(ActualType *ptr)
Creates an intrusive_ptr from raw pointer.