diff options
Diffstat (limited to 'LibOVR/Src/Kernel/OVR_Observer.h')
-rw-r--r-- | LibOVR/Src/Kernel/OVR_Observer.h | 457 |
1 files changed, 0 insertions, 457 deletions
diff --git a/LibOVR/Src/Kernel/OVR_Observer.h b/LibOVR/Src/Kernel/OVR_Observer.h deleted file mode 100644 index 76b4be6..0000000 --- a/LibOVR/Src/Kernel/OVR_Observer.h +++ /dev/null @@ -1,457 +0,0 @@ -/************************************************************************************ - -PublicHeader: Kernel -Filename : OVR_Observer.h -Content : Observer pattern -Created : June 20, 2014 -Author : Chris Taylor - -Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.2 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -************************************************************************************/ - -#ifndef OVR_Observer_h -#define OVR_Observer_h - -#include "OVR_Types.h" -#include "OVR_Atomic.h" -#include "OVR_RefCount.h" -#include "OVR_Delegates.h" -#include "OVR_Array.h" -#include "OVR_String.h" -#include "OVR_Hash.h" - -namespace OVR { - -template<class DelegateT> class Observer; -template<class DelegateT> class ObserverScope; -template<class DelegateT> class ObserverHash; - - -//----------------------------------------------------------------------------- -// Observer pattern - -// An Observer will observe a Subject. The Subject can emit callbacks that get -// serviced by the Observers. - -// The trickiest part of this is the shutdown code. -// To simplify shutdown, the Observer is a reference-counted object divorced -// from the handler that is called. To avoid misuse, the ObserverScope object -// is provided to ensure that the Shutdown() method is called when it goes out -// of scope. - -// The Observer<> class doubles as the subject class. -// To avoid misuse, assertions are added if a subject tries to observe, or if -// an observer tries to be watched. - -/* - Usage example: - - Say we want to invoke a handler with the signature: - - void MyHandler(int i, bool b); - - The corresponding delegate type is: - - typedef Delegate2<void, int, bool> Handler; - - Note: The return value will be ignored for the Observer pattern. - - For this example there are two classes, one that emits events and another - that listens for events: -*/ - -/* - Event emitter example: - - class MyEmitter - { - ObserverScope<Handler> TheSubject; - - public: - void ClearAllListeners() - { - TheSubject.ReleaseAll(); - } - - void CallListeners(int x, bool y) - { - TheSubject->Call(x, y); - } - - Observer<Handler>* GetSubject() - { - return TheSubject; - } - }; -*/ - -/* - Event listener example: - - class MyListener - { - ObserverScope<Handler> TheObserver; - - void OnEvent(int x, bool y) - { - // Handle event here - } - - public: - MyListener() - { - TheObserver.SetHandler( - Handler::FromMember<MyListener, &MyListener::OnEvent>(this) - ); - } - - void ClearListener() - { - TheObserver.ReleaseAll(); - } - - void ListenTo(Observer<Handler>* emitter) - { - TheObserver->Observe(emitter); - } - }; -*/ - -/* - Usage example: - - MyListener listener; - MyEmitter emitter; - - // To listen to an emitter, - listener.ListenTo(emitter.GetSubject()); - - // To call the listeners, - emitter.CallListeners(22, true); -*/ - -template<class DelegateT> -class Observer : public RefCountBase< Observer<DelegateT> > -{ - friend class ObserverScope<DelegateT>; - friend class ObserverHash<DelegateT>; - -public: - typedef Observer<DelegateT> ThisType; - typedef DelegateT Handler; - -protected: - bool IsShutdown; // Flag to indicate that the object went out of scope - mutable Lock TheLock; // Lock to synchronize calls and shutdown - Array< Ptr< ThisType > > References; // List of observed or observing objects - Handler TheHandler; // Observer-only: Handler for callbacks - - Observer() : - IsShutdown(false) - { - TheHandler.Invalidate(); - } - Observer(Handler handler) : - IsShutdown(false), - TheHandler(handler) - { - } - ~Observer() - { - OVR_ASSERT(References.GetSizeI() == 0); - } - -public: - void SetHandler(Handler handler) - { - OVR_ASSERT(References.GetSizeI() == 0); - TheHandler = handler; - } - - // Release references and prevent further actions - void Shutdown() - { - Lock::Locker locker(&TheLock); - IsShutdown = true; - References.ClearAndRelease(); - } - - // Get count of references held - int GetSizeI() const - { - Lock::Locker locker(&TheLock); - return References.GetSizeI(); - } - - // Observe a subject - bool Observe(ThisType *subject) - { - OVR_ASSERT(TheHandler.IsValid()); - - if (!subject) - { - return false; - } - - Lock::Locker locker(&TheLock); - - if (IsShutdown) - { - return false; - } - - if (!subject->SubjectAddObserver(this)) - { - return false; - } - - References.PushBack(subject); - return true; - } - -protected: - // Subject function: AddObserver() - // Returns true if the observer was added - bool SubjectAddObserver(ThisType* observer) - { - OVR_ASSERT(!TheHandler.IsValid()); - - if (!observer) - { - return true; - } - - Lock::Locker locker(&TheLock); - - if (IsShutdown) - { - return false; - } - - const int count = References.GetSizeI(); - for (int i = 0; i < count; ++i) - { - if (References[i] == observer) - { - // Already watched - return true; - } - } - - References.PushBack(observer); - - return true; - } - -public: - // Subject function: Call() -#define OVR_OBSERVER_CALL_BODY(params) \ - bool callSuccess = false; \ - Lock::Locker locker(&TheLock); \ - int count = References.GetSizeI(); \ - for (int i = 0; i < count; ++i) \ - { \ - if (!References[i]->IsShutdown) \ - { \ - OVR_ASSERT(References[i]->TheHandler.IsValid()); \ - References[i]->TheHandler params; \ - callSuccess = true; \ - } \ - if (References[i]->IsShutdown) \ - { \ - References.RemoveAt(i); \ - --i; --count; \ - } \ - } \ - return callSuccess; - - // Call: Various parameter counts - // Returns true if a call was made - bool Call() - { - OVR_OBSERVER_CALL_BODY(()) - } - template<class Param1> - bool Call(Param1& p1) - { - OVR_OBSERVER_CALL_BODY((p1)) - } - template<class Param1> - bool Call(Param1* p1) - { - OVR_OBSERVER_CALL_BODY((p1)) - } - template<class Param1, class Param2> - bool Call(Param1& p1, Param2& p2) - { - OVR_OBSERVER_CALL_BODY((p1, p2)) - } - template<class Param1, class Param2> - bool Call(Param1* p1, Param2* p2) - { - OVR_OBSERVER_CALL_BODY((p1, p2)) - } - template<class Param1, class Param2, class Param3> - bool Call(Param1& p1, Param2& p2, Param3& p3) - { - OVR_OBSERVER_CALL_BODY((p1, p2, p3)) - } - template<class Param1, class Param2, class Param3> - bool Call(Param1* p1, Param2* p2, Param3* p3) - { - OVR_OBSERVER_CALL_BODY((p1, p2, p3)) - } - -#undef OVR_OBSERVER_CALL_BODY -}; - - -//----------------------------------------------------------------------------- -// ObserverScope - -// Scoped shutdown of the Observer object -template<class DelegateT> -class ObserverScope : public NewOverrideBase -{ - Ptr< Observer<DelegateT> > TheObserver; - DelegateT TheHandler; - - void Shutdown() - { - if (TheObserver) - { - TheObserver->Shutdown(); - TheObserver.Clear(); - } - } - -public: - ObserverScope() - { - TheObserver = *new Observer<DelegateT>; - } - ~ObserverScope() - { - Shutdown(); - } - - // Release all references and recreate it - void ReleaseAll() - { - Shutdown(); - TheObserver = *new Observer<DelegateT>; - if (TheHandler.IsValid()) - { - TheObserver->SetHandler(TheHandler); - } - } - - void SetHandler(DelegateT handler) - { - TheHandler = handler; - TheObserver->SetHandler(handler); - } - - Observer<DelegateT>* GetPtr() - { - return TheObserver.GetPtr(); - } - Observer<DelegateT>* operator->() - { - return TheObserver.GetPtr(); - } - const Observer<DelegateT>* operator->() const - { - return TheObserver.GetPtr(); - } - operator Observer<DelegateT>*() - { - return TheObserver.GetPtr(); - } -}; - - -//----------------------------------------------------------------------------- -// ObserverHash - -// A hash containing Observers -template<class DelegateT> -class ObserverHash : public NewOverrideBase -{ -public: - ObserverHash() {} - ~ObserverHash() {Clear();} - void Clear() - { - Lock::Locker locker(&TheLock); - typename OVR::Hash< String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor >::Iterator it = _Hash.Begin(); - for( it = _Hash.Begin(); it != _Hash.End(); ++it ) - { - Ptr<Observer<DelegateT> > o = it->Second; - o->Shutdown(); - } - } - - Ptr<Observer<DelegateT> > GetSubject(OVR::String key) - { - Lock::Locker locker(&TheLock); - Ptr<Observer<DelegateT> > *o = _Hash.Get(key); - if (o) - return (*o); - return NULL; - } - - // Add handler to new observer with implicit creation of subject. - void AddObserverToSubject(OVR::String key, Observer<DelegateT> *observer) - { - Lock::Locker locker(&TheLock); - Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key); - - if (subjectPtr==NULL) - { - Ptr<Observer<DelegateT> > subject = *new Observer<DelegateT>(); - _Hash.Add(key, subject); - observer->Observe(subject); - } - else - { - observer->Observe(*subjectPtr); - } - } - - void RemoveSubject(OVR::String key) - { - Lock::Locker locker(&TheLock); - Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key); - if (subjectPtr!=NULL) - { - (*subjectPtr)->Shutdown(); - _Hash.Remove(key); - } - } - -protected: - OVR::Hash< OVR::String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor > _Hash; - Lock TheLock; // Lock to synchronize calls and shutdown -}; - - -} // namespace OVR - -#endif // OVR_Observer_h |