mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-09-12 22:45:02 -04:00
Added platform libs
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
|
||||
@@ -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,390 @@
|
||||
#include "../Logger.h"
|
||||
#include "Mutex.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
|
||||
#endif
|
||||
namespace Base
|
||||
{
|
||||
|
||||
const char file_sep = '/';
|
||||
|
||||
Logger::Logger(const char *prefix, int level, unsigned size, bool rollDate)
|
||||
: m_defaultLevel(level), m_defaultSize(size), m_dirPrefix(prefix), m_rollDate(rollDate)
|
||||
{
|
||||
char buf[1024];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
time_t t = time(NULL);
|
||||
localtime_r(&t, &now);
|
||||
|
||||
memcpy(&m_lastDateTime, &now, sizeof(tm));
|
||||
if(m_rollDate)
|
||||
{
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf, "%s", m_dirPrefix.c_str());
|
||||
}
|
||||
logDir = fopen(buf, "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
|
||||
}
|
||||
m_logTable.clear();
|
||||
}
|
||||
|
||||
void Logger::flush(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::flushAll()
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
LogInfo *info = (*iter).second;
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = size;
|
||||
newLog->last = 0;
|
||||
newLog->level = level;
|
||||
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---=== Log Started ===---");
|
||||
}
|
||||
|
||||
void Logger::addLog(const char *id, unsigned logenum)
|
||||
{
|
||||
LogInfo *newLog = new LogInfo;
|
||||
newLog->filename = m_logPrefix + file_sep + id + ".log";
|
||||
newLog->name = id;
|
||||
newLog->used = 0;
|
||||
newLog->max = m_defaultSize;
|
||||
newLog->last = 0;
|
||||
newLog->level = m_defaultLevel;
|
||||
|
||||
m_logTable.insert(pair<unsigned, LogInfo *>(logenum, newLog));
|
||||
|
||||
if(strcmp("stdout", id) == 0)
|
||||
{
|
||||
newLog->file = stdout;
|
||||
}
|
||||
else if(strcmp("stderr", id) == 0)
|
||||
{
|
||||
newLog->file = stderr;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog->file = fopen(newLog->filename.c_str(), "a+");
|
||||
}
|
||||
log(logenum, LOG_FILEONLY, "---===Log Started ===---");
|
||||
}
|
||||
|
||||
void Logger::updateLog(unsigned logenum, int level, unsigned size)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
(*iter).second->level = level;
|
||||
(*iter).second->max = size;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::removeLog(unsigned logenum)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
log((*iter).first, LOG_ALWAYS, "---=== Log Stopped ===---");
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
delete((*iter).second);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::logSimple(unsigned logenum, int level, const char *message)
|
||||
{
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
memcpy(&info->ts, localtime(&t), sizeof(tm));
|
||||
info->last = t;
|
||||
}
|
||||
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
|
||||
info->used += tmp;
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, message);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Logger::log(unsigned logenum, int level, const char *message, ...)
|
||||
{
|
||||
char buf[2048];
|
||||
va_list varg;
|
||||
va_start(varg, message);
|
||||
vsnprintf(buf, 2047, message, varg);
|
||||
buf[2047] = 0;
|
||||
va_end(varg);
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter = m_logTable.find(logenum);
|
||||
if(iter == m_logTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
LogInfo *info = (*iter).second;
|
||||
if(level >= info->level)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(info->last != t)
|
||||
{
|
||||
localtime_r(&t, &info->ts);
|
||||
info->last = t;
|
||||
}
|
||||
if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Lock();
|
||||
#endif
|
||||
if(info->ts.tm_mday != m_lastDateTime.tm_mday)
|
||||
{
|
||||
memcpy(&m_lastDateTime, &info->ts, sizeof(tm));
|
||||
rollDate(t);
|
||||
}
|
||||
#if defined(_REENTRANT)
|
||||
rLock.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
if(iter != m_logTable.end())
|
||||
{
|
||||
if(info->max > 0)
|
||||
{
|
||||
int tmp = fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
|
||||
info->used += tmp;
|
||||
if(info->used > info->max)
|
||||
{
|
||||
fflush(info->file);
|
||||
info->used = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(info->file, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] %s\n", (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec, buf);
|
||||
fflush(info->file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::rollDate(time_t t)
|
||||
{
|
||||
char buf[80];
|
||||
FILE *logDir = NULL;
|
||||
|
||||
logDir = fopen(m_dirPrefix.c_str(), "r+");
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(m_dirPrefix.c_str(), 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
|
||||
tm now;
|
||||
localtime_r(&t, &now);
|
||||
|
||||
sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100));
|
||||
logDir = fopen(buf, "r+");
|
||||
|
||||
if(errno == ENOENT)
|
||||
{
|
||||
cmkdir(buf, 0755);
|
||||
}
|
||||
else if(logDir != NULL)
|
||||
{
|
||||
fclose(logDir);
|
||||
}
|
||||
m_logPrefix = buf;
|
||||
|
||||
map<unsigned, LogInfo *>::iterator iter;
|
||||
for(iter = m_logTable.begin(); iter != m_logTable.end(); iter++)
|
||||
{
|
||||
(*iter).second->filename = m_logPrefix + file_sep + (*iter).second->name.c_str() + ".log";
|
||||
fflush((*iter).second->file);
|
||||
fclose((*iter).second->file);
|
||||
(*iter).second->file = fopen((*iter).second->filename.c_str(), "a+");
|
||||
memcpy(&((*iter).second->ts), &now, sizeof(tm));
|
||||
}
|
||||
}
|
||||
|
||||
// mkdir function that creates intermediate directories
|
||||
void Logger::cmkdir(const char *dir, int mode)
|
||||
{
|
||||
char dirbuf[128];
|
||||
strncpy(dirbuf, dir, 127);
|
||||
dirbuf[127] = 0;
|
||||
char *j = dirbuf, *i = dirbuf;
|
||||
int handle;
|
||||
|
||||
while(*i)
|
||||
{
|
||||
if(*i == file_sep)
|
||||
{
|
||||
(*i) = 0;
|
||||
// handle = open(j, O_EXCL); // Ben's original code
|
||||
// if((handle > 0) || (errno != EISDIR && errno != ENOENT))
|
||||
// {
|
||||
// perror("Logger::cmkdir():");
|
||||
// abort();
|
||||
// }
|
||||
|
||||
// This doesnt work under Linux, it returns a valid handle
|
||||
// Instead: see if file exists. If it doesnt, create directory ok
|
||||
// If it exists, do stat to see if it is a dir.
|
||||
// If it is a dir, then ok, create the directory.
|
||||
// If it is a file, error
|
||||
// ging 9-16-2002
|
||||
|
||||
handle = open(j, O_RDONLY);
|
||||
if (handle > 0)
|
||||
{
|
||||
struct stat stat_buffer;
|
||||
int ret = fstat(handle,&stat_buffer);
|
||||
if ((ret == -1) || ((stat_buffer.st_mode | S_IFDIR) == 0))
|
||||
{
|
||||
perror("Logger::cmkdir():");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
mkdir(j, mode);
|
||||
close(handle);
|
||||
(*i) = file_sep;
|
||||
}
|
||||
else if(*(i + 1) == 0)
|
||||
{
|
||||
mkdir(j, mode);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,199 @@
|
||||
# environment variables:
|
||||
# $INCLUDE_PATH is a colon-delimited list of include directories
|
||||
|
||||
EMPTY_CHAR=
|
||||
SPACE_CHAR=$(empty) $(empty)
|
||||
COLON_CHAR=:
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
OUTPUT_FILE_ST=libBase.a
|
||||
OUTPUT_FILE_MT=libBase_MT.a
|
||||
OUTPUT_DIR=../../../lib
|
||||
OBJECT_DIR_ST=./obj_st
|
||||
OBJECT_DIR_MT=./obj_mt
|
||||
|
||||
STL_HOME=../../../../stlport453
|
||||
|
||||
INCLUDE_DIRS=.. ../ $(STL_HOME)/stlport
|
||||
|
||||
SOURCE_DIRS=. ..
|
||||
SOURCE_FILES=
|
||||
|
||||
LIBRARY_DIRS=
|
||||
LIBRARY_FILES=
|
||||
|
||||
CFLAGS_USER=
|
||||
LFLAGS_USER=
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
INCLUDE_DIR_LIST=$(subst $(COLON_CHAR),$(SPACE_CHAR),$(INCLUDE_PATH)) $(INCLUDE_DIRS)
|
||||
INCLUDE_FLAGS=$(addprefix -I,$(INCLUDE_DIR_LIST))
|
||||
CFLAGS_ST=$(INCLUDE_FLAGS) $(CFLAGS_USER) -D_GNU_SOURCE -Wall -Wno-unknown-pragmas
|
||||
CFLAGS_MT=$(INCLUDE_FLAGS) $(CFLAGS_USER) -D_GNU_SOURCE -D_REENTRANT -Wall -Wno-unknown-pragmas
|
||||
CFLAGS_DEBUG_ST=$(CFLAGS_ST) -D_DEBUG -g
|
||||
CFLAGS_RELEASE_ST=$(CFLAGS_ST) -DNDEBUG -O2
|
||||
CFLAGS_DEBUG_MT=$(CFLAGS_MT) -D_DEBUG -g
|
||||
CFLAGS_RELEASE_MT=$(CFLAGS_MT) -DNDEBUG -O2
|
||||
|
||||
LIBRARY_FLAGS=$(addprefix -l,$(LIBRARIES))
|
||||
LFLAGS=$(LIBRARY_FLAGS) $(LFLAGS_USER) -r
|
||||
LFLAGS_DEBUG=$(LFLAGS)
|
||||
LFLAGS_RELEASE=$(LFLAGS)
|
||||
|
||||
CPP=g++
|
||||
LINK=ld
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
DEBUG_OBJ_DIR_ST=$(OBJECT_DIR_ST)/debug
|
||||
RELEASE_OBJ_DIR_ST=$(OBJECT_DIR_ST)/release
|
||||
DEBUG_OBJ_DIR_MT=$(OBJECT_DIR_MT)/debug
|
||||
RELEASE_OBJ_DIR_MT=$(OBJECT_DIR_MT)/release
|
||||
|
||||
DEBUG_DIR=$(OUTPUT_DIR)/debug
|
||||
RELEASE_DIR=$(OUTPUT_DIR)/release
|
||||
|
||||
FIND=$(shell ls $(x)/*.cpp)
|
||||
SOURCE_LIST = $(SOURCE_FILES) $(foreach x, $(SOURCE_DIRS), $(FIND))
|
||||
|
||||
DEBUG_OBJ_LIST_ST=$(addprefix $(DEBUG_OBJ_DIR_ST)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
RELEASE_OBJ_LIST_ST=$(addprefix $(RELEASE_OBJ_DIR_ST)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
DEBUG_OBJ_LIST_MT=$(addprefix $(DEBUG_OBJ_DIR_MT)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
RELEASE_OBJ_LIST_MT=$(addprefix $(RELEASE_OBJ_DIR_MT)/, $(notdir $(SOURCE_LIST:.cpp=.o)))
|
||||
|
||||
|
||||
DEPENDENCY_LIST = $(SOURCE_LIST:.cpp=.d)
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
release_st: echoRelease_st releaseDirs_st $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo Successfully built $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo
|
||||
|
||||
debug_st: debugDirs_st $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo Successfully built $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo
|
||||
|
||||
release_mt: echoRelease_mt releaseDirs_mt $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo Successfully built $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo
|
||||
|
||||
debug_mt: debugDirs_mt $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo Successfully built $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo
|
||||
|
||||
all: clean debug_st release_st debug_mt release_mt
|
||||
|
||||
all_st: clean debug_st release_st
|
||||
|
||||
all_mt: clean debug_mt release_mt
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
debugDirs_st :
|
||||
@mkdir -p $(DEBUG_OBJ_DIR_ST)
|
||||
@mkdir -p $(DEBUG_DIR)
|
||||
|
||||
$(DEBUG_OBJ_DIR_ST)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
$(CPP) $(CFLAGS_DEBUG_ST) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(DEBUG_DIR)/$(OUTPUT_FILE_ST): $(DEBUG_OBJ_LIST_ST)
|
||||
$(LINK) $(LFLAGS_DEBUG) -o $@ $(DEBUG_OBJ_LIST_ST)
|
||||
|
||||
|
||||
debugDirs_mt :
|
||||
@mkdir -p $(DEBUG_OBJ_DIR_MT)
|
||||
@mkdir -p $(DEBUG_DIR)
|
||||
|
||||
$(DEBUG_OBJ_DIR_MT)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
$(CPP) $(CFLAGS_DEBUG_MT) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(DEBUG_DIR)/$(OUTPUT_FILE_MT): $(DEBUG_OBJ_LIST_MT)
|
||||
$(LINK) $(LFLAGS_DEBUG) -o $@ $(DEBUG_OBJ_LIST_MT)
|
||||
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
echoRelease_st :
|
||||
@echo Building $(OUTPUT_FILE_ST)
|
||||
@echo compiler: $(CPP) $(CFLAGS_RELEASE_ST)
|
||||
@echo linker: $(LINK) $(LFLAGS_RELEASE)
|
||||
@echo
|
||||
|
||||
echoRelease_mt :
|
||||
@echo Building $(OUTPUT_FILE_MT)
|
||||
@echo compiler: $(CPP) $(CFLAGS_RELEASE_MT)
|
||||
@echo linker: $(LINK) $(LFLAGS_RELEASE)
|
||||
@echo
|
||||
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
releaseDirs_st :
|
||||
@mkdir -p $(RELEASE_OBJ_DIR_ST)
|
||||
@mkdir -p $(RELEASE_DIR)
|
||||
|
||||
$(RELEASE_OBJ_DIR_ST)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@echo compiling $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@$(CPP) $(CFLAGS_RELEASE_ST) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(RELEASE_DIR)/$(OUTPUT_FILE_ST): $(RELEASE_OBJ_LIST_ST)
|
||||
@echo linking $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@$(LINK) $(LFLAGS_RELEASE) -o $@ $(RELEASE_OBJ_LIST_ST)
|
||||
|
||||
releaseDirs_mt :
|
||||
@mkdir -p $(RELEASE_OBJ_DIR_MT)
|
||||
@mkdir -p $(RELEASE_DIR)
|
||||
|
||||
$(RELEASE_OBJ_DIR_MT)/%.o : $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@echo compiling $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
@$(CPP) $(CFLAGS_RELEASE_MT) -o $@ -c $(filter %/$(notdir $(basename $@)).cpp,$(SOURCE_LIST))
|
||||
|
||||
$(RELEASE_DIR)/$(OUTPUT_FILE_MT): $(RELEASE_OBJ_LIST_MT)
|
||||
@echo linking $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@$(LINK) $(LFLAGS_RELEASE) -o $@ $(RELEASE_OBJ_LIST_MT)
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
include .depend
|
||||
|
||||
.PHONY : $(DEPENDENCY_LIST)
|
||||
|
||||
depend: .depend $(DEPENDENCY_LIST)
|
||||
|
||||
.depend:
|
||||
touch .depend
|
||||
make depend
|
||||
|
||||
$(DEPENDENCY_LIST):
|
||||
@echo Generating dependencies for $(notdir $(@:.d=.cpp))
|
||||
@echo -n $(DEBUG_OBJ_DIR_ST)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp)>> .depend
|
||||
@echo -n $(DEBUG_OBJ_DIR_MT)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp) >> .depend
|
||||
@echo -n $(RELEASE_OBJ_DIR_ST)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp)>> .depend
|
||||
@echo -n $(RELEASE_OBJ_DIR_MT)/ >> .depend
|
||||
@$(CPP) -MM $(addprefix -I,$(INCLUDE_DIRS)) $(@:.d=.cpp) >> .depend
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
|
||||
clean:
|
||||
@echo removing "$(OBJECT_DIR_ST)/*.o"
|
||||
@rm -rf $(OBJECT_DIR_ST)
|
||||
@echo removing "$(OBJECT_DIR_MT)/*.o"
|
||||
@rm -rf $(OBJECT_DIR_MT)
|
||||
@echo removing $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@rm -f $(DEBUG_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo removing $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@rm -f $(RELEASE_DIR)/$(OUTPUT_FILE_ST)
|
||||
@echo removing $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f $(DEBUG_DIR)/$(OUTPUT_FILE_MT)
|
||||
@echo removing $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f $(RELEASE_DIR)/$(OUTPUT_FILE_MT)
|
||||
@rm -f .depend
|
||||
@echo
|
||||
|
||||
|
||||
@@ -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,274 @@
|
||||
////////////////////////////////////////
|
||||
// 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;
|
||||
pthread_create(&mThreadID,0,threadProc,this);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
new CMember(this);
|
||||
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);
|
||||
~CThreadPool();
|
||||
|
||||
bool Execute(void( *function )( void * ), void * arg);
|
||||
|
||||
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