You.i Engine
CYISignalHandler Class Reference

Detailed Description

This is the foundation class of the signal and slots. This class is a marker for a collection of slots, allowing them to connect to any internal or external CYISignal. This class serves as a life-tracker of the object, and as a connection manager for the CYISignal connected to it. If the CYISignalHandler goes out of scope, or is deleted, all of its connection will be automatically disconnected in a thread-safe manner.

If a CYISignalHandler (or a class that derives from CYISignalHandler) is copied, all existing signal connections are copied as well. If this is undesirable, call DisconnectFromAllSignals() on the copy.

Here is an example of how to use the CYISignal and CYISignalHandler to mark a class:

// first we add a signal into this class
class SomeClass
{
// a one parameter signal named "MySignal"
};
// Secondly, make our slots
class MyHandler : public CYISignalHandler
{
public:
void DoSomething();
void DoSomethingElse(uint32_t data);
};
// Now, the last step is to instantiate our signal and slot
// and wire them up.
void Setup()
{
SomeClass *pSomeClass = new SomeClass();
MyHandler *pMyHandler = new MyHandler();
// Connect. Notice how a connection is established between
// SomeClass and MyHandler while not even knowing anything
// about each other.
pSomeClass->MySignal.Connect(*pMyHandler, &MyHandler::DoSomething);
pSomeClass->MySignal.Connect(*pMyHandler, &MyHandler::DoSomethingElse);
// And we emit a signal. Both MyHandler::DoSomething and
// MyHandler::DoSomethingElse should be called, while MyHandler::DoSomethingElse
// receives the value of 42.
pSomeClass->MySignal(42);
// if we delete the handler, the connection is automatically disconnected.
delete pMyHandler;
// this won't have any effect, and most importantly, it won't crash
pSomeClass->MySignal(43);
// finally, delete SomeClass. Memory leaks are bad.
delete pSomeClass;
}

When instantiating a CYISignalHandler, it will automatically bind itself to the thread that created it in the first place. Every time we connect a CYISignal to this CYISignalHanlder using the default EYIConnectionType::Auto connection type, the signal will compare its calling thread against the CYISignalHandler thread. If they are different, then the signal will be queued onto the thread's CYIEventDispatcher if the CYIThread and the CYIEventDispatcher is running.

Here is an code example:

// first we add a signal into this class
class SomeClass
{
// a one parameter signal named "MySignal"
};
// Secondly, make our slots
class MyHandler : public CYISignalHandler
{
public:
void DoSomething();
void DoSomethingElse(uint32_t data);
};
// And then make a thread class
class MyThread : public CYIThread
{
public:
MyThread();
MyHandler *GetHandler();
protected:
virtual void Run() override;
private:
MyHandler *m_pHandler;
};
inline MyThread::MyThread() : m_pHandler(NULL)
{
}
inline MyHandler *MyThread::GetHandler()
{
return m_pHandler;
}
inline void MyThread::Run()
{
// the Handler will be bound to this new thread.
m_pHandler = new MyHandler();
// start the event dispatcher by running default Run()
// This will block until someone calls CYIThread::Terminate()
delete m_pHandler;
m_pHandler = NULL;
}
// Now, the last step is to instantiate our signal and slot
// and wire them up.
void Setup()
{
MyThread *pThread = new MyThread();
pThread->StartThread();
YI_SLEEP(100); // wait for thread to start
SomeClass *pSomeClass = new SomeClass();
// Connect. Notice how a connection is established between
// SomeClass and MyHandler while not even knowing anything
// about each other.
pSomeClass->MySignal.Connect(*(pThread->GetHandler()), &MyHandler::DoSomething);
pSomeClass->MySignal.Connect(*(pThread->GetHandler()), &MyHandler::DoSomethingElse);
// And we emit a signal. Both MyHandler::DoSomething and
// MyHandler::DoSomethingElse should be called, while MyHandler::DoSomethingElse
// receives the value of 42. The only difference from the 1st example is that the
// signal will be queued and will return immediately. Signal is automatically asynchronous.
pSomeClass->MySignal(42);
YI_SLEEP(100); // wait for thread to process the signal event
pThread->Terminate();
pThread->Join();
delete pThread;
// this won't have any effect, and most importantly, it won't crash
pSomeClass->MySignal(43);
// finally, delete SomeClass. Memory leaks are bad.
delete pSomeClass;
}
Warning
Signals and slots should not be used in time-critical sections, as they heavily make use of mutexes for thread-safety. Synchronous signals can be four times slower than calling a virtual function directly.
See also
CYISignal
CYIThread

#include <signal/YiSignalHandler.h>

Inheritance diagram for CYISignalHandler:

Public Member Functions

 CYISignalHandler ()
 
 CYISignalHandler (const CYISignalHandler &rSignalHandler)
 
virtual ~CYISignalHandler ()
 
CYISignalHandleroperator= (const CYISignalHandler &rSignalHandler)
 
void MoveToThread (CYIThread *pThread)
 This function allows the user to override the default thread affinity to any CYIThread that may or may not be running. More...
 
CYIThreadHandle GetThreadAffinity () const
 
void SetThreadAffinity (const CYIThreadHandle &rThreadAffinity)
 
virtual bool IsConnected () const
 
virtual bool IsConnected (const CYISignalBase &rSignal) const
 
void Disconnect (CYISignalBase &rSignal)
 
void DisconnectFromAllSignals ()
 
- Public Member Functions inherited from CYIThread::Listener
 Listener ()
 
virtual ~Listener ()
 
virtual void OnThreadStarted (CYIThread *)
 
virtual void OnThreadTerminated (CYIThread *)
 
virtual void OnThreadFinished (CYIThread *)
 

Friends

class CYISignalBase
 

Constructor & Destructor Documentation

◆ CYISignalHandler() [1/2]

CYISignalHandler::CYISignalHandler ( )

◆ CYISignalHandler() [2/2]

CYISignalHandler::CYISignalHandler ( const CYISignalHandler rSignalHandler)

◆ ~CYISignalHandler()

virtual CYISignalHandler::~CYISignalHandler ( )
virtual

Member Function Documentation

◆ Disconnect()

void CYISignalHandler::Disconnect ( CYISignalBase rSignal)

Disconnects all established connections from a given CYISignal.

Note
This is done automatically when the CYISignal goes out of scope or is deleted.
If the connection doesn't exists with a given slot, it won't have any effect.
This function is thread-safe.
See also
CYISignalBase::Disconnect(CYISignalHandler &rSignalHandler)
DisconnectFromAllSignals()

◆ DisconnectFromAllSignals()

void CYISignalHandler::DisconnectFromAllSignals ( )

Disconnects every connection from every CYISignal.

Note
This function is thread-safe.
See also
CYISignalBase::Disconnect(CYISignalHandler &rSignalHandler)
Disconnect(CYISignalBase &rSignal)

◆ GetThreadAffinity()

CYIThreadHandle CYISignalHandler::GetThreadAffinity ( ) const

Returns the thread affinity of the object.

Usually, it will return the CYIThreadHandle of the thread that instantiated our CYISignalHandler, but if the CYISignalHandler has been moved to a different thread using MoveToThread(CYIThread *pThread) and if the CYIThread is running, it will return the CYIThreadHandle of that CYIThread instead. If the thread is not running or stopped running, it will default back to the thread that instantiated it.

Warning
This function is not thread-safe.

◆ IsConnected() [1/2]

virtual bool CYISignalHandler::IsConnected ( ) const
virtual

Checks if at least one connection has been established with any CYISignal.

Note
This function is thread-safe.
See also
IsConnected(const CYISignalBase &rSignal) const
CYISignalBase::IsConnected(const CYISignalHandler &) const

Reimplemented in CYISignalBase.

◆ IsConnected() [2/2]

virtual bool CYISignalHandler::IsConnected ( const CYISignalBase rSignal) const
virtual

Checks if this CYISignalHandler is connected to a specific CYISignal.

Example:

class MyHandler : public CYISignalHandler
{
public:
void Slot0();
void Slot1(int32_t param);
};
MyHandler myHandler;
void Setup()
{
MySignal1.Connect(myHandler, &MyHandler::Slot0);
}
bool IsConnectedToMySignal1()
{
return myHandler.IsConnected(MySignal1); // will return 'true'
}
bool IsConnectedToMySignal2()
{
return myHandler.IsConnected(MySignal2); // will return 'false'
}
Note
This function is thread-safe.
See also
IsConnected() const
CYISignalBase::IsConnected(const CYISignalHandler &) const

Reimplemented in CYISignalBase.

◆ MoveToThread()

void CYISignalHandler::MoveToThread ( CYIThread pThread)

This function allows the user to override the default thread affinity to any CYIThread that may or may not be running.

Here is an example:

// first we add a signal into this class
class SomeClass
{
// a one parameter signal named "MySignal"
};
// Secondly, make our slots
class MyHandler : public CYISignalHandler
{
public:
void DoSomething();
void DoSomethingElse(uint32_t data);
};
// Now, the last step is to instantiate our signal and slot
// and wire them up.
void Setup()
{
CYIThread *pThread = new CYIThread();
SomeClass *pSomeClass = new SomeClass();
MyHandler *pMyHandler = new MyHandler();
// Connect. Notice how a connection is established between
// SomeClass and MyHandler while not even knowing anything
// about each other.
pSomeClass->MySignal.Connect(*pMyHandler, &MyHandler::DoSomething);
pSomeClass->MySignal.Connect(*pMyHandler, &MyHandler::DoSomethingElse);
// We manually change our handler's thread affinity.
pMyHandler->MoveToThread(pThread);
// Start the thread after to demonstrate that the thread can be started after
// the thread affinity change.
pThread->StartThread();
YI_SLEEP(100); // wait for thread to start
// And we emit a signal. Both MyHandler::DoSomething and
// MyHandler::DoSomethingElse should be called, while MyHandler::DoSomethingElse
// receives the value of 42. The only difference from the 1st example is that the
// signal will be queued and will return immediately. Signal is automatically asynchronous.
pSomeClass->MySignal(42);
YI_SLEEP(100); // wait for thread to process the signal event
pThread->Terminate();
pThread->Join();
delete pThread;
// this won't have any effect, and most importantly, it won't crash
pSomeClass->MySignal(43);
// finally, delete SomeClass. Memory leaks are bad.
delete pSomeClass;
}
Note
If the given CYIThread goes out of scope or is deleted by the user, it will automatically be disassociated and the thread affinity will default back to the thread that instantiated the CYISignalHandler.
Warning
This function is not thread-safe.
See also
SetThreadAffinity

◆ operator=()

CYISignalHandler& CYISignalHandler::operator= ( const CYISignalHandler rSignalHandler)

◆ SetThreadAffinity()

void CYISignalHandler::SetThreadAffinity ( const CYIThreadHandle rThreadAffinity)

Sets the thread affinity to rThreadAffinity.

This function is very similar to MoveToThread(CYIThread *pThread), but it will overwrite the creation thread affinity instead. If a CYIThread has previously been assigned using MoveToThread(CYIThread *pThread), it will be automatically be disassociated from this CYIThread. The CYIThreadHandle can be created from any thread from any thread API. It does not require to be from a CYIThread.

Warning
This function is not thread-safe.
See also
CYIThread::GetCurrentThreadId()

Friends And Related Function Documentation

◆ CYISignalBase

friend class CYISignalBase
friend

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