Explorar el Código

Merge pull request #628 from BeamNG/fix_cmake_crash_on_t3d_exit

 Fix crash on exit T3D when build with CMake.
Thomas Fischer hace 11 años
padre
commit
08e6b261a3

+ 5 - 0
Engine/source/core/util/journal/process.h

@@ -96,6 +96,11 @@ public:
       get()._signalProcess.notify(del,order);
    }
 
+   static void notify(SignalSlot<void()> &slot, F32 order = PROCESS_DEFAULT_ORDER) 
+   {
+      get()._signalProcess.notify(slot,order);
+   }
+
    template <class T>
    static void notify(T func, F32 order = PROCESS_DEFAULT_ORDER) 
    {

+ 103 - 0
Engine/source/core/util/tSignal.h

@@ -77,6 +77,8 @@ protected:
 
       void insert(DelegateLink* node, F32 order);
       void unlink();
+
+      virtual ~DelegateLink() {}
    };
 
    DelegateLink mList;
@@ -92,6 +94,78 @@ protected:
    Vector<DelegateLink*> mTriggerNext;
 };
 
+template<typename Signature> class SignalBaseT;
+
+/// Class for handle automatic diconnect form Signal when destroyed
+template< typename Signature >
+class SignalSlot
+{
+public:
+   typedef Delegate< Signature > DelegateSig;
+   typedef SignalBaseT< Signature > SignalSig;
+
+   SignalSlot() : mSignal(NULL)
+   {
+
+   }
+
+   ~SignalSlot()
+   {
+      disconnect();
+   }
+
+   const DelegateSig& getDelegate() { return mDlg; }
+
+   /// setDelegate disconect form Signal old delegate and connect new delegate
+   template<typename X>
+   void setDelegate( const X &fn ) { setDelegate( DelegateSig( fn ) ); }
+
+   template<typename X, typename Y>
+   void setDelegate( const X &ptr, const Y &fn ) { setDelegate( DelegateSig( ptr, fn ) ); }
+
+   void setDelegate( const DelegateSig &dlg) 
+   {
+      SignalSig* signal = mSignal;
+      if( isConnected() )
+         disconnect();      
+
+      mDlg = dlg;
+      if( signal && mDlg )
+         signal->notify( mDlg );
+   }
+
+   /// is connected to Signal
+   bool isConnected() const { return mSignal; }
+
+   /// disconnect from Signal
+   void disconnect()
+   {
+      if( mSignal )
+      {
+         SignalSig *oldSignal = mSignal;
+         mSignal = NULL;
+         oldSignal->remove( mDlg );
+      }
+   }
+
+protected:
+   friend class SignalSig;
+
+   void _setSignal(SignalSig *sig)
+   {      
+      mSignal = sig;
+   }
+
+   SignalSig* _getSignal() const { return mSignal; }   
+
+   DelegateSig mDlg;
+   SignalSig *mSignal;
+
+private:
+   SignalSlot( const SignalSlot&) {}
+   SignalSlot& operator=( const SignalSlot&) {}
+};
+
 template<typename Signature> class SignalBaseT : public SignalBase
 {
 public:
@@ -163,6 +237,18 @@ public:
       notify(dlg, order);
    }
 
+   void notify( SignalSlot<Signature> &slot, F32 order = 0.5f)
+   {
+      if( !slot.getDelegate() )
+         return;
+
+      if( slot.isConnected() )
+         slot.disconnect();
+
+      slot._setSignal( this );
+      mList.insert( new SlotLinkImpl(slot), order );
+   }
+
    template <class T,class U>
    void remove(T obj,U func)
    {
@@ -198,6 +284,23 @@ protected:
       DelegateLinkImpl(DelegateSig dlg) : mDelegate(dlg) {}
    };
 
+   struct SlotLinkImpl : public DelegateLinkImpl
+   {      
+      SlotLinkImpl(SignalSlot<Signature>& slot) : mSlot( &slot ), DelegateLinkImpl( slot.getDelegate() )
+      {
+
+      }
+
+      ~SlotLinkImpl()
+      {
+         if( mSlot )
+            mSlot->_setSignal( NULL ); 
+      }
+
+   protected:
+      SignalSlot<Signature> *mSlot;
+   };
+
    DelegateSig & getDelegate(SignalBase::DelegateLink * link)
    {
       return ((DelegateLinkImpl*)link)->mDelegate;

+ 2 - 4
Engine/source/windowManager/win32/win32WindowMgr.cpp

@@ -41,7 +41,8 @@ PlatformWindowManager * CreatePlatformWindowManager()
 Win32WindowManager::Win32WindowManager()
 {
    // Register in the process list.
-   Process::notify(this, &Win32WindowManager::_process, PROCESS_INPUT_ORDER);
+   mOnProcessSignalSlot.setDelegate( this, &Win32WindowManager::_process );
+   Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER );
 
    // Init our list of allocated windows.
    mWindowListHead = NULL;
@@ -58,9 +59,6 @@ Win32WindowManager::Win32WindowManager()
 
 Win32WindowManager::~Win32WindowManager()
 {
-   // Get ourselves off the process list.
-   Process::remove(this, &Win32WindowManager::_process);
-
    // Kill all our windows first.
    while(mWindowListHead)
       // The destructors update the list, so this works just fine.

+ 2 - 0
Engine/source/windowManager/win32/win32WindowMgr.h

@@ -85,6 +85,8 @@ class Win32WindowManager : public PlatformWindowManager
    /// If a curtain window is present, then its HWND will be stored here.
    HWND mCurtainWindow;
 
+   SignalSlot<void()> mOnProcessSignalSlot;
+
 public:
    Win32WindowManager();
    ~Win32WindowManager();