added methods to CLog for getting the outputter, getting and
setting the priority filter, and added code for thread safety. added code to apps to enable thread safety in CLog.
This commit is contained in:
parent
70f5f9491d
commit
536eb52337
|
@ -9,7 +9,6 @@
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int g_maxPriority = -1;
|
|
||||||
static const char* g_priority[] = {
|
static const char* g_priority[] = {
|
||||||
"FATAL",
|
"FATAL",
|
||||||
"ERROR",
|
"ERROR",
|
||||||
|
@ -33,6 +32,8 @@ static const int g_newlineLength = 2;
|
||||||
//
|
//
|
||||||
|
|
||||||
CLog::Outputter CLog::s_outputter = NULL;
|
CLog::Outputter CLog::s_outputter = NULL;
|
||||||
|
CLog::Lock CLog::s_lock = &CLog::dummyLock;
|
||||||
|
int CLog::s_maxPriority = -1;
|
||||||
|
|
||||||
void CLog::print(const char* fmt, ...)
|
void CLog::print(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -100,31 +101,75 @@ void CLog::printt(const char* file, int line,
|
||||||
|
|
||||||
void CLog::setOutputter(Outputter outputter)
|
void CLog::setOutputter(Outputter outputter)
|
||||||
{
|
{
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
s_outputter = outputter;
|
s_outputter = outputter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLog::Outputter CLog::getOutputter()
|
||||||
|
{
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
|
return s_outputter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLog::setLock(Lock newLock)
|
||||||
|
{
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
|
s_lock = (newLock == NULL) ? dummyLock : newLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLog::Lock CLog::getLock()
|
||||||
|
{
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
|
return (s_lock == dummyLock) ? NULL : s_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLog::setFilter(int maxPriority)
|
||||||
|
{
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
|
s_maxPriority = maxPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLog::getFilter()
|
||||||
|
{
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
|
return getMaxPriority();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLog::dummyLock(bool)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLog::getMaxPriority()
|
||||||
|
{
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
|
|
||||||
|
if (s_maxPriority == -1) {
|
||||||
|
#if defined(NDEBUG)
|
||||||
|
s_maxPriority = 4;
|
||||||
|
#else
|
||||||
|
s_maxPriority = 5;
|
||||||
|
#endif
|
||||||
|
const char* priEnv = getenv("SYN_LOG_PRI");
|
||||||
|
if (priEnv != NULL) {
|
||||||
|
for (int i = 0; i < g_numPriority; ++i) {
|
||||||
|
if (strcmp(priEnv, g_priority[i]) == 0) {
|
||||||
|
s_maxPriority = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_maxPriority;
|
||||||
|
}
|
||||||
|
|
||||||
void CLog::output(int priority, char* msg)
|
void CLog::output(int priority, char* msg)
|
||||||
{
|
{
|
||||||
assert(priority >= 0 && priority < g_numPriority);
|
assert(priority >= 0 && priority < g_numPriority);
|
||||||
assert(msg != 0);
|
assert(msg != 0);
|
||||||
|
|
||||||
if (g_maxPriority == -1) {
|
if (priority <= getMaxPriority()) {
|
||||||
#if defined(NDEBUG)
|
|
||||||
g_maxPriority = 4;
|
|
||||||
#else
|
|
||||||
g_maxPriority = 5;
|
|
||||||
#endif
|
|
||||||
const char* priEnv = getenv("SYN_LOG_PRI");
|
|
||||||
if (priEnv != NULL) {
|
|
||||||
for (int i = 0; i < g_numPriority; ++i)
|
|
||||||
if (strcmp(priEnv, g_priority[i]) == 0) {
|
|
||||||
g_maxPriority = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priority <= g_maxPriority) {
|
|
||||||
// insert priority label
|
// insert priority label
|
||||||
int n = strlen(g_priority[priority]);
|
int n = strlen(g_priority[priority]);
|
||||||
sprintf(msg + g_maxPriorityLength - n, "%s:", g_priority[priority]);
|
sprintf(msg + g_maxPriorityLength - n, "%s:", g_priority[priority]);
|
||||||
|
@ -138,6 +183,7 @@ void CLog::output(int priority, char* msg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// print it
|
// print it
|
||||||
|
CHoldLock lock(s_lock);
|
||||||
if (s_outputter) {
|
if (s_outputter) {
|
||||||
s_outputter(msg + g_maxPriorityLength - n);
|
s_outputter(msg + g_maxPriorityLength - n);
|
||||||
}
|
}
|
||||||
|
|
35
base/CLog.h
35
base/CLog.h
|
@ -7,12 +7,45 @@
|
||||||
class CLog {
|
class CLog {
|
||||||
public:
|
public:
|
||||||
typedef void (*Outputter)(const char*);
|
typedef void (*Outputter)(const char*);
|
||||||
|
typedef void (*Lock)(bool lock);
|
||||||
|
|
||||||
|
//
|
||||||
static void print(const char*, ...);
|
static void print(const char*, ...);
|
||||||
static void printt(const char* file, int line, const char*, ...);
|
static void printt(const char* file, int line, const char*, ...);
|
||||||
|
|
||||||
|
// get/set the function used to write the log. a NULL outputter
|
||||||
|
// means to use the default which is fprintf(stderr, ...). note
|
||||||
|
// that the outputter should not call CLog methods but, if it
|
||||||
|
// does, the current lock function must permit recursive locks.
|
||||||
static void setOutputter(Outputter);
|
static void setOutputter(Outputter);
|
||||||
|
static Outputter getOutputter();
|
||||||
|
|
||||||
|
// get/set the lock/unlock function. use setLock(NULL) to remove
|
||||||
|
// the locking function. note that the lock function is used when
|
||||||
|
// retrieving the lock function. there is no default lock function.
|
||||||
|
static void setLock(Lock);
|
||||||
|
static Lock getLock();
|
||||||
|
|
||||||
|
// get/set the minimum priority filter. any message below this
|
||||||
|
// priority is discarded. the default priority is 4 (INFO)
|
||||||
|
// (unless built without NDEBUG in which case it's 5 (DEBUG)).
|
||||||
|
// the default can be overridden by setting the SYN_LOG_PRI env
|
||||||
|
// var to "CRIT", "ERR", etc.
|
||||||
|
static void setFilter(int);
|
||||||
|
static int getFilter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class CHoldLock {
|
||||||
|
public:
|
||||||
|
CHoldLock(CLog::Lock lock) : m_lock(lock) { m_lock(true); }
|
||||||
|
~CHoldLock() { m_lock(false); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
CLog::Lock m_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dummyLock(bool);
|
||||||
|
static int getMaxPriority();
|
||||||
static void output(int priority, char* msg);
|
static void output(int priority, char* msg);
|
||||||
static char* vsprint(int pad, char*, int len, const char*, va_list);
|
static char* vsprint(int pad, char*, int len, const char*, va_list);
|
||||||
static int nprint(const char*, va_list);
|
static int nprint(const char*, va_list);
|
||||||
|
@ -22,6 +55,8 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Outputter s_outputter;
|
static Outputter s_outputter;
|
||||||
|
static Lock s_lock;
|
||||||
|
static int s_maxPriority;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(NOLOGGING)
|
#if defined(NOLOGGING)
|
||||||
|
|
|
@ -1,14 +1,47 @@
|
||||||
#include "CClient.h"
|
#include "CClient.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
|
#include "CLog.h"
|
||||||
|
#include "CMutex.h"
|
||||||
#include "CNetwork.h"
|
#include "CNetwork.h"
|
||||||
#include "CNetworkAddress.h"
|
#include "CNetworkAddress.h"
|
||||||
#include "CThread.h"
|
#include "CThread.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// logging thread safety
|
||||||
|
//
|
||||||
|
|
||||||
|
static CMutex* s_logMutex = NULL;
|
||||||
|
|
||||||
|
static void logLock(bool lock)
|
||||||
|
{
|
||||||
|
assert(s_logMutex != NULL);
|
||||||
|
|
||||||
|
if (lock) {
|
||||||
|
s_logMutex->lock();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s_logMutex->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// main
|
||||||
|
//
|
||||||
|
|
||||||
void realMain(const CString& name,
|
void realMain(const CString& name,
|
||||||
const CString& hostname,
|
const CString& hostname,
|
||||||
UInt16 port)
|
UInt16 port)
|
||||||
{
|
{
|
||||||
|
// initialize threading library
|
||||||
CThread::init();
|
CThread::init();
|
||||||
|
|
||||||
|
// make logging thread safe
|
||||||
|
CMutex logMutex;
|
||||||
|
s_logMutex = &logMutex;
|
||||||
|
CLog::setLock(&logLock);
|
||||||
|
|
||||||
|
// initialize network library
|
||||||
CNetwork::init();
|
CNetwork::init();
|
||||||
|
|
||||||
CClient* client = NULL;
|
CClient* client = NULL;
|
||||||
|
@ -18,14 +51,23 @@ void realMain(const CString& name,
|
||||||
client->run(addr);
|
client->run(addr);
|
||||||
delete client;
|
delete client;
|
||||||
CNetwork::cleanup();
|
CNetwork::cleanup();
|
||||||
|
CLog::setLock(NULL);
|
||||||
|
s_logMutex = NULL;
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
delete client;
|
delete client;
|
||||||
CNetwork::cleanup();
|
CNetwork::cleanup();
|
||||||
|
CLog::setLock(NULL);
|
||||||
|
s_logMutex = NULL;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// platform dependent entry points
|
||||||
|
//
|
||||||
|
|
||||||
#if defined(CONFIG_PLATFORM_WIN32)
|
#if defined(CONFIG_PLATFORM_WIN32)
|
||||||
|
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CMSWindowsScreen.h"
|
||||||
|
|
|
@ -1,11 +1,44 @@
|
||||||
#include "CServer.h"
|
#include "CServer.h"
|
||||||
#include "CScreenMap.h"
|
#include "CScreenMap.h"
|
||||||
#include "CThread.h"
|
#include "CLog.h"
|
||||||
|
#include "CMutex.h"
|
||||||
#include "CNetwork.h"
|
#include "CNetwork.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// logging thread safety
|
||||||
|
//
|
||||||
|
|
||||||
|
static CMutex* s_logMutex = NULL;
|
||||||
|
|
||||||
|
static void logLock(bool lock)
|
||||||
|
{
|
||||||
|
assert(s_logMutex != NULL);
|
||||||
|
|
||||||
|
if (lock) {
|
||||||
|
s_logMutex->lock();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s_logMutex->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// main
|
||||||
|
//
|
||||||
|
|
||||||
void realMain()
|
void realMain()
|
||||||
{
|
{
|
||||||
|
// initialize threading library
|
||||||
CThread::init();
|
CThread::init();
|
||||||
|
|
||||||
|
// make logging thread safe
|
||||||
|
CMutex logMutex;
|
||||||
|
s_logMutex = &logMutex;
|
||||||
|
CLog::setLock(&logLock);
|
||||||
|
|
||||||
|
// initialize network library
|
||||||
CNetwork::init();
|
CNetwork::init();
|
||||||
|
|
||||||
CScreenMap screenMap;
|
CScreenMap screenMap;
|
||||||
|
@ -24,14 +57,23 @@ void realMain()
|
||||||
server->run();
|
server->run();
|
||||||
delete server;
|
delete server;
|
||||||
CNetwork::cleanup();
|
CNetwork::cleanup();
|
||||||
|
CLog::setLock(NULL);
|
||||||
|
s_logMutex = NULL;
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
delete server;
|
delete server;
|
||||||
CNetwork::cleanup();
|
CNetwork::cleanup();
|
||||||
|
CLog::setLock(NULL);
|
||||||
|
s_logMutex = NULL;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// platform dependent entry points
|
||||||
|
//
|
||||||
|
|
||||||
#if defined(CONFIG_PLATFORM_WIN32)
|
#if defined(CONFIG_PLATFORM_WIN32)
|
||||||
|
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CMSWindowsScreen.h"
|
||||||
|
|
Loading…
Reference in New Issue