1
0

Fixed *nix threading issue;

Thread objects now use variable names consistent with MCS convention;
Fixed a few *nix threading cornercases

git-svn-id: http://mc-server.googlecode.com/svn/trunk@392 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2012-03-10 17:37:00 +00:00
parent e5b91a8d97
commit 1a5ebb44aa
11 changed files with 93 additions and 88 deletions

View File

@ -30,7 +30,7 @@ cChunkSender::cChunkSender(void) :
cChunkSender::~cChunkSender() cChunkSender::~cChunkSender()
{ {
mShouldTerminate = true; m_ShouldTerminate = true;
m_evtQueue.Set(); m_evtQueue.Set();
} }
@ -100,7 +100,7 @@ void cChunkSender::RemoveClient(cClientHandle * a_Client)
void cChunkSender::Execute(void) void cChunkSender::Execute(void)
{ {
while (!mShouldTerminate) while (!m_ShouldTerminate)
{ {
cCSLock Lock(m_CS); cCSLock Lock(m_CS);
while (m_ChunksReady.empty() && m_SendChunks.empty()) while (m_ChunksReady.empty() && m_SendChunks.empty())
@ -108,7 +108,7 @@ void cChunkSender::Execute(void)
cCSUnlock Unlock(Lock); cCSUnlock Unlock(Lock);
m_evtRemoved.Set(); // Notify that the removed clients are safe to be deleted m_evtRemoved.Set(); // Notify that the removed clients are safe to be deleted
m_evtQueue.Wait(); m_evtQueue.Wait();
if (mShouldTerminate) if (m_ShouldTerminate)
{ {
return; return;
} }

View File

@ -40,7 +40,7 @@ void cLightingThread::Stop(void)
delete *itr; delete *itr;
} // for itr - m_Queue[] } // for itr - m_Queue[]
} }
mShouldTerminate = true; m_ShouldTerminate = true;
m_Event.Set(); m_Event.Set();
Wait(); Wait();

View File

@ -153,10 +153,11 @@ void cWorldStorage::WaitForFinish(void)
} }
// Wait for the thread to finish: // Wait for the thread to finish:
mShouldTerminate = true; m_ShouldTerminate = true;
m_Event.Set(); m_Event.Set();
m_evtRemoved.Set(); // Wake up anybody waiting in the WaitForQueuesEmpty() method m_evtRemoved.Set(); // Wake up anybody waiting in the WaitForQueuesEmpty() method
super::Wait(); super::Wait();
LOG("World storage thread finished");
} }
@ -166,7 +167,7 @@ void cWorldStorage::WaitForFinish(void)
void cWorldStorage::WaitForQueuesEmpty(void) void cWorldStorage::WaitForQueuesEmpty(void)
{ {
cCSLock Lock(m_CSQueues); cCSLock Lock(m_CSQueues);
while (!mShouldTerminate && (!m_LoadQueue.empty() || !m_SaveQueue.empty())) while (!m_ShouldTerminate && (!m_LoadQueue.empty() || !m_SaveQueue.empty()))
{ {
cCSUnlock Unlock(Lock); cCSUnlock Unlock(Lock);
m_evtRemoved.Wait(); m_evtRemoved.Wait();
@ -305,7 +306,7 @@ void cWorldStorage::InitSchemas(void)
void cWorldStorage::Execute(void) void cWorldStorage::Execute(void)
{ {
while (!mShouldTerminate) while (!m_ShouldTerminate)
{ {
m_Event.Wait(); m_Event.Wait();
@ -314,7 +315,7 @@ void cWorldStorage::Execute(void)
do do
{ {
HasMore = false; HasMore = false;
if (mShouldTerminate) if (m_ShouldTerminate)
{ {
return; return;
} }

View File

@ -24,9 +24,9 @@
cAuthenticator::cAuthenticator(void) : cAuthenticator::cAuthenticator(void) :
super("cAuthenticator"), super("cAuthenticator"),
mServer(DEFAULT_AUTH_SERVER), m_Server(DEFAULT_AUTH_SERVER),
mAddress(DEFAULT_AUTH_ADDRESS), m_Address(DEFAULT_AUTH_ADDRESS),
mShouldAuthenticate(true) m_ShouldAuthenticate(true)
{ {
ReadINI(); ReadINI();
} }
@ -53,27 +53,27 @@ void cAuthenticator::ReadINI(void)
return; return;
} }
mServer = IniFile.GetValue("Authentication", "Server"); m_Server = IniFile.GetValue("Authentication", "Server");
mAddress = IniFile.GetValue("Authentication", "Address"); m_Address = IniFile.GetValue("Authentication", "Address");
mShouldAuthenticate = IniFile.GetValueB("Authentication", "Authenticate", true); m_ShouldAuthenticate = IniFile.GetValueB("Authentication", "Authenticate", true);
bool bSave = false; bool bSave = false;
if (mServer.length() == 0) if (m_Server.length() == 0)
{ {
mServer = DEFAULT_AUTH_SERVER; m_Server = DEFAULT_AUTH_SERVER;
IniFile.SetValue("Authentication", "Server", mServer); IniFile.SetValue("Authentication", "Server", m_Server);
bSave = true; bSave = true;
} }
if (mAddress.length() == 0) if (m_Address.length() == 0)
{ {
mAddress = DEFAULT_AUTH_ADDRESS; m_Address = DEFAULT_AUTH_ADDRESS;
IniFile.SetValue("Authentication", "Address", mAddress); IniFile.SetValue("Authentication", "Address", m_Address);
bSave = true; bSave = true;
} }
if (bSave) if (bSave)
{ {
IniFile.SetValueB("Authentication", "Authenticate", mShouldAuthenticate); IniFile.SetValueB("Authentication", "Authenticate", m_ShouldAuthenticate);
IniFile.WriteFile(); IniFile.WriteFile();
} }
} }
@ -85,15 +85,15 @@ void cAuthenticator::ReadINI(void)
/// Queues a request for authenticating a user. If the auth fails, the user is kicked /// Queues a request for authenticating a user. If the auth fails, the user is kicked
void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash) void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash)
{ {
if (!mShouldAuthenticate) if (!m_ShouldAuthenticate)
{ {
cRoot::Get()->AuthenticateUser(a_ClientID); cRoot::Get()->AuthenticateUser(a_ClientID);
return; return;
} }
cCSLock Lock(mCS); cCSLock Lock(m_CS);
mQueue.push_back(cUser(a_ClientID, a_UserName, a_ServerHash)); m_Queue.push_back(cUser(a_ClientID, a_UserName, a_ServerHash));
mQueueNonempty.Set(); m_QueueNonempty.Set();
} }
@ -102,8 +102,8 @@ void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, co
void cAuthenticator::Stop(void) void cAuthenticator::Stop(void)
{ {
mShouldTerminate = true; m_ShouldTerminate = true;
mQueueNonempty.Set(); m_QueueNonempty.Set();
Wait(); Wait();
} }
@ -115,27 +115,27 @@ void cAuthenticator::Execute(void)
{ {
for (;;) for (;;)
{ {
cCSLock Lock(mCS); cCSLock Lock(m_CS);
while (!mShouldTerminate && (mQueue.size() == 0)) while (!m_ShouldTerminate && (m_Queue.size() == 0))
{ {
cCSUnlock Unlock(Lock); cCSUnlock Unlock(Lock);
mQueueNonempty.Wait(); m_QueueNonempty.Wait();
} }
if (mShouldTerminate) if (m_ShouldTerminate)
{ {
return; return;
} }
ASSERT(mQueue.size() > 0); ASSERT(m_Queue.size() > 0);
int ClientID = mQueue.front().mClientID; int ClientID = m_Queue.front().mClientID;
AString UserName = mQueue.front().mName; AString UserName = m_Queue.front().mName;
AString ActualAddress = mAddress; AString ActualAddress = m_Address;
ReplaceString(ActualAddress, "%USERNAME%", UserName); ReplaceString(ActualAddress, "%USERNAME%", UserName);
ReplaceString(ActualAddress, "%SERVERID%", cRoot::Get()->GetServer()->GetServerID()); ReplaceString(ActualAddress, "%SERVERID%", cRoot::Get()->GetServer()->GetServerID());
mQueue.pop_front(); m_Queue.pop_front();
Lock.Unlock(); Lock.Unlock();
if (!AuthFromAddress(mServer, ActualAddress, UserName)) if (!AuthFromAddress(m_Server, ActualAddress, UserName))
{ {
cRoot::Get()->KickUser(ClientID, "Failed to authenticate account!"); cRoot::Get()->KickUser(ClientID, "Failed to authenticate account!");
} }

View File

@ -59,13 +59,13 @@ private:
typedef std::deque<cUser> cUserList; typedef std::deque<cUser> cUserList;
cCriticalSection mCS; cCriticalSection m_CS;
cUserList mQueue; cUserList m_Queue;
cEvent mQueueNonempty; cEvent m_QueueNonempty;
AString mServer; AString m_Server;
AString mAddress; AString m_Address;
bool mShouldAuthenticate; bool m_ShouldAuthenticate;
// cIsThread override: // cIsThread override:
virtual void Execute(void) override; virtual void Execute(void) override;

View File

@ -69,7 +69,7 @@ bool cChunkGenerator::Start(cWorld * a_World, const AString & a_WorldGeneratorNa
void cChunkGenerator::Stop(void) void cChunkGenerator::Stop(void)
{ {
mShouldTerminate = true; m_ShouldTerminate = true;
m_Event.Set(); m_Event.Set();
m_evtRemoved.Set(); // Wake up anybody waiting for empty queue m_evtRemoved.Set(); // Wake up anybody waiting for empty queue
Wait(); Wait();
@ -115,7 +115,7 @@ void cChunkGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
void cChunkGenerator::WaitForQueueEmpty(void) void cChunkGenerator::WaitForQueueEmpty(void)
{ {
cCSLock Lock(m_CS); cCSLock Lock(m_CS);
while (!mShouldTerminate && !m_Queue.empty()) while (!m_ShouldTerminate && !m_Queue.empty())
{ {
cCSUnlock Unlock(Lock); cCSUnlock Unlock(Lock);
m_evtRemoved.Wait(); m_evtRemoved.Wait();
@ -138,14 +138,14 @@ int cChunkGenerator::GetQueueLength(void)
void cChunkGenerator::Execute(void) void cChunkGenerator::Execute(void)
{ {
while (!mShouldTerminate) while (!m_ShouldTerminate)
{ {
cCSLock Lock(m_CS); cCSLock Lock(m_CS);
while (m_Queue.size() == 0) while (m_Queue.size() == 0)
{ {
cCSUnlock Unlock(Lock); cCSUnlock Unlock(Lock);
m_Event.Wait(); m_Event.Wait();
if (mShouldTerminate) if (m_ShouldTerminate)
{ {
return; return;
} }

View File

@ -51,12 +51,12 @@ static void SetThreadName( DWORD dwThreadID, LPCSTR szThreadName)
// cIsThread: // cIsThread:
cIsThread::cIsThread(const AString & iThreadName) : cIsThread::cIsThread(const AString & iThreadName) :
mThreadName(iThreadName), m_ThreadName(iThreadName),
mShouldTerminate(false), m_ShouldTerminate(false),
#ifdef _WIN32 #ifdef _WIN32
mHandle(NULL) m_Handle(NULL)
#else // _WIN32 #else // _WIN32
mHasStarted(false) m_HasStarted(false)
#endif // else _WIN32 #endif // else _WIN32
{ {
} }
@ -67,7 +67,7 @@ cIsThread::cIsThread(const AString & iThreadName) :
cIsThread::~cIsThread() cIsThread::~cIsThread()
{ {
mShouldTerminate = true; m_ShouldTerminate = true;
Wait(); Wait();
} }
@ -78,34 +78,35 @@ cIsThread::~cIsThread()
bool cIsThread::Start(void) bool cIsThread::Start(void)
{ {
#ifdef _WIN32 #ifdef _WIN32
ASSERT(mHandle == NULL); // Has already started one thread? ASSERT(m_Handle == NULL); // Has already started one thread?
// Create the thread suspended, so that the mHandle variable is valid in the thread procedure // Create the thread suspended, so that the mHandle variable is valid in the thread procedure
DWORD ThreadID = 0; DWORD ThreadID = 0;
mHandle = CreateThread(NULL, 0, thrExecute, this, CREATE_SUSPENDED, &ThreadID); m_Handle = CreateThread(NULL, 0, thrExecute, this, CREATE_SUSPENDED, &ThreadID);
if (mHandle == NULL) if (m_Handle == NULL)
{ {
LOGERROR("ERROR: Could not create thread \"%s\", GLE = %d!", mThreadName.c_str(), GetLastError()); LOGERROR("ERROR: Could not create thread \"%s\", GLE = %d!", m_ThreadName.c_str(), GetLastError());
return false; return false;
} }
ResumeThread(mHandle); ResumeThread(m_Handle);
#if defined(_DEBUG) && defined(_MSC_VER) #if defined(_DEBUG) && defined(_MSC_VER)
// Thread naming is available only in MSVC // Thread naming is available only in MSVC
if (!mThreadName.empty()) if (!m_ThreadName.empty())
{ {
SetThreadName(ThreadID, mThreadName.c_str()); SetThreadName(ThreadID, m_ThreadName.c_str());
} }
#endif // _DEBUG and _MSC_VER #endif // _DEBUG and _MSC_VER
#else // _WIN32 #else // _WIN32
ASSERT(!mHasStarted); ASSERT(!m_HasStarted);
if (pthread_create(&mHandle, NULL, thrExecute, this)) if (pthread_create(&m_Handle, NULL, thrExecute, this))
{ {
LOGERROR("ERROR: Could not create thread \"%s\", !", mThreadName.c_str()); LOGERROR("ERROR: Could not create thread \"%s\", !", m_ThreadName.c_str());
return false; return false;
} }
m_HasStarted = true;
#endif // else _WIN32 #endif // else _WIN32
return true; return true;
@ -119,28 +120,30 @@ bool cIsThread::Wait(void)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (mHandle == NULL) if (m_Handle == NULL)
{ {
return true; return true;
} }
// Cannot log, logger may already be stopped: // Cannot log, logger may already be stopped:
// LOG("Waiting for thread \"%s\" to terminate.", mThreadName.c_str()); // LOG("Waiting for thread \"%s\" to terminate.", m_ThreadName.c_str());
int res = WaitForSingleObject(mHandle, INFINITE); int res = WaitForSingleObject(m_Handle, INFINITE);
mHandle = NULL; m_Handle = NULL;
// Cannot log, logger may already be stopped: // Cannot log, logger may already be stopped:
// LOG("Thread \"%s\" %s terminated, GLE = %d", mThreadName.c_str(), (res == WAIT_OBJECT_0) ? "" : "not", GetLastError()); // LOG("Thread \"%s\" %s terminated, GLE = %d", m_ThreadName.c_str(), (res == WAIT_OBJECT_0) ? "" : "not", GetLastError());
return (res == WAIT_OBJECT_0); return (res == WAIT_OBJECT_0);
#else // _WIN32 #else // _WIN32
if (!mHasStarted) if (!m_HasStarted)
{ {
return true; return true;
} }
LOG("Waiting for thread \"%s\" to terminate.", mThreadName.c_str()); // Cannot log, logger may already be stopped:
int res = pthread_join(mHandle, NULL); // LOG("Waiting for thread \"%s\" to terminate.", m_ThreadName.c_str());
mHasStarted = false; int res = pthread_join(m_Handle, NULL);
LOG("Thread \"%s\" %s terminated, errno = %d", mThreadName.c_str(), (res == 0) ? "" : "not", errno); m_HasStarted = false;
// Cannot log, logger may already be stopped:
// LOG("Thread \"%s\" %s terminated, errno = %d", m_ThreadName.c_str(), (res == 0) ? "" : "not", errno);
return (res == 0); return (res == 0);
#endif // else _WIN32 #endif // else _WIN32

View File

@ -28,7 +28,7 @@ class cIsThread
protected: protected:
virtual void Execute(void) = 0; // This function is called in the new thread's context virtual void Execute(void) = 0; // This function is called in the new thread's context
volatile bool mShouldTerminate; // The overriden Execute() method should check this periodically and terminate if this is true volatile bool m_ShouldTerminate; // The overriden Execute() method should check this periodically and terminate if this is true
public: public:
cIsThread(const AString & iThreadName); cIsThread(const AString & iThreadName);
@ -40,26 +40,26 @@ public:
static unsigned long GetCurrentID(void); // Returns the OS-dependent thread ID for the caller's thread static unsigned long GetCurrentID(void); // Returns the OS-dependent thread ID for the caller's thread
private: private:
AString mThreadName; AString m_ThreadName;
#ifdef _WIN32 #ifdef _WIN32
HANDLE mHandle; HANDLE m_Handle;
static DWORD_PTR __stdcall thrExecute(LPVOID iParam) static DWORD_PTR __stdcall thrExecute(LPVOID a_Param)
{ {
((cIsThread *)iParam)->Execute(); ((cIsThread *)a_Param)->Execute();
return 0; return 0;
} }
#else // _WIN32 #else // _WIN32
pthread_t mHandle; pthread_t m_Handle;
bool mHasStarted; bool m_HasStarted;
static void * thrExecute(void * iParam) static void * thrExecute(void * a_Param)
{ {
((cIsThread *)iParam)->Execute(); ((cIsThread *)a_Param)->Execute();
return NULL; return NULL;
} }

View File

@ -666,7 +666,7 @@ cServer::cNotifyWriteThread::cNotifyWriteThread(void) :
cServer::cNotifyWriteThread::~cNotifyWriteThread() cServer::cNotifyWriteThread::~cNotifyWriteThread()
{ {
mShouldTerminate = true; m_ShouldTerminate = true;
m_Event.Set(); m_Event.Set();
Wait(); Wait();
} }
@ -688,14 +688,14 @@ bool cServer::cNotifyWriteThread::Start(cServer * a_Server)
void cServer::cNotifyWriteThread::Execute(void) void cServer::cNotifyWriteThread::Execute(void)
{ {
cClientHandleList Clients; cClientHandleList Clients;
while (!mShouldTerminate) while (!m_ShouldTerminate)
{ {
cCSLock Lock(m_CS); cCSLock Lock(m_CS);
while (m_Clients.size() == 0) while (m_Clients.size() == 0)
{ {
cCSUnlock Unlock(Lock); cCSUnlock Unlock(Lock);
m_Event.Wait(); m_Event.Wait();
if (mShouldTerminate) if (m_ShouldTerminate)
{ {
return; return;
} }

View File

@ -155,7 +155,8 @@ void cSocketThreads::Write(const cSocket * a_Socket, const AString & a_Data)
} }
} // for itr - m_Threads[] } // for itr - m_Threads[]
ASSERT(!"Writing to an unknown socket"); // This may be perfectly legal, if the socket has been destroyed and the client is finishing up
// ASSERT(!"Writing to an unknown socket");
} }
@ -224,7 +225,7 @@ cSocketThreads::cSocketThread::cSocketThread(cSocketThreads * a_Parent) :
cSocketThreads::cSocketThread::~cSocketThread() cSocketThreads::cSocketThread::~cSocketThread()
{ {
mShouldTerminate = true; m_ShouldTerminate = true;
m_ControlSocket1.CloseSocket(); m_ControlSocket1.CloseSocket();
m_ControlSocket2.CloseSocket(); m_ControlSocket2.CloseSocket();
} }
@ -506,7 +507,7 @@ void cSocketThreads::cSocketThread::Execute(void)
} }
// The main thread loop: // The main thread loop:
while (!mShouldTerminate) while (!m_ShouldTerminate)
{ {
// Put all sockets into the Read set: // Put all sockets into the Read set:
fd_set fdRead; fd_set fdRead;

View File

@ -113,7 +113,7 @@ protected:
for (int i = 0; i < 20; i++) for (int i = 0; i < 20; i++)
{ {
cSleep::MilliSleep(100); cSleep::MilliSleep(100);
if (mShouldTerminate) if (m_ShouldTerminate)
{ {
return; return;
} }