FWIW, I was able to simulate the event idea with just basic threads and mutexes. A native implementation would be better, though, as the below approach involves creating an entirely separate thread, and has additional latency due to sleeping:
class ThreadEvent : public sf::NonCopyable
{
public:
ThreadEvent()
: mThread(&ThreadEvent::ThreadLogic,this)
, mState(state_none)
, mWantExit(false)
, mIsLocked(false)
{
mThread.Launch();
}
~ThreadEvent()
{
mWantExit = true;
mThread.Wait();
}
inline bool IsLocked() { return mIsLocked; }
inline void Lock() { ChangeState( state_wantlock ); }
inline void Unlock() { ChangeState( state_wantunlock ); }
inline void Wait() { mStateLock.Lock(); mStateLock.Unlock(); }
private:
void ThreadLogic()
{
while(!mWantExit)
{
if(mState == state_wantlock)
{
if(!mIsLocked)
{
mStateLock.Lock();
mIsLocked = true;
}
mState = state_none;
}
if(mState == state_wantunlock)
{
if(mIsLocked)
{
mStateLock.Unlock();
mIsLocked = false;
}
mState = state_none;
}
try{
sf::Sleep(1);
}catch(...){}
}
if(mIsLocked)
mStateLock.Unlock();
}
sf::Thread mThread;
sf::Mutex mStateLock; // locked by mThread when state is "reset"
sf::Mutex mStateChange; // locked to guard state changes
enum state_t
{
state_none,
state_wantlock,
state_wantunlock
};
volatile state_t mState;
volatile bool mIsLocked;
volatile bool mWantExit;
void ChangeState(state_t newstate)
{
sf::Lock lock(mStateChange);
mState = newstate;
while(mState != state_none)
sf::Sleep(1);
}
};