@ -66,6 +66,9 @@
# include <windows.h>
# include <windows.h>
# endif // NL_OS_WINDOWS
# endif // NL_OS_WINDOWS
# include <mutex>
# include <condition_variable>
using namespace std ;
using namespace std ;
using namespace NLNET ;
using namespace NLNET ;
using namespace NLMISC ;
using namespace NLMISC ;
@ -236,33 +239,50 @@ void flushMessagesToSend()
class CSendRunnable : public IRunnable
class CSendRunnable : public IRunnable
{
{
public :
public :
CSendRunnable ( ) : m_StopThread ( false ) , m_SendBuffer ( false ) { }
CSendRunnable ( ) : StopThread ( false ) , SendBuffer ( false ) { }
volatile bool StopThread ;
volatile bool SendBuffer ;
virtual void run ( )
virtual void run ( )
{
{
while ( ! StopThread )
for ( ; ; )
{
{
while ( ! StopThread & & ! SendBuffer )
{
nlSleep ( 1 ) ; // FIXME: Use thread event instead. This is only called once per tick, so no need to heat up the CPU here either
std : : unique_lock < std : : mutex > lock ( m_Mutex ) ;
m_CondVar . wait ( lock , [ & ] ( ) - > bool { return m_StopThread | | m_SendBuffer ; } ) ;
if ( StopThread )
m_SendBuffer = false ;
break ;
if ( m_StopThread )
{
SendBuffer = false ;
m_StopThread = false ;
return ;
}
}
flushMessagesToSend ( ) ;
flushMessagesToSend ( ) ;
}
}
}
void sendBuffer ( )
{
std : : unique_lock < std : : mutex > lock ( m_Mutex ) ;
m_SendBuffer = true ;
m_CondVar . notify_one ( ) ;
}
StopThread = false ;
void stopThread ( )
{
std : : unique_lock < std : : mutex > lock ( m_Mutex ) ;
m_StopThread = true ;
m_CondVar . notify_one ( ) ;
}
}
private :
bool m_StopThread ;
bool m_SendBuffer ;
std : : condition_variable m_CondVar ;
std : : mutex m_Mutex ;
} ;
} ;
CSendRunnable SendTask ;
CSendRunnable * SendTask ;
IThread * SendThread = NULL ;
IThread * SendThread ;
/*
/*
* Receive task
* Receive task
@ -1138,7 +1158,7 @@ inline void CFrontEndService::onTick()
fillPrioritizedActionsToSend ( ) ;
fillPrioritizedActionsToSend ( ) ;
swapSendBuffers ( ) ; // waits for the end of flushMessagesToSend using the boolean FlushInProgress (with addWait there would be a deadlock at the beginning)
swapSendBuffers ( ) ; // waits for the end of flushMessagesToSend using the boolean FlushInProgress (with addWait there would be a deadlock at the beginning)
SendTask . SendBuffer = true ;
SendTask - > sendBuffer ( ) ;
if ( SendThread = = NULL )
if ( SendThread = = NULL )
{
{
@ -1328,7 +1348,8 @@ void CFrontEndService::init()
{
{
// Init send thread
// Init send thread
nlinfo ( " UseSendThread on, initialise send thread " ) ;
nlinfo ( " UseSendThread on, initialise send thread " ) ;
SendThread = IThread : : create ( & SendTask ) ;
SendTask = new CSendRunnable ( ) ;
SendThread = IThread : : create ( SendTask ) ;
SendThread - > start ( ) ;
SendThread - > start ( ) ;
}
}
@ -1379,7 +1400,10 @@ void CFrontEndService::postInit()
*/
*/
void CFrontEndService : : release ( )
void CFrontEndService : : release ( )
{
{
SendTask . StopThread = true ;
if ( SendTask )
{
SendTask - > stopThread ( ) ;
}
_ReceiveSub . release ( ) ;
_ReceiveSub . release ( ) ;
@ -1402,12 +1426,15 @@ void CFrontEndService::release()
{
{
nlinfo ( " Release send thread, waiting for task to terminate " ) ;
nlinfo ( " Release send thread, waiting for task to terminate " ) ;
// stop send thread
// stop send thread
while ( SendT ask. StopThread )
while ( SendT hread- > isRunning ( ) ) // FIXME: Implement thread.join()
nlSleep ( 1 ) ;
nlSleep ( 1 ) ;
delete SendThread ;
delete SendThread ;
SendThread = NULL ;
SendThread = NULL ;
}
}
delete SendTask ;
SendTask = NULL ;
}
}