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  static constexpr auto ANGELSCRIPT_TYPE = \
20  #x "@"; // Appended @ because these are handle types
21 #define REFERENCE_COUNTED_PTR_TYPE_NAMED(x, y) \
22  using pointer = boost::intrusive_ptr<x>; \
23  static constexpr auto ANGELSCRIPT_TYPE = \
24  #y "@"; // Appended @ because these are handle types
25 #else
26 #define REFERENCE_COUNTED_PTR_TYPE(x)
27 #define REFERENCE_COUNTED_PTR_TYPE_NAMED(x, y)
28 #endif // LEVIATHAN_USING_BOOST
29 
30 
35 public:
36 #ifdef LEVIATHAN_USING_BOOST
37  // This needs to added with the REFERENCE_COUNTED_PTR_TYPE to any child class
38  // using pointer = boost::intrusive_ptr<use REFERENCE_COUNTED_PTR_TYPE>;
39  // static constexpr auto ANGELSCRIPT_TYPE = "...";
40  using basepointer = boost::intrusive_ptr<ReferenceCounted>;
41  using refcountedpointer = boost::intrusive_ptr<ReferenceCounted>;
42 #endif // LEVIATHAN_USING_BOOST
43 
44  // Prevent directly using this class
45 protected:
46  DLLEXPORT inline ReferenceCounted() : RefCount(1) {}
48 
49 public:
50  // Cannot be easily copied because of the reference count
51  ReferenceCounted(const ReferenceCounted& other) = delete;
52  ReferenceCounted& operator=(const ReferenceCounted& other) = delete;
53 
55  {
57  }
58 
61  {
63  }
64 
65 #ifdef LEVIATHAN_USING_BOOST
66  template<class ActualType>
70  static inline boost::intrusive_ptr<ActualType> WrapPtr(ActualType* ptr)
71  {
72  if(!ptr)
73  return nullptr;
74 
75  boost::intrusive_ptr<ActualType> newptr(ptr);
76  ptr->Release();
77 
78  return newptr;
79  }
80 
81  // Copy this comment to any protected constructors that are meant to be
82  // accessed through this:
83  // These are protected for only constructing properly reference
84  // counted instances through MakeShared
85  // friend ReferenceCounted;
86  // Uncomment the above line after pasting
87 
90  template<class ActualType, class... Args>
91  static boost::intrusive_ptr<ActualType> MakeShared(Args&&... args)
92  {
93  boost::intrusive_ptr<ActualType> ptr(new ActualType(std::forward<Args>(args)...));
94  ptr->Release();
95 
96  return ptr;
97  }
98 
99 #endif // LEVIATHAN_USING_BOOST
100 
103  int32_t GetRefCount() const
104  {
105  return RefCount.load(std::memory_order_acquire);
106  }
107 
108 
109 protected:
110  friend void intrusive_ptr_add_ref(const ReferenceCounted* obj)
111  {
112  obj->RefCount.fetch_add(1, std::memory_order_relaxed);
113  }
114 
115  friend void intrusive_ptr_release(const ReferenceCounted* obj)
116  {
117  if(obj->RefCount.fetch_sub(1, std::memory_order_release) == 1) {
118  std::atomic_thread_fence(std::memory_order_acquire);
119  delete obj;
120  }
121  }
122 
123 private:
124  mutable std::atomic_int_fast32_t RefCount;
125 };
126 } // namespace Leviathan
boost::intrusive_ptr< ReferenceCounted > basepointer
ReferenceCounted & operator=(const ReferenceCounted &other)=delete
#define FORCE_INLINE
Definition: Include.h:126
boost::intrusive_ptr< ReferenceCounted > refcountedpointer
int32_t GetRefCount() const
Returns the reference count.
FORCE_INLINE void AddRef()
FORCE_INLINE void Release()
removes a reference and deletes the object if reference count reaches zero
virtual DLLEXPORT ~ReferenceCounted()
friend void intrusive_ptr_release(const ReferenceCounted *obj)
static boost::intrusive_ptr< ActualType > MakeShared(Args &&... args)
Constructs a new instance and wraps it.
#define DLLEXPORT
Definition: Include.h:115
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.