Merge pull request #628 from BeamNG/fix_cmake_crash_on_t3d_exit

Fix crash on exit T3D when build with CMake.
This commit is contained in:
Thomas Fischer 2014-05-13 09:12:33 +02:00
commit 08e6b261a3
4 changed files with 112 additions and 4 deletions

View file

@ -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)
{

View file

@ -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;

View file

@ -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.

View file

@ -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();