Leviathan  0.8.0.0
Leviathan game engine
Leviathan::BaseNotifiable< ParentType, ChildType > Class Template Reference

#include <BaseNotifiable.h>

+ Inheritance diagram for Leviathan::BaseNotifiable< ParentType, ChildType >:

Public Member Functions

 BaseNotifiable (ChildType *ourptr)
 
virtual ~BaseNotifiable ()
 
void ReleaseParentHooks (Lock &guard)
 Release function which releases all hooks. More...
 
bool UnConnectFromNotifier (Lock &guard, BaseNotifier< ParentType, ChildType > *specificnotifier, Lock &notifierlock)
 The actual implementation of UnConnectFromNotifier. More...
 
bool UnConnectFromNotifier (Lock &guard, BaseNotifier< ParentType, ChildType > *specificnotifier)
 
virtual void NotifyAll (Lock &guard)
 Notifies all the parents of this object about something. More...
 
FORCE_INLINE bool UnConnectFromNotifier (BaseNotifier< ParentType, ChildType > *specificnotifier)
 Disconnects this from a previously connected notifier. More...
 
bool IsConnectedTo (BaseNotifier< ParentType, ChildType > *check, Lock &guard)
 Actual implementation of this method. More...
 
FORCE_INLINE bool IsConnectedTo (BaseNotifier< ParentType, ChildType > *check)
 Returns true when the specified object is already connected. More...
 
bool UnConnectFromNotifier (int id)
 This searches the connected notifiers and calls the above function with it's pointer. More...
 
bool ConnectToNotifier (BaseNotifier< ParentType, ChildType > *owner)
 Connects this to a notifier object calling all the needed functions. More...
 
bool ConnectToNotifier (Lock &unlockable, BaseNotifier< ParentType, ChildType > *owner)
 Variant for already locked objects. More...
 
void _OnUnhookNotifier (Lock &locked, BaseNotifier< ParentType, ChildType > *parent, Lock &parentlock)
 Callback called by the parent, used to not to call the unhook again on the parent. More...
 
void _OnHookNotifier (Lock &locked, BaseNotifier< ParentType, ChildType > *parent, Lock &parentlock)
 Called by parent to hook, and doesn't call the parent's functions. More...
 
ChildType * GetActualPointerToNotifiableObject ()
 Gets the internal pointer to the actual object. More...
 
virtual void OnNotified (Lock &ownlock, ParentType *parent, Lock &parentlock)
 Called when our parent notifies us about something. More...
 
- Public Member Functions inherited from Leviathan::ThreadSafeGeneric< MutexType >
DLLEXPORT ThreadSafeGeneric ()
 
DLLEXPORT ~ThreadSafeGeneric ()
 
FORCE_INLINE void VerifyLock (RecursiveLock &guard) const
 
FORCE_INLINE void VerifyLock (Lock &lockit) const
 

Protected Member Functions

virtual void _OnNotifierConnected (Lock &guard, ParentType *parentadded, Lock &parentlock)
 
virtual void _OnNotifierDisconnected (Lock &guard, ParentType *parentremoved, Lock &parentlock)
 

Protected Attributes

ChildType * PointerToOurNotifiable
 Stores a pointer to the object that is inherited from this. More...
 
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
 Vector of other objects that this is connected to. More...
 
- Protected Attributes inherited from Leviathan::ThreadSafeGeneric< MutexType >
MutexType ObjectsLock
 

Additional Inherited Members

- Public Types inherited from Leviathan::ThreadSafeGeneric< MutexType >
using LockT = typename LockTypeResolver< MutexType >::LType
 

Detailed Description

template<class ParentType, class ChildType>
class Leviathan::BaseNotifiable< ParentType, ChildType >

This class is used to allow objects to connect to other objects safely

This works by using unhook events that are called on both if either one is destroyed

Definition at line 14 of file BaseNotifiable.h.

Constructor & Destructor Documentation

◆ BaseNotifiable()

template<class ParentType , class ChildType>
Leviathan::BaseNotifiable< ParentType, ChildType >::BaseNotifiable ( ChildType *  ourptr)

Definition at line 11 of file BaseNotifiableImpl.h.

11  : PointerToOurNotifiable(ourptr){
12 
13 }
ChildType * PointerToOurNotifiable
Stores a pointer to the object that is inherited from this.

◆ ~BaseNotifiable()

template<class ParentType , class ChildType >
Leviathan::BaseNotifiable< ParentType, ChildType >::~BaseNotifiable ( )
virtual

Definition at line 16 of file BaseNotifiableImpl.h.

16  {
17  GUARD_LOCK();
18 
19  // Last chance to unhook //
20  if(ConnectedToParents.size())
21  ReleaseParentHooks(guard);
22 }
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
void ReleaseParentHooks(Lock &guard)
Release function which releases all hooks.
#define GUARD_LOCK()
Definition: ThreadSafe.h:111

Member Function Documentation

◆ _OnHookNotifier()

template<class ParentType, class ChildType>
void Leviathan::BaseNotifiable< ParentType, ChildType >::_OnHookNotifier ( Lock locked,
BaseNotifier< ParentType, ChildType > *  parent,
Lock parentlock 
)

Called by parent to hook, and doesn't call the parent's functions.

Definition at line 182 of file BaseNotifiableImpl.h.

184 {
185 
186  // Add the object to the list of objects //
187  ConnectedToParents.push_back(parent);
188  _OnNotifierConnected(locked, parent->GetActualPointerToNotifierObject(), parentlock);
189 }
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
virtual void _OnNotifierConnected(Lock &guard, ParentType *parentadded, Lock &parentlock)

◆ _OnNotifierConnected()

template<class ParentType, class ChildType >
void Leviathan::BaseNotifiable< ParentType, ChildType >::_OnNotifierConnected ( Lock guard,
ParentType *  parentadded,
Lock parentlock 
)
protectedvirtual

Definition at line 219 of file BaseNotifiableImpl.h.

221 {
222 
223 }

◆ _OnNotifierDisconnected()

template<class ParentType, class ChildType >
void Leviathan::BaseNotifiable< ParentType, ChildType >::_OnNotifierDisconnected ( Lock guard,
ParentType *  parentremoved,
Lock parentlock 
)
protectedvirtual

Definition at line 212 of file BaseNotifiableImpl.h.

214 {
215 
216 }

◆ _OnUnhookNotifier()

template<class ParentType, class ChildType>
void Leviathan::BaseNotifiable< ParentType, ChildType >::_OnUnhookNotifier ( Lock locked,
BaseNotifier< ParentType, ChildType > *  parent,
Lock parentlock 
)

Callback called by the parent, used to not to call the unhook again on the parent.

Definition at line 192 of file BaseNotifiableImpl.h.

194 {
195 
196  // Remove from list //
197  auto end = ConnectedToParents.end();
198  for(auto iter = ConnectedToParents.begin(); iter != end; ++iter){
199 
200  if(*iter == parent){
201  // Remove it //
202  _OnNotifierDisconnected(locked, (*iter)->GetActualPointerToNotifierObject(),
203  parentlock);
204 
205  ConnectedToParents.erase(iter);
206  return;
207  }
208  }
209 }
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
virtual void _OnNotifierDisconnected(Lock &guard, ParentType *parentremoved, Lock &parentlock)

◆ ConnectToNotifier() [1/2]

template<class ParentType, class ChildType>
bool Leviathan::BaseNotifiable< ParentType, ChildType >::ConnectToNotifier ( BaseNotifier< ParentType, ChildType > *  owner)

Connects this to a notifier object calling all the needed functions.

Definition at line 109 of file BaseNotifiableImpl.h.

111 {
112  // Lock the other first //
113  GUARD_LOCK_OTHER_NAME(owner, guard2);
114  GUARD_LOCK();
115 
116  // Check is it already connected //
117  if(IsConnectedTo(owner, guard)){
118 
119  return false;
120  }
121 
122  // Call hook on the parent //
123  owner->_OnHookNotifiable(guard2, this, guard);
124 
125  // Add to the list //
126  ConnectedToParents.push_back(owner);
127 
128  // Finally call the callback //
129  _OnNotifierConnected(guard, owner->GetActualPointerToNotifierObject(), guard2);
130 
131 
132  return true;
133 }
bool IsConnectedTo(BaseNotifier< ParentType, ChildType > *check, Lock &guard)
Actual implementation of this method.
#define GUARD_LOCK_OTHER_NAME(x, y)
Definition: ThreadSafe.h:127
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
virtual void _OnNotifierConnected(Lock &guard, ParentType *parentadded, Lock &parentlock)
#define GUARD_LOCK()
Definition: ThreadSafe.h:111

◆ ConnectToNotifier() [2/2]

template<class ParentType, class ChildType>
bool Leviathan::BaseNotifiable< ParentType, ChildType >::ConnectToNotifier ( Lock unlockable,
BaseNotifier< ParentType, ChildType > *  owner 
)

Variant for already locked objects.

Parameters
unlockableLock that has this object locked and can be safely unlocked

Definition at line 136 of file BaseNotifiableImpl.h.

138 {
139  unlockable.unlock();
140 
141  // Lock the other first //
142  GUARD_LOCK_OTHER_NAME(owner, guard2);
143 
144  unlockable.lock();
145 
146  // Check is it already connected //
147  if(IsConnectedTo(owner, unlockable)){
148 
149  return false;
150  }
151 
152  // Call hook on the parent //
153  owner->_OnHookNotifiable(guard2, this, unlockable);
154 
155  // Add to the list //
156  ConnectedToParents.push_back(owner);
157 
158  // Finally call the callback //
159  _OnNotifierConnected(unlockable, owner->GetActualPointerToNotifierObject(), guard2);
160 
161  return true;
162 }
bool IsConnectedTo(BaseNotifier< ParentType, ChildType > *check, Lock &guard)
Actual implementation of this method.
#define GUARD_LOCK_OTHER_NAME(x, y)
Definition: ThreadSafe.h:127
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
virtual void _OnNotifierConnected(Lock &guard, ParentType *parentadded, Lock &parentlock)

◆ GetActualPointerToNotifiableObject()

template<class ParentType , class ChildType >
ChildType * Leviathan::BaseNotifiable< ParentType, ChildType >::GetActualPointerToNotifiableObject ( )

Gets the internal pointer to the actual object.

Definition at line 226 of file BaseNotifiableImpl.h.

226  {
227  return PointerToOurNotifiable;
228 }
ChildType * PointerToOurNotifiable
Stores a pointer to the object that is inherited from this.

◆ IsConnectedTo() [1/2]

template<class ParentType, class ChildType>
bool Leviathan::BaseNotifiable< ParentType, ChildType >::IsConnectedTo ( BaseNotifier< ParentType, ChildType > *  check,
Lock guard 
)

Actual implementation of this method.

Definition at line 165 of file BaseNotifiableImpl.h.

167 {
168  VerifyLock(guard);
169 
170  auto end = ConnectedToParents.end();
171  for(auto iter = ConnectedToParents.begin(); iter != end; ++iter){
172 
173  if(*iter == check)
174  return true;
175  }
176 
177  // Didn't find a match //
178  return false;
179 }
FORCE_INLINE void VerifyLock(RecursiveLock &guard) const
Definition: ThreadSafe.h:144
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.

◆ IsConnectedTo() [2/2]

template<class ParentType, class ChildType>
FORCE_INLINE bool Leviathan::BaseNotifiable< ParentType, ChildType >::IsConnectedTo ( BaseNotifier< ParentType, ChildType > *  check)
inline

Returns true when the specified object is already connected.

Definition at line 57 of file BaseNotifiable.h.

57  {
58  GUARD_LOCK();
59  return IsConnectedTo(check, guard);
60  }
bool IsConnectedTo(BaseNotifier< ParentType, ChildType > *check, Lock &guard)
Actual implementation of this method.
#define GUARD_LOCK()
Definition: ThreadSafe.h:111

◆ NotifyAll()

template<class ParentType , class ChildType >
void Leviathan::BaseNotifiable< ParentType, ChildType >::NotifyAll ( Lock guard)
virtual

Notifies all the parents of this object about something.

This will call the BaseNotifier::OnNotified on all the child objects

Parameters
guardLock for this object that needs to be able to be safely unlocked

Definition at line 231 of file BaseNotifiableImpl.h.

231  {
232  // More trickery needed here to keep the locking order //
233  auto currentparent = *ConnectedToParents.begin();
234  auto actualptr = GetActualPointerToNotifiableObject();
235 
236  while(currentparent){
237 
238  // Now we need to unlock and the lock the parent //
239  guard.unlock();
240  {
241  GUARD_LOCK_OTHER_NAME(currentparent, guard2);
242 
243  // Now that the parent is locked we can re-lock ourselves //
244  guard.lock();
245 
246  // Notify now //
247  // TODO: add guard2 to this call
248  currentparent->OnNotified(guard2, actualptr, guard);
249 
250  }
251  // The current parent doesn't need to be locked while we change to a different parent //
252 
253  // Seek back to the current position //
254  auto end = ConnectedToParents.end();
255  for(auto iter = ConnectedToParents.begin(); iter != end; ){
256  // Check did we find the parent we are after, otherwise continue //
257  if(*iter == currentparent){
258  // The next parent will be the next target //
259  ++iter;
260 
261  currentparent = iter != ConnectedToParents.end() ? *iter: NULL;
262  break;
263 
264  } else {
265  ++iter;
266  }
267  }
268  }
269 }
ChildType * GetActualPointerToNotifiableObject()
Gets the internal pointer to the actual object.
#define GUARD_LOCK_OTHER_NAME(x, y)
Definition: ThreadSafe.h:127
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.

◆ OnNotified()

template<class ParentType, class ChildType >
void Leviathan::BaseNotifiable< ParentType, ChildType >::OnNotified ( Lock ownlock,
ParentType *  parent,
Lock parentlock 
)
virtual

Called when our parent notifies us about something.

Note
Both the parent and this object has been locked when this is called
Warning
Do not directly call this if you don't know what you are doing!

Reimplemented in Leviathan::ScriptNotifiable.

Definition at line 272 of file BaseNotifiableImpl.h.

274 {
275 
276 }

◆ ReleaseParentHooks()

template<class ParentType , class ChildType >
void Leviathan::BaseNotifiable< ParentType, ChildType >::ReleaseParentHooks ( Lock guard)

Release function which releases all hooks.

Definition at line 25 of file BaseNotifiableImpl.h.

25  {
26  // This needs a bit of trickery since the lock order must be parent, child so we may not lock ourselves
27 
28  while(!ConnectedToParents.empty()){
29 
30  // Get the parent and erase it from the vector, this should avoid problems during this
31  // object is unlocked
32  auto parentptr = *ConnectedToParents.begin();
34 
35  guard.unlock();
36 
37  // Lock the parent //
38  GUARD_LOCK_OTHER_NAME(parentptr, guard2);
39 
40  // Now that the parent is locked we can re-lock ourselves //
41  guard.lock();
42 
43  parentptr->_OnUnhookNotifiable(guard2, this, guard);
44 
45  // Remove it //
46  _OnNotifierDisconnected(guard, parentptr->GetActualPointerToNotifierObject(), guard2);
47  }
48 }
#define GUARD_LOCK_OTHER_NAME(x, y)
Definition: ThreadSafe.h:127
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
virtual void _OnNotifierDisconnected(Lock &guard, ParentType *parentremoved, Lock &parentlock)

◆ UnConnectFromNotifier() [1/4]

template<class ParentType, class ChildType>
bool Leviathan::BaseNotifiable< ParentType, ChildType >::UnConnectFromNotifier ( Lock guard,
BaseNotifier< ParentType, ChildType > *  specificnotifier,
Lock notifierlock 
)

The actual implementation of UnConnectFromNotifier.

Definition at line 84 of file BaseNotifiableImpl.h.

86 {
87  VerifyLock(guard);
88 
89  // Remove from the list and call functions //
90  auto end = ConnectedToParents.end();
91  for(auto iter = ConnectedToParents.begin(); iter != end; ++iter){
92 
93  if(*iter == specificnotifier){
94  // Call unhook on the child //
95  (*iter)->_OnUnhookNotifiable(notifierlock, this, guard);
96 
97  // Remove it //
98  _OnNotifierDisconnected(guard, (*iter)->GetActualPointerToNotifierObject(),
99  notifierlock);
100 
101  ConnectedToParents.erase(iter);
102  return true;
103  }
104  }
105  return false;
106 }
FORCE_INLINE void VerifyLock(RecursiveLock &guard) const
Definition: ThreadSafe.h:144
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
virtual void _OnNotifierDisconnected(Lock &guard, ParentType *parentremoved, Lock &parentlock)

◆ UnConnectFromNotifier() [2/4]

template<class ParentType, class ChildType>
bool Leviathan::BaseNotifiable< ParentType, ChildType >::UnConnectFromNotifier ( Lock guard,
BaseNotifier< ParentType, ChildType > *  specificnotifier 
)
inline

Definition at line 26 of file BaseNotifiable.h.

28  {
29 
30  guard.unlock();
31  GUARD_LOCK_OTHER_NAME(specificnotifier, guard2);
32  guard.lock();
33 
34  return UnConnectFromNotifier(guard, specificnotifier, guard2);
35  }
#define GUARD_LOCK_OTHER_NAME(x, y)
Definition: ThreadSafe.h:127
bool UnConnectFromNotifier(Lock &guard, BaseNotifier< ParentType, ChildType > *specificnotifier, Lock &notifierlock)
The actual implementation of UnConnectFromNotifier.

◆ UnConnectFromNotifier() [3/4]

template<class ParentType, class ChildType>
FORCE_INLINE bool Leviathan::BaseNotifiable< ParentType, ChildType >::UnConnectFromNotifier ( BaseNotifier< ParentType, ChildType > *  specificnotifier)
inline

Disconnects this from a previously connected notifier.

Definition at line 44 of file BaseNotifiable.h.

46  {
47  // The parent has to be locked before this object //
48  GUARD_LOCK_OTHER_NAME(specificnotifier, guard2);
49  GUARD_LOCK();
50  return UnConnectFromNotifier(specificnotifier, guard, guard2);
51  }
#define GUARD_LOCK_OTHER_NAME(x, y)
Definition: ThreadSafe.h:127
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
bool UnConnectFromNotifier(Lock &guard, BaseNotifier< ParentType, ChildType > *specificnotifier, Lock &notifierlock)
The actual implementation of UnConnectFromNotifier.

◆ UnConnectFromNotifier() [4/4]

template<class ParentType, class ChildType>
bool Leviathan::BaseNotifiable< ParentType, ChildType >::UnConnectFromNotifier ( int  id)

This searches the connected notifiers and calls the above function with it's pointer.

Definition at line 51 of file BaseNotifiableImpl.h.

51  {
52 
53  // Used to force the specific locking order //
54  BaseNotifier<ParentType, ChildType>* foundtarget = NULL;
55 
56  {
57  GUARD_LOCK();
58 
59  // Find child matching the provided id //
60  auto end = ConnectedToParents.end();
61  for(auto iter = ConnectedToParents.begin(); iter != end; ++iter){
62 
63  if(iter->GetID() == id){
64  // Found the target //
65  foundtarget = *iter;
66  }
67  }
68  }
69 
70  if(!foundtarget){
71  // Didn't find it //
72  return false;
73  }
74 
75  // Found a target, do the locking in the right order //
76 
77  GUARD_LOCK_OTHER_NAME(foundtarget, guard2);
78  GUARD_LOCK();
79 
80  return UnConnectFromNotifier(guard, foundtarget, guard2);
81 }
#define GUARD_LOCK_OTHER_NAME(x, y)
Definition: ThreadSafe.h:127
std::vector< BaseNotifier< ParentType, ChildType > * > ConnectedToParents
Vector of other objects that this is connected to.
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
bool UnConnectFromNotifier(Lock &guard, BaseNotifier< ParentType, ChildType > *specificnotifier, Lock &notifierlock)
The actual implementation of UnConnectFromNotifier.

Member Data Documentation

◆ ConnectedToParents

template<class ParentType, class ChildType>
std::vector<BaseNotifier<ParentType, ChildType>*> Leviathan::BaseNotifiable< ParentType, ChildType >::ConnectedToParents
protected

Vector of other objects that this is connected to.

Definition at line 102 of file BaseNotifiable.h.

◆ PointerToOurNotifiable

template<class ParentType, class ChildType>
ChildType* Leviathan::BaseNotifiable< ParentType, ChildType >::PointerToOurNotifiable
protected

Stores a pointer to the object that is inherited from this.

Definition at line 99 of file BaseNotifiable.h.


The documentation for this class was generated from the following files: