mirror of
https://github.com/SWG-Source/src.git
synced 2026-08-01 01:16:03 -04:00
Added ChatServer and soePlatform
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#ifndef BASE_LINUX_ARCHIVE_H
|
||||
#define BASE_LINUX_ARCHIVE_H
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
#ifdef PACK_BIG_ENDIAN
|
||||
|
||||
inline double byteSwap(double value) { byteReverse(&value); return value; }
|
||||
inline float byteSwap(float value) { byteReverse(&value); return value; }
|
||||
inline uint64 byteSwap(uint64 value) { byteReverse(&value); return value; }
|
||||
inline int64 byteSwap(int64 value) { byteReverse(&value); return value; }
|
||||
inline uint32 byteSwap(uint32 value) { byteReverse(&value); return value; }
|
||||
inline int32 byteSwap(int32 value) { byteReverse(&value); return value; }
|
||||
inline uint16 byteSwap(uint16 value) { byteReverse(&value); return value; }
|
||||
inline int16 byteSwap(int16 value) { byteReverse(&value); return value; }
|
||||
|
||||
#else
|
||||
|
||||
inline double byteSwap(double value) { return value; }
|
||||
inline float byteSwap(float value) { return value; }
|
||||
inline uint64 byteSwap(uint64 value) { return value; }
|
||||
inline int64 byteSwap(int64 value) { return value; }
|
||||
inline uint32 byteSwap(uint32 value) { return value; }
|
||||
inline int32 byteSwap(int32 value) { return value; }
|
||||
inline uint16 byteSwap(uint16 value) { return value; }
|
||||
inline int16 byteSwap(int16 value) { return value; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
#include "../BlockAllocator.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
BlockAllocator::BlockAllocator()
|
||||
{
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
m_blocks[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BlockAllocator::~BlockAllocator()
|
||||
{
|
||||
// free all allocated memory blocks
|
||||
for(unsigned i = 0; i < 31; i++)
|
||||
{
|
||||
while(m_blocks[i] != NULL)
|
||||
{
|
||||
unsigned *tmp = m_blocks[i];
|
||||
m_blocks[i] = (unsigned *)*m_blocks[i];
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a block that is the next power of two greater than the # of bytes passed.
|
||||
// 33 bytes yields a 64 byte block of memory and so forth.
|
||||
|
||||
void *BlockAllocator::getBlock(unsigned bytes)
|
||||
{
|
||||
unsigned accum = 16, bits = 16;
|
||||
unsigned *handle = NULL;
|
||||
|
||||
// Perform a binary search looking for the highest bit.
|
||||
|
||||
while(bits != 0)
|
||||
{
|
||||
// If bytes is less than the bit we're testing for, subtract half
|
||||
// from the bit value and repeat
|
||||
if(bytes < (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum -= bits;
|
||||
}
|
||||
// If bytes is greater than the bit we're testing for, add half
|
||||
// from the but value and repeat
|
||||
else if(bytes > (unsigned)(1 << accum))
|
||||
{
|
||||
bits /= 2;
|
||||
accum += bits;
|
||||
}
|
||||
// Got lucky and hit the value dead on
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At this point accum contains the most significant bit index, increment
|
||||
accum++;
|
||||
if(accum < 2)
|
||||
{
|
||||
accum = 2;
|
||||
}
|
||||
|
||||
// Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front
|
||||
// The first integer is the address of the next block of memory when the block is in the allocator
|
||||
// The second integer is the bit length of the block
|
||||
// Memory is allocated on 4 byte boundaries to sidestep byte alignment problems
|
||||
|
||||
|
||||
// Check if the allocator already has a block of that size
|
||||
if(m_blocks[accum] == 0)
|
||||
{
|
||||
// remove the pre allocated block from the linked list
|
||||
handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned));
|
||||
handle[1] = accum;
|
||||
handle[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate a new block
|
||||
handle = m_blocks[accum];
|
||||
m_blocks[accum] = (unsigned *)handle[0];
|
||||
handle[0] = 0;
|
||||
}
|
||||
// return a pointer that skips over the header used for the allocator's purposes
|
||||
return(handle + 2);
|
||||
}
|
||||
|
||||
void BlockAllocator::returnBlock(unsigned *handle)
|
||||
{
|
||||
// C++ allows for safe deletion of a NULL pointer
|
||||
if(handle)
|
||||
{
|
||||
// Update the allocator linked list, insert this entry at the head
|
||||
*(handle - 2) = (unsigned)m_blocks[*(handle - 1)];
|
||||
// Add this entry to the proper linked list node
|
||||
m_blocks[*(handle - 1)] = (handle - 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
////////////////////////////////////////
|
||||
// Event.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CEvent class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CEvent::CEvent() :
|
||||
mMutex(),
|
||||
mCond(),
|
||||
mThreadCount(0)
|
||||
{
|
||||
pthread_mutex_init(&mMutex, NULL);
|
||||
pthread_cond_init(&mCond, NULL);
|
||||
}
|
||||
|
||||
CEvent::~CEvent()
|
||||
{
|
||||
pthread_cond_destroy(&mCond);
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
bool CEvent::Signal()
|
||||
{
|
||||
pthread_mutex_lock(&mMutex);
|
||||
if (mThreadCount == 0)
|
||||
mThreadCount = SIGNALED;
|
||||
pthread_cond_signal(&mCond);
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 CEvent::Wait(uint32 timeout)
|
||||
{
|
||||
int result;
|
||||
|
||||
pthread_mutex_lock(&mMutex);
|
||||
if (mThreadCount == SIGNALED)
|
||||
{
|
||||
mThreadCount = 0;
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
return eWAIT_SIGNAL;
|
||||
}
|
||||
|
||||
if (!timeout)
|
||||
{
|
||||
mThreadCount++;
|
||||
result = pthread_cond_wait(&mCond, &mMutex);
|
||||
mThreadCount--;
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct timeval now;
|
||||
struct timespec abs_timeout;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
abs_timeout.tv_sec = now.tv_sec + timeout/1000;
|
||||
abs_timeout.tv_nsec = now.tv_usec * 1000 + (timeout%1000)*1000000;
|
||||
abs_timeout.tv_sec += abs_timeout.tv_nsec / 1000000000;
|
||||
abs_timeout.tv_nsec %= 1000000000;
|
||||
|
||||
mThreadCount++;
|
||||
result = pthread_cond_timedwait(&mCond, &mMutex, &abs_timeout);
|
||||
mThreadCount--;
|
||||
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
|
||||
if (result == 0 || result == EINTR)
|
||||
return eWAIT_SIGNAL;
|
||||
else if (result == ETIMEDOUT)
|
||||
return eWAIT_TIMEOUT;
|
||||
else
|
||||
return eWAIT_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,74 @@
|
||||
////////////////////////////////////////
|
||||
// Event.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CEvent class that encapsulates the functionality of a
|
||||
// single-locking semaphore.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_EVENT_H
|
||||
#define BASE_LINUX_EVENT_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CEvent
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a singal-locking semaphore.
|
||||
// This class is valuable for thread syncronization when a thead's
|
||||
// execution needs to be dependent upon another thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// Signal() : Signals a thread that has called Wait() so that it can
|
||||
// continue execution. This function returns true if the waiting
|
||||
// thread was signalled successfully, otherwise false is returned.
|
||||
// Wait() : Halts the calling thread's execution indefinately until
|
||||
// a Singal() call is made by an external thread. If the thread is
|
||||
// successfully signalled, the function returns eWAIT_SIGNAL. If
|
||||
// timeout period expires without a signal, eWAIT_TIMEOUT is returned.
|
||||
// If the function fails, eWAIT_ERROR is returned.
|
||||
//
|
||||
class CEvent
|
||||
{
|
||||
public:
|
||||
CEvent();
|
||||
virtual ~CEvent();
|
||||
|
||||
bool Signal();
|
||||
int32 Wait(uint32 timeout = 0);
|
||||
|
||||
public:
|
||||
enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT };
|
||||
enum { SIGNALED = -1 };
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
pthread_cond_t mCond;
|
||||
int mThreadCount;
|
||||
};
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_LINUX_EVENT_H
|
||||
@@ -0,0 +1,40 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CMutex class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
CMutex::CMutex()
|
||||
{
|
||||
mInitialized = (pthread_mutex_init(&mMutex, 0) == 0);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,79 @@
|
||||
////////////////////////////////////////
|
||||
// Mutex.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CMutex class that encapsulates the functionality of a
|
||||
// mutually-exclusive device.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_MUTEX_H
|
||||
#define BASE_LINUX_MUTEX_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CMutex
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates the functionality of a mutually-exclusive device.
|
||||
// This class is valuable for protecting against race conditions
|
||||
// within threaded applications. The CMutex class can be used to
|
||||
// only allow a single thread to run within a specified code
|
||||
// segment at a time.
|
||||
//
|
||||
// Public Methods:
|
||||
// Lock() : Locks the mutex. If the mutex is already locked, the
|
||||
// operating system will block the calling thread until another
|
||||
// thread has unlocked the mutex.
|
||||
// Unlock() : Unlocks the mutex.
|
||||
//
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void Lock();
|
||||
void Unlock();
|
||||
private:
|
||||
pthread_mutex_t mMutex;
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
inline void CMutex::Lock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
|
||||
inline void CMutex::Unlock(void)
|
||||
{
|
||||
if (mInitialized)
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_MT)
|
||||
|
||||
#endif // BASE_LINUX_MUTEX_H
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the global functionality declaired in Platform.h.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#include <ctype.h>
|
||||
#include "Platform.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
// Implementation of microsoft strlwr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void strlwr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of microsoft strlwr extension
|
||||
// This non-ANSI function is not supported under UNIX
|
||||
void strupr(char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CTimer::CTimer() :
|
||||
mTimer(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
////////////////////////////////////////
|
||||
// Platform.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Include relevent system headers that are platform specific.
|
||||
// 2. Declair global platform specific functionality.
|
||||
// 3. Include primative type definitions
|
||||
//
|
||||
// Global Functions:
|
||||
// getTimer() : Return the current high resolution clock count.
|
||||
// getTimerFrequency() : Return the frequency of the high resolution clock.
|
||||
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
|
||||
// specified number of milliseconds.
|
||||
// strlwr() : Alters the contents of a string, making it all lower-case.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_PLATFORM_H
|
||||
#define BASE_LINUX_PLATFORM_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/errno.h>
|
||||
#include <pthread.h>
|
||||
#include <resolv.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
uint64 getTimer(void);
|
||||
uint64 getTimerFrequency(void);
|
||||
void sleep(uint32 ms);
|
||||
|
||||
inline uint64 getTimer(void)
|
||||
{
|
||||
uint64 t;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
t = tv.tv_sec;
|
||||
t = t * 1000000;
|
||||
t += tv.tv_usec;
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64 getTimerFrequency(void)
|
||||
{
|
||||
uint64 f = 1000000;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline void sleep(uint32 ms)
|
||||
{
|
||||
usleep(static_cast<unsigned long>(ms * 1000));
|
||||
}
|
||||
|
||||
void strlwr(char * s);
|
||||
void strupr(char * s);
|
||||
|
||||
|
||||
class CTimer
|
||||
{
|
||||
public:
|
||||
CTimer();
|
||||
|
||||
void Set(uint32 seconds);
|
||||
void Signal();
|
||||
bool Expired();
|
||||
|
||||
private:
|
||||
uint32 mTimer;
|
||||
};
|
||||
|
||||
inline void CTimer::Set(uint32 interval)
|
||||
{
|
||||
mTimer = (uint32)time(0) + interval;
|
||||
}
|
||||
|
||||
inline void CTimer::Signal()
|
||||
{
|
||||
mTimer = 0;
|
||||
}
|
||||
|
||||
inline bool CTimer::Expired()
|
||||
{
|
||||
return (mTimer <= (uint32)time(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // BASE_LINUX_PLATFORM_H
|
||||
@@ -0,0 +1,299 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.cpp
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Implementation of the CThread class.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#if defined(_REENTRANT)
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include "Thread.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
void *threadProc(void *threadPtr)
|
||||
{
|
||||
CThread &thread = *((CThread*)threadPtr);
|
||||
thread.mThreadActive = true;
|
||||
thread.ThreadProc();
|
||||
thread.mThreadActive = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CThread::CThread()
|
||||
{
|
||||
mThreadID = 0;
|
||||
mThreadActive = false;
|
||||
mThreadContinue = false;
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
StopThread();
|
||||
}
|
||||
|
||||
void CThread::StartThread()
|
||||
{
|
||||
mThreadContinue = true;
|
||||
if (pthread_create(&mThreadID,0,threadProc,this) == 0)
|
||||
pthread_detach(mThreadID);
|
||||
while (!IsThreadActive())
|
||||
Base::sleep(1);
|
||||
}
|
||||
|
||||
int32 CThread::StopThread(int timeout)
|
||||
{
|
||||
timeout += time(0);
|
||||
|
||||
mThreadContinue = false;
|
||||
while (mThreadActive && time(0)<timeout)
|
||||
sleep(1);
|
||||
if (mThreadActive)
|
||||
{
|
||||
mThreadActive = false;
|
||||
return eSTOP_TIMEOUT;
|
||||
}
|
||||
return eSTOP_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CMember::CMember(CThreadPool * parent) :
|
||||
mParent(parent),
|
||||
mFunction(NULL),
|
||||
mArgument(NULL),
|
||||
mSemaphore()
|
||||
{
|
||||
StartThread();
|
||||
}
|
||||
|
||||
CThreadPool::CMember::~CMember()
|
||||
{
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::Destroy()
|
||||
{
|
||||
mThreadContinue = false;
|
||||
mSemaphore.Signal();
|
||||
}
|
||||
|
||||
bool CThreadPool::CMember::Execute(void( *function )( void * ), void * arg)
|
||||
{
|
||||
if (mFunction)
|
||||
return false;
|
||||
|
||||
mArgument = arg;
|
||||
mFunction = function;
|
||||
mSemaphore.Signal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CThreadPool::CMember::ThreadProc()
|
||||
{
|
||||
mParent->OnStartup(this);
|
||||
while (mThreadContinue)
|
||||
{
|
||||
mParent->OnIdle(this);
|
||||
mSemaphore.Wait(mParent->GetTimeOut()*1000);
|
||||
|
||||
if (mFunction)
|
||||
{
|
||||
mFunction(mArgument);
|
||||
mArgument = NULL;
|
||||
mFunction = NULL;
|
||||
}
|
||||
else if (mParent->OnDestory(this))
|
||||
mThreadContinue = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) :
|
||||
mMutex(),
|
||||
mIdleMember(),
|
||||
mBusyMember(),
|
||||
mNullMember(),
|
||||
mThreadCount(0),
|
||||
mMaxThreads(maxThreads),
|
||||
mMinThreads(minThreads),
|
||||
mTimeOut(timeout)
|
||||
{
|
||||
if (mMaxThreads == 0) mMaxThreads = 1;
|
||||
if (mMinThreads == 0) mMinThreads = 1;
|
||||
if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads;
|
||||
|
||||
for (uint32 i=0; i<mMinThreads; i++)
|
||||
new CMember(this);
|
||||
}
|
||||
|
||||
CThreadPool::~CThreadPool()
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) Destory all busy member threads
|
||||
mMutex.Lock();
|
||||
setIterator = mBusyMember.begin();
|
||||
while (setIterator != mBusyMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Destory all idle member threads
|
||||
while (mThreadCount)
|
||||
{
|
||||
mMutex.Lock();
|
||||
setIterator = mIdleMember.begin();
|
||||
while (setIterator != mIdleMember.end())
|
||||
(*setIterator++)->Destroy();
|
||||
mMutex.Unlock();
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Delete the null member threads
|
||||
mMutex.Lock();
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::Execute(void( *function )( void * ), void * arg, uint32 poolGrowthSize )
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
////////////////////////////////////////
|
||||
// (1) If no idle members, return false to indicate that no threads
|
||||
// were available. If the thread count is below the max, create
|
||||
// a new thread.
|
||||
if (mIdleMember.empty())
|
||||
{
|
||||
if (mThreadCount < mMaxThreads)
|
||||
{
|
||||
if (!poolGrowthSize)
|
||||
poolGrowthSize = mMinThreads;
|
||||
|
||||
if ((mThreadCount + poolGrowthSize) > mMaxThreads)
|
||||
poolGrowthSize = mMaxThreads - mThreadCount;
|
||||
|
||||
for (uint32 i(0); i < poolGrowthSize; i++)
|
||||
new CMember(this);
|
||||
mMutex.Unlock();
|
||||
time_t idleTimeout = time(0) + 5;
|
||||
while(mIdleMember.empty())
|
||||
{
|
||||
if (time(0) >= idleTimeout)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Base::sleep(10);
|
||||
}
|
||||
mMutex.Lock();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (2) Delete any null member threads.
|
||||
while (!mNullMember.empty())
|
||||
{
|
||||
delete mNullMember.front();
|
||||
mNullMember.pop_front();
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// (3) Move the first idle thread to the busy set and signal the
|
||||
// thread to execute the specified function.
|
||||
CMember * member = *(mIdleMember.begin());
|
||||
mIdleMember.erase(member);
|
||||
mBusyMember.insert(member);
|
||||
member->Execute(function,arg);
|
||||
|
||||
mMutex.Unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 CThreadPool::GetTimeOut()
|
||||
{
|
||||
return mTimeOut;
|
||||
}
|
||||
|
||||
void CThreadPool::OnStartup(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mThreadCount++;
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
void CThreadPool::OnIdle(CMember * member)
|
||||
{
|
||||
mMutex.Lock();
|
||||
|
||||
mBusyMember.erase(member);
|
||||
mIdleMember.insert(member);
|
||||
|
||||
mMutex.Unlock();
|
||||
}
|
||||
|
||||
bool CThreadPool::OnDestory(CMember * member)
|
||||
{
|
||||
set<CMember *>::iterator setIterator;
|
||||
|
||||
mMutex.Lock();
|
||||
|
||||
bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end();
|
||||
if (result)
|
||||
{
|
||||
mNullMember.push_back(member);
|
||||
mIdleMember.erase(setIterator);
|
||||
mThreadCount--;
|
||||
}
|
||||
|
||||
mMutex.Unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
@@ -0,0 +1,146 @@
|
||||
////////////////////////////////////////
|
||||
// Thread.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Declair the CThread class that encapsulates threading functionality.
|
||||
// This abstract base class in intended to be used to encapsulate
|
||||
// individual tasks that require threading in derived classes.
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_THREAD_H
|
||||
#define BASE_LINUX_THREAD_H
|
||||
|
||||
#if !defined(_REENTRANT)
|
||||
# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_REENTRANT)" )
|
||||
#else
|
||||
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "Platform.h"
|
||||
#include "Mutex.h"
|
||||
#include "Event.h"
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// Class:
|
||||
// CThread
|
||||
//
|
||||
// Purpose:
|
||||
// Encapsulates threading functionality. Creating classes derived
|
||||
// from CThread provides an easy way to encapsulate tasks that require
|
||||
// their own thread.
|
||||
//
|
||||
// Public Methods:
|
||||
// StartThread() : Creates the low-level thread handle and begins executing
|
||||
// the CThread::ThreadProc() function within the new thread.
|
||||
// StopThread() : Signals the ThreadProc() function to stop executing using
|
||||
// the mThreadContinue member variable, and waits for the ThreadProc()
|
||||
// function to exit. By default, the function will block for a maximum
|
||||
// of 5 seconds before exiting without the thread halting.
|
||||
// IsThreadActive() : Returns true if the physical thread is still executing
|
||||
// within the ThreadProc() function, otherwise it returns false.
|
||||
// ThreadProc() : Pure-virtual function that will be executed when the StartThread()
|
||||
// function is called. Derived classes must implement this function. The
|
||||
// mThreadContinue member variable should be used internal the the ThreadProc()
|
||||
// function to indicate whether it should continue executing or exit.
|
||||
// Protected Attributes:
|
||||
// mThreadContinue : Boolean value indicating to the ThreadProc() function
|
||||
// whether to continue executing or to exit. If mThreadContinue is true,
|
||||
// ThreadProc() should continue, otherwise ThreadProc() should exit. It
|
||||
// left up to the derived class to implement a ThreadProc() function that
|
||||
// uses the mThreadContinue member.
|
||||
//
|
||||
//
|
||||
class CThread
|
||||
{
|
||||
friend void * threadProc(void *);
|
||||
|
||||
public:
|
||||
enum { eSTOP_SUCCESS, eSTOP_TIMEOUT };
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
void StartThread();
|
||||
int32 StopThread(int timeout=5);
|
||||
bool IsThreadActive() { return mThreadActive; }
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc() {}
|
||||
|
||||
protected:
|
||||
bool mThreadContinue;
|
||||
private:
|
||||
pthread_t mThreadID;
|
||||
bool mThreadActive;
|
||||
};
|
||||
|
||||
|
||||
class CThreadPool
|
||||
{
|
||||
private:
|
||||
class CMember : public CThread
|
||||
{
|
||||
public:
|
||||
CMember(CThreadPool * parent);
|
||||
virtual ~CMember();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual void ThreadProc();
|
||||
|
||||
private:
|
||||
CThreadPool * mParent;
|
||||
void( * mFunction )( void * );
|
||||
void * mArgument;
|
||||
CEvent mSemaphore;
|
||||
};
|
||||
friend class CMember;
|
||||
|
||||
public:
|
||||
CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60);
|
||||
virtual ~CThreadPool();
|
||||
|
||||
virtual bool Execute(void( *function )( void * ), void * arg, uint32 poolGrowthSize = 0);
|
||||
|
||||
private:
|
||||
uint32 GetTimeOut();
|
||||
void OnStartup(CMember * member);
|
||||
void OnIdle(CMember * member);
|
||||
bool OnDestory(CMember * member);
|
||||
|
||||
private:
|
||||
CMutex mMutex;
|
||||
std::set<CMember *> mIdleMember;
|
||||
std::set<CMember *> mBusyMember;
|
||||
std::list<CMember *> mNullMember;
|
||||
uint32 mThreadCount;
|
||||
|
||||
uint32 mMaxThreads;
|
||||
uint32 mMinThreads;
|
||||
uint32 mTimeOut;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // #if defined(_REENTRANT)
|
||||
|
||||
#endif // BASE_LINUX_THREAD_H
|
||||
@@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////
|
||||
// Types.h
|
||||
//
|
||||
// Purpose:
|
||||
// 1. Define integer types that are unambiguous with respect to size
|
||||
//
|
||||
// Revisions:
|
||||
// 07/10/2001 Created
|
||||
//
|
||||
|
||||
#ifndef BASE_LINUX_TYPES_H
|
||||
#define BASE_LINUX_TYPES_H
|
||||
|
||||
#include <sys/bitypes.h>
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
namespace Base
|
||||
{
|
||||
#define INT32_MAX 0x7FFFFFFF
|
||||
#define INT32_MIN 0x80000000
|
||||
#define UINT32_MAX 0xFFFFFFFF
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
typedef int32_t int32;
|
||||
typedef u_int32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef u_int64_t uint64;
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
#endif // BASE_LINUX_TYPES_H
|
||||
|
||||
Reference in New Issue
Block a user