Added platform libs

This commit is contained in:
Anonymous
2014-01-16 07:25:50 -07:00
parent 202d7d1de3
commit 77c2b5f6bc
92 changed files with 16139 additions and 2 deletions
@@ -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
+103
View File
@@ -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)
+74
View File
@@ -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
};
+199
View File
@@ -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)
+79
View File
@@ -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)
+146
View File
@@ -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
+42
View File
@@ -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