cleanup some junk we don't need here

This commit is contained in:
DarthArgus
2016-06-12 04:21:02 -07:00
parent 303b37440b
commit 9500ff05df
220 changed files with 1 additions and 26531 deletions
@@ -1,18 +0,0 @@
/* SQLC_Defs.h
*
* This file includes common definitions needed by the other SQLClasses header files.
* (Don't include this file directly -- files that require it will include it.)
*
* Note that this file is specific to each OS, because what header files are
* needed varies in each OS. In particular, Unix versions don't want windows.h.
*
* ODBC versions: includes definitions of ODBC datatypes needed by the various
* SQLClasses
*/
#ifndef _SQLC_DEFS_H
#define _SQLC_DEFS_H
#include <sqltypes.h>
#endif
@@ -1,70 +0,0 @@
// ======================================================================
//
// ConfigSharedDebugLinux.cpp
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedDebug/FirstSharedDebug.h"
#include "sharedDebug/ConfigSharedDebugLinux.h"
#include "sharedDebug/Profiler.h"
#include "sharedFoundation/ConfigFile.h"
//===================================================================
namespace ConfigSharedDebugLinuxNamespace
{
bool s_useTty;
const char *s_debugMonitorOutputFilename;
bool s_logTtySetup;
}
using namespace ConfigSharedDebugLinuxNamespace;
//===================================================================
#define KEY_BOOL(a,b) (s_ ## a = ConfigFile::getKeyBool("SharedDebugLinux", #a, b))
#define KEY_STRING(a,b) (s_ ## a = ConfigFile::getKeyString("SharedDebugLinux", #a, b))
// #define KEY_INT(a,b) (s_ ## a = ConfigFile::getKeyInt("ClientAnimation", #a, b))
// #define KEY_FLOAT(a,b) (s_ ## a = ConfigFile::getKeyFloat("ClientAnimation", #a, b))
//===================================================================
void ConfigSharedDebugLinux::install(void)
{
KEY_BOOL(useTty, false);
KEY_STRING(debugMonitorOutputFilename, "ttySpecifier.txt");
KEY_BOOL(logTtySetup, false);
//-- Handle startup profiler handling here.
// @todo this should move into ConfigSharedDebug or be loaded
// by Profiler. Profiler can't load this config file option
// because the Profiler is installed prior to the config file
// system.
Profiler::enableProfilerOutput(ConfigFile::getKeyBool("SharedDebugLinux", "reportProfiler", false));
}
// ------------------------------------------------------------------
bool ConfigSharedDebugLinux::getUseTty()
{
return s_useTty;
}
// ------------------------------------------------------------------
char const *ConfigSharedDebugLinux::getDebugMonitorOutputFilename()
{
return s_debugMonitorOutputFilename;
}
// ------------------------------------------------------------------
bool ConfigSharedDebugLinux::getLogTtySetup()
{
return s_logTtySetup;
}
//===================================================================
@@ -1,29 +0,0 @@
// ======================================================================
//
// ConfigSharedDebugLinux.h
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ConfigSharedDebugLinux_H
#define INCLUDED_ConfigSharedDebugLinux_H
//===================================================================
class ConfigSharedDebugLinux
{
public:
static void install();
static bool getUseTty();
static char const *getDebugMonitorOutputFilename();
static bool getLogTtySetup();
};
//===================================================================
#endif
@@ -1,677 +0,0 @@
// ======================================================================
//
// DebugHelp.cpp
// Copyright 2001-2003 Sony Online Entertainment
//
// ======================================================================
#include "sharedDebug/FirstSharedDebug.h"
#include "sharedDebug/DebugHelp.h"
#include "sharedSynchronization/Mutex.h"
#include <execinfo.h>
#include <elf.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <dlfcn.h>
#include <map>
#include <vector>
#include <stddef.h>
// ======================================================================
class SymbolCache
{
public:
struct SymbolInfo
{
char const *srcLib;
char const *srcFile;
int srcLine;
bool found;
};
static void clear();
static SymbolInfo const &lookup(void const *addr);
static char const *uniqueString(char const *s);
static void *memPoolAllocate(size_t size);
static const size_t cms_memPoolMaxBytes = 8*1024*1024;
private:
static size_t ms_memPoolUsed;
static char ms_memPool[cms_memPoolMaxBytes];
static char *ms_memPoolFreeList;
static Mutex ms_memPoolMutex;
static SymbolInfo ms_nullSym;
};
// ----------------------------------------------------------------------
template <class T>
class SymbolCacheAllocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T * pointer;
typedef T const * const_pointer;
typedef T & reference;
typedef T const & const_reference;
typedef T value_type;
public:
SymbolCacheAllocator() {}
template <class U> SymbolCacheAllocator(SymbolCacheAllocator<U> const &) {}
template <class U> struct rebind { typedef SymbolCacheAllocator<U> other; };
pointer allocate(size_type n, const_pointer = 0) { return reinterpret_cast<pointer>(SymbolCache::memPoolAllocate(n*sizeof(value_type))); }
void deallocate(const_pointer p, size_type n) {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
size_type max_size() const { return SymbolCache::cms_memPoolMaxBytes; }
void construct(pointer p, value_type const & x) { new(p) value_type(x); }
void destroy(pointer p) { p->~value_type(); }
};
// ----------------------------------------------------------------------
size_t SymbolCache::ms_memPoolUsed;
char SymbolCache::ms_memPool[SymbolCache::cms_memPoolMaxBytes];
char *SymbolCache::ms_memPoolFreeList;
Mutex SymbolCache::ms_memPoolMutex;
SymbolCache::SymbolInfo SymbolCache::ms_nullSym;
typedef std::map<void const *, SymbolCache::SymbolInfo, std::less<void const *>, SymbolCacheAllocator<std::pair<void const *, SymbolCache::SymbolInfo> > > SymbolMap;
typedef std::vector<char const *, SymbolCacheAllocator<char const *> > UniqueStringVector;
static SymbolMap ms_cacheMap;
static UniqueStringVector ms_uniqueStringVector;
// ----------------------------------------------------------------------
static Elf32_Shdr const *elfGetObjSectionHeader(void const *objBaseAddr, int sectionIndex)
{
Elf32_Ehdr const *eh = reinterpret_cast<Elf32_Ehdr const *>(objBaseAddr);
if (sectionIndex >= 0 && sectionIndex < eh->e_shnum)
return reinterpret_cast<Elf32_Shdr const *>(static_cast<char const *>(objBaseAddr)+eh->e_shoff+sectionIndex*eh->e_shentsize);
return 0;
}
// ----------------------------------------------------------------------
static char const *elfGetObjSectionData(void const *objBaseAddr, int sectionIndex)
{
Elf32_Shdr const *sh = elfGetObjSectionHeader(objBaseAddr, sectionIndex);
if (sh)
return reinterpret_cast<char const *>(objBaseAddr)+sh->sh_offset;
return 0;
}
// ----------------------------------------------------------------------
static unsigned int elfGetObjSectionSize(void const *objBaseAddr, int sectionIndex)
{
Elf32_Shdr const *sh = elfGetObjSectionHeader(objBaseAddr, sectionIndex);
if (sh)
return sh->sh_size;
return 0;
}
// ----------------------------------------------------------------------
static char const *elfGetObjSectionName(void const *objBaseAddr, int sectionIndex)
{
Elf32_Ehdr const *eh = reinterpret_cast<Elf32_Ehdr const *>(objBaseAddr);
char const *sectionStr = elfGetObjSectionData(objBaseAddr, eh->e_shstrndx);
if (sectionStr)
{
Elf32_Shdr const *sh = elfGetObjSectionHeader(objBaseAddr, sectionIndex);
if (sh)
return sectionStr+sh->sh_name;
}
return 0;
}
// ----------------------------------------------------------------------
static int elfGetObjSectionByName(void const *objBaseAddr, char const *sectionName)
{
int n = reinterpret_cast<Elf32_Ehdr const *>(objBaseAddr)->e_shnum;
for (int i = 0; i < n; ++i)
if (!strcmp(elfGetObjSectionName(objBaseAddr, i), sectionName))
return i;
return -1;
}
// ----------------------------------------------------------------------
inline unsigned int dwarfGet(char const *src, u_int8_t &dest)
{
memcpy(&dest, src, sizeof(u_int8_t));
return sizeof(u_int8_t);
}
// ----------------------------------------------------------------------
inline unsigned int dwarfGet(char const *src, u_int16_t &dest)
{
memcpy(&dest, src, sizeof(u_int16_t));
return sizeof(u_int16_t);
}
// ----------------------------------------------------------------------
inline unsigned int dwarfGet(char const *src, u_int32_t &dest)
{
memcpy(&dest, src, sizeof(u_int32_t));
return sizeof(u_int32_t);
}
// ----------------------------------------------------------------------
class LEB128
{
public:
operator int() const { return value; }
int value;
};
// ----------------------------------------------------------------------
inline unsigned int dwarfGet(char const *src, LEB128 &dest)
{
unsigned int pos = 0;
int shift = 7;
int byte = ((u_int8_t*)src)[pos++];
dest.value = byte;
while (byte >= 0x80)
{
byte = ((u_int8_t *)src)[pos++] ^ 1;
dest.value ^= byte << shift;
shift += 7;
}
if (shift < 32 && (byte & 0x40))
dest.value |= -(1L<<shift);
return pos;
}
// ----------------------------------------------------------------------
class LEB128u
{
public:
operator unsigned int() const { return value; }
unsigned int value;
};
// ----------------------------------------------------------------------
inline unsigned int dwarfGet(char const *src, LEB128u &dest)
{
unsigned int pos = 0;
int shift = 7;
unsigned int byte = ((u_int8_t*)src)[pos++];
dest.value = byte;
while (byte >= 0x80)
{
byte = ((u_int8_t *)src)[pos++] ^ 1;
dest.value ^= byte << shift;
shift += 7;
}
return pos;
}
// ----------------------------------------------------------------------
static bool dwarfSearch(char const *dwarfLines, unsigned int linesLength, void const *addr, Dl_info const &info, char const *&retSrcFile, int &retSrcLine)
{
enum
{
DW_LNE_end_sequence = 1,
DW_LNE_set_address = 2,
DW_LNS_copy = 1,
DW_LNS_advance_pc = 2,
DW_LNS_advance_line = 3,
DW_LNS_set_file = 4,
DW_LNS_set_column = 5,
DW_LNS_negate_stmt = 6,
DW_LNS_set_basic_block = 7,
DW_LNS_const_add_pc = 8,
DW_LNS_fixed_advance_pc = 9,
};
////
void const *bestOverAddr = reinterpret_cast<void const *>(0xffffffff);
void const *bestUnderAddr = 0;
char const *bestUnderSrcFileTable = 0;
int bestUnderSrcFileNum = 0;
int bestUnderSrcLine = 0;
unsigned int stmtProgMaxLen = linesLength;
u_int32_t stmtProgLen = 0;
for (unsigned int progBeginOffset = 0; progBeginOffset < linesLength; progBeginOffset += stmtProgLen+4, stmtProgMaxLen -= stmtProgLen+4)
{
char const *stmtProg = dwarfLines+progBeginOffset;
// get program length
stmtProg += dwarfGet(stmtProg, stmtProgLen);
if (stmtProgLen < 12 || stmtProgLen+4 > stmtProgMaxLen)
continue;
char const *stmtProgEnd = stmtProg+stmtProgLen;
stmtProg += 2; // skip version
// get prologue length
u_int32_t stmtProgPrologueLen; stmtProg += dwarfGet(stmtProg, stmtProgPrologueLen);
if (stmtProgPrologueLen+10 > stmtProgMaxLen)
continue;
char const *stmtProgStart = stmtProg;
u_int8_t stmtProgMinInstructionLen; stmtProg += dwarfGet(stmtProg, stmtProgMinInstructionLen);
if (stmtProgMinInstructionLen == 0)
continue;
++stmtProg; // skip default_is_stmt
int8_t stmtProgLineBase; stmtProg += dwarfGet(stmtProg, *(u_int8_t*)&stmtProgLineBase);
u_int8_t stmtProgLineRange; stmtProg += dwarfGet(stmtProg, stmtProgLineRange);
if (stmtProgLineRange == 0)
continue;
u_int8_t stmtProgOpcodeBase; stmtProg += dwarfGet(stmtProg, stmtProgOpcodeBase);
u_int8_t const *stmtProgOpcodeLengths = reinterpret_cast<u_int8_t const *>(stmtProg);
stmtProg += stmtProgOpcodeBase-1;
// include dirs here
while (*stmtProg)
while (*stmtProg++);
char const *stmtProgFilenames = stmtProg;
stmtProg = stmtProgStart+stmtProgPrologueLen;
// run program
while (stmtProg < stmtProgEnd)
{
int progFile = 0;
int progLine = 1;
u_int32_t progAddr = 0;
bool done = false;
bool valid = false;
while (!done)
{
u_int8_t opcode = *stmtProg++;
if (opcode < stmtProgOpcodeBase)
{
switch (opcode)
{
case 0: // extended
{
u_int8_t size, extendedOpcode;
stmtProg += dwarfGet(stmtProg, size);
stmtProg += dwarfGet(stmtProg, extendedOpcode);
switch (extendedOpcode)
{
case DW_LNE_end_sequence:
valid = true;
done = true;
break;
case DW_LNE_set_address:
stmtProg += dwarfGet(stmtProg, progAddr);
break;
default: // unimplemented extended opcode, skip parms
stmtProg += size-1;
break;
}
}
break;
case DW_LNS_advance_pc:
{
LEB128u incr; stmtProg += dwarfGet(stmtProg, incr);
progAddr += incr*stmtProgMinInstructionLen;
}
break;
case DW_LNS_const_add_pc:
progAddr += (255-stmtProgOpcodeBase)/stmtProgLineRange*stmtProgMinInstructionLen;
break;
case DW_LNS_fixed_advance_pc:
{
u_int16_t incr; stmtProg += dwarfGet(stmtProg, incr);
progAddr += incr;
}
break;
case DW_LNS_advance_line:
{
LEB128 incr; stmtProg += dwarfGet(stmtProg, incr);
progLine += incr;
}
break;
case DW_LNS_set_file:
{
LEB128u fileNum; stmtProg += dwarfGet(stmtProg, fileNum);
progFile = fileNum-1;
}
break;
case DW_LNS_copy:
valid = true;
break;
// ignored
case DW_LNS_set_column:
{
LEB128u col; stmtProg += dwarfGet(stmtProg, col);
}
break;
case DW_LNS_negate_stmt:
case DW_LNS_set_basic_block:
break;
default:
{
// unimplemented standard opcode
// look up standard opcode length and skip that many LEB128u's
LEB128u temp;
for (int i = 0; i < stmtProgOpcodeLengths[opcode-1]; ++i)
stmtProg += dwarfGet(stmtProg, temp);
}
break;
}
}
else // special opcode
{
progLine += stmtProgLineBase+(opcode-stmtProgOpcodeBase)%stmtProgLineRange;
progAddr += (opcode-stmtProgOpcodeBase)/stmtProgLineRange*stmtProgMinInstructionLen;
valid = true;
}
if (valid)
{
unsigned int addrOffset = 0;
if (progAddr < reinterpret_cast<unsigned int>(info.dli_fbase))
addrOffset = reinterpret_cast<unsigned int>(info.dli_fbase);
const void *testAddr = reinterpret_cast<const void *>(progAddr+addrOffset);
if (testAddr >= addr)
{
if (testAddr < bestOverAddr)
bestOverAddr = testAddr;
}
else if (testAddr > bestUnderAddr)
{
bestUnderAddr = testAddr;
bestUnderSrcFileTable = stmtProgFilenames;
bestUnderSrcFileNum = progFile;
bestUnderSrcLine = progLine;
}
}
}
}
}
if (bestUnderAddr && bestOverAddr != reinterpret_cast<void const *>(0xffffffff))
{
char const *srcFile = bestUnderSrcFileTable+1;
for (int i = 0; i < bestUnderSrcFileNum; ++i)
{
while (*srcFile++);
srcFile += 3;
}
retSrcFile = SymbolCache::uniqueString(srcFile);
retSrcLine = bestUnderSrcLine;
return true;
}
return false;
}
// ----------------------------------------------------------------------
static bool dwarfFind(void const *addr, Dl_info const &info, char const *& retSrcFile, int &retSrcLine)
{
bool found = false;
int fd = open(info.dli_fname, O_RDONLY);
if (fd != -1)
{
int fileSize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
void const *mappedAddr = reinterpret_cast<void const *>(mmap(0, fileSize, PROT_READ, MAP_PRIVATE, fd, 0));
close(fd);
if (mappedAddr != MAP_FAILED)
{
int dwarfLinesIndex = elfGetObjSectionByName(mappedAddr, ".debug_line");
if (dwarfLinesIndex != -1)
{
try
{
found = dwarfSearch(
elfGetObjSectionData(mappedAddr, dwarfLinesIndex),
elfGetObjSectionSize(mappedAddr, dwarfLinesIndex),
addr,
info,
retSrcFile,
retSrcLine);
}
catch (std::bad_alloc &)
{
munmap(const_cast<void *>(mappedAddr), fileSize);
throw std::bad_alloc();
}
}
munmap(const_cast<void *>(mappedAddr), fileSize);
}
}
return found;
}
// ----------------------------------------------------------------------
struct Stab
{
unsigned int n_strx; // index into string table
unsigned char n_type; // type of stab entry
char n_other;
unsigned short n_desc; // for N_SLINE entries, line number
unsigned int n_value; // value of symbol
};
// ----------------------------------------------------------------------
static bool stabSearch(Stab const *stab, unsigned int stabSize, char const *stabStr, void const *addr, Dl_info const &info, char const *&retSrcFile, int &retSrcLine)
{
enum
{
N_UNDF = 0, // undefined
N_FUN = 0x24, // function
N_SLINE = 0x44, // source line
N_SO = 0x64, // source file name
N_SOL = 0x84 // local source file name
};
unsigned int stabCount = stabSize/sizeof(Stab);
char const *srcFile = "";
void const *funcBase = 0;
int foundSrcLine = -1;
for (unsigned int i = 0; i < stabCount; ++i, ++stab)
{
if (stab->n_type == N_UNDF) // new stabs section, do a recursive search of it
{
if (stabSearch(stab+1, stab->n_desc*sizeof(Stab), stabStr, addr, info, retSrcFile, retSrcLine))
return true;
i += stab->n_desc;
stab += stab->n_desc;
srcFile = "";
continue;
}
else if (stab->n_type == N_SO || stab->n_type == N_SOL) // source or header file specification
srcFile = stabStr+stab->n_strx;
else if (stab->n_type == N_FUN) // function specification
{
// This may not be terribly accurate - it's attempting to differentiate between already relocated symbols (main program)
// and shared libs, which need to be offset by their file base
if (reinterpret_cast<void const *>(stab->n_value) > info.dli_fbase)
funcBase = reinterpret_cast<void const *>(stab->n_value);
else
funcBase = reinterpret_cast<void const *>(reinterpret_cast<unsigned int>(info.dli_fbase)+stab->n_value);
foundSrcLine = -1;
}
else if (stab->n_type == N_SLINE && addr >= funcBase) // source line
{
if (stab->n_value < reinterpret_cast<unsigned int>(addr)-reinterpret_cast<unsigned int>(funcBase))
foundSrcLine = stab->n_desc;
else
{
retSrcLine = foundSrcLine == -1 ? stab->n_desc : foundSrcLine;
retSrcFile = SymbolCache::uniqueString(srcFile);
return true;
}
}
}
return false;
}
// ----------------------------------------------------------------------
static bool stabsFind(void const *addr, Dl_info const &info, char const *& retSrcFile, int &retSrcLine)
{
bool found = false;
int fd = open(info.dli_fname, O_RDONLY);
if (fd != -1)
{
int fileSize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
void const *mappedAddr = reinterpret_cast<void const *>(mmap(0, fileSize, PROT_READ, MAP_PRIVATE, fd, 0));
close(fd);
if (mappedAddr != MAP_FAILED)
{
int stabIndex = elfGetObjSectionByName(mappedAddr, ".stab");
int stabStrIndex = elfGetObjSectionByName(mappedAddr, ".stabstr");
if (stabIndex != -1 && stabStrIndex != -1)
{
try
{
found = stabSearch(
reinterpret_cast<Stab const *>(elfGetObjSectionData(mappedAddr, stabIndex)),
elfGetObjSectionSize(mappedAddr, stabIndex),
elfGetObjSectionData(mappedAddr, stabStrIndex),
addr,
info,
retSrcFile,
retSrcLine);
}
catch (std::bad_alloc &)
{
munmap(const_cast<void *>(mappedAddr), fileSize);
throw std::bad_alloc();
}
}
munmap(const_cast<void *>(mappedAddr), fileSize);
}
}
return found;
}
// ----------------------------------------------------------------------
SymbolCache::SymbolInfo const &SymbolCache::lookup(void const *addr)
{
SymbolMap::const_iterator i = ms_cacheMap.find(addr);
if (i != ms_cacheMap.end())
return (*i).second;
// allow for running out of the fixed memory pool and recover gracefully
for (int tries = 0; tries < 2; ++tries)
{
try
{
SymbolInfo &symInfo = ms_cacheMap[addr];
Dl_info info;
if (dladdr(addr, &info))
{
symInfo.srcLib = uniqueString(info.dli_fname);
if ( stabsFind(addr, info, symInfo.srcFile, symInfo.srcLine)
|| dwarfFind(addr, info, symInfo.srcFile, symInfo.srcLine))
symInfo.found = true;
}
return symInfo;
}
catch (std::bad_alloc &)
{
ms_uniqueStringVector.clear();
ms_cacheMap.clear();
ms_memPoolUsed = 0;
}
}
return ms_nullSym;
}
// ----------------------------------------------------------------------
char const *SymbolCache::uniqueString(char const *s)
{
for (UniqueStringVector::const_iterator i = ms_uniqueStringVector.begin(); i != ms_uniqueStringVector.end(); ++i)
if (!strcmp(s, *i))
return *i;
char *newString = static_cast<char *>(memPoolAllocate((strlen(s)+8)&(~7)));
strcpy(newString, s);
ms_uniqueStringVector.push_back(newString);
return newString;
}
// ----------------------------------------------------------------------
void *SymbolCache::memPoolAllocate(size_t size)
{
ms_memPoolMutex.enter();
if (ms_memPoolUsed+size > cms_memPoolMaxBytes)
{
ms_memPoolMutex.leave();
throw std::bad_alloc();
}
void *ret = ms_memPool+ms_memPoolUsed;
ms_memPoolUsed += size;
ms_memPoolMutex.leave();
return ret;
}
// ----------------------------------------------------------------------
bool lookupAddressInfo(void const *addr, char *retSrcLib, char *retSrcFile, int &retSrcLine, int stringBufLengths)
{
SymbolCache::SymbolInfo const &symInfo = SymbolCache::lookup(addr);
if (retSrcLib && symInfo.srcLib)
{
strncpy(retSrcLib, symInfo.srcLib, stringBufLengths);
retSrcLib[stringBufLengths-1] = '\0';
}
if (symInfo.found && retSrcFile)
{
strncpy(retSrcFile, symInfo.srcFile, stringBufLengths);
retSrcFile[stringBufLengths-1] = '\0';
}
retSrcLine = symInfo.srcLine;
return symInfo.found;
}
////
// ======================================================================
void DebugHelp::install()
{
}
// ----------------------------------------------------------------------
void DebugHelp::remove()
{
}
// ----------------------------------------------------------------------
bool DebugHelp::lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line)
{
return lookupAddressInfo(reinterpret_cast<void const *>(address), libName, fileName, line, fileNameLength);
}
// ----------------------------------------------------------------------
void DebugHelp::getCallStack(uint32 *callStack, int sizeOfCallStack)
{
for (int i = 0; i < sizeOfCallStack; ++i)
callStack[i] = 0;
IGNORE_RETURN(backtrace(reinterpret_cast<void **>(callStack), sizeOfCallStack));
}
// ======================================================================
@@ -1,33 +0,0 @@
// ======================================================================
//
// DebugHelp.h
// copyright 2000 Verant Interactive
//
// ======================================================================
#ifndef DEBUG_HELP_H
#define DEBUG_HELP_H
#include "sharedDebug/FirstSharedDebug.h"
// ======================================================================
typedef unsigned long uint32;
// ======================================================================
class DebugHelp
{
public:
static void install();
static void remove();
static void getCallStack(uint32 *callStack, int sizeOfCallStack);
static bool lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line);
};
// ======================================================================
#endif
@@ -1,445 +0,0 @@
// ======================================================================
//
// DebugMonitor.cpp
// Copyright 2002, Sony Online Entertainment.h
// All rights reserved.
//
// ======================================================================
#include "sharedDebug/FirstSharedDebug.h"
#include "sharedDebug/DebugMonitor.h"
#ifdef _DEBUG
#include "sharedDebug/ConfigSharedDebugLinux.h"
#include "sharedDebug/Profiler.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include <curses.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
// ======================================================================
namespace DebugMonitorNamespace
{
bool s_installed;
SCREEN *s_initialScreen;
WINDOW *s_initialWindow;
FILE *s_ttyOutputFile;
FILE *s_ttyInputFile;
SCREEN *s_outputScreen;
WINDOW *s_outputWindow;
}
using namespace DebugMonitorNamespace;
// ======================================================================
// Install the debug monitor subsystem
//
// Remarks:
//
// This routine will first attempt to install the selected debug monitor.
void DebugMonitor::install(void)
{
DEBUG_FATAL(s_installed, ("DebugMonitor already installed."));
//-- Check if user wants to use a TTY for the DebugMonitor.
if (!ConfigSharedDebugLinux::getUseTty())
{
// Do not use the DebugMonitor.
DEBUG_REPORT_LOG(ConfigSharedDebugLinux::getLogTtySetup(), ("DebugMonitor: skipping install, ConfigSharedDebugLinux/useTty is false.\n"));
return;
}
//-- Open and retrieve the name of the TTY file for output from the TTY Specification file.
char const *const configFilename = ConfigSharedDebugLinux::getDebugMonitorOutputFilename();
if (!configFilename || (*configFilename == '\0'))
{
DEBUG_WARNING(true, ("DebugMonitor(): skipping installation, no debugMonitorOutputFilename specified."));
return;
}
char ttyFilename[1024];
if (configFilename[0] != '@')
{
// filename is the real output filename (usually a device) for DebugMonitor output.
strncpy(ttyFilename, configFilename, sizeof(ttyFilename) - 1);
ttyFilename[sizeof(ttyFilename)-1] = 0;
}
else
{
// filename is actually an indirection filename, the contents of this file contains the real filename.
FILE *ttySpecifierFile = fopen(configFilename + 1, "r");
if (!ttySpecifierFile)
{
DEBUG_WARNING(true, ("DebugMonitor: failed to open tty specifier file [%s]: [%s].", configFilename + 1, strerror(errno)));
return;
}
// Retrieve the TTY file name.
fgets(ttyFilename, sizeof(ttyFilename), ttySpecifierFile);
fclose(ttySpecifierFile);
}
// Strip trailing newline from TTY filename.
const int filenameLength = strlen(ttyFilename);
if (filenameLength > 0)
{
// chop off trailing newline if present.
if (ttyFilename[filenameLength - 1] == '\n')
ttyFilename[filenameLength - 1] = '\0';
}
//-- Open the TTY file for output.
DEBUG_REPORT_LOG(ConfigSharedDebugLinux::getLogTtySetup(), ("DebugMonitor: opening TTY file [%s] for reading and writing.\n", ttyFilename));
FILE *s_ttyOutputFile = fopen(ttyFilename, "w");
if (!s_ttyOutputFile)
{
DEBUG_WARNING(true, ("DebugMonitor: failed to open tty file for output [%s]: [%s].", ttyFilename, strerror(errno)));
return;
}
//-- Open the TTY file for input.
FILE *s_ttyInputFile = fopen(ttyFilename, "r");
if (!s_ttyInputFile)
{
DEBUG_WARNING(true, ("DebugMonitor: failed to open tty file for input [%s]: [%s].", ttyFilename, strerror(errno)));
fclose(s_ttyOutputFile);
return;
}
#if 1
// NOTE: -TRF- I would not expect this chunk of termios setup
// code to be necessary. My expectation is that it should
// be handled by the curs_inopts (see man page) options I have
// selected below. Alas, these are needed.
//-- Setup profiler window input mode.
const int inputFd = STDIN_FILENO;
// Get terminal attributes.
termios terminalAttributes;
if (tcgetattr(inputFd, &terminalAttributes) != 0)
{
DEBUG_WARNING(true, ("DebugMonitor: tcgetattr failed [%s].", strerror(errno)));
return;
}
// Turn off line-processing mode. We want a character at a time.
terminalAttributes.c_lflag &= ~ICANON;
// Turn off echo.
terminalAttributes.c_lflag &= ~ECHO;
// Specify that read should return immediately (non-blocking).
terminalAttributes.c_cc[VMIN] = 0;
terminalAttributes.c_cc[VTIME] = 0;
// Set terminal attributes.
if (tcsetattr(inputFd, TCSAFLUSH, &terminalAttributes) != 0)
{
DEBUG_WARNING(true, ("DebugMonitor: tcsetattr failed [%s].", strerror(errno)));
return;
}
#endif
//-- Create a curses screen to represent the DebugMonitor output tty.
// NOTE: for now the curses input is hooked up to the application's
// standard input. Later we may want to change that to
// handle input from the output terminal, particularly to
// handle profiler modifications when the output window
// is active.
s_outputScreen = newterm(NULL, s_ttyOutputFile, stdin);
if (!s_outputScreen)
{
DEBUG_WARNING(true, ("DebugMonitor: newterm() failed [%s].", strerror(errno)));
fclose(s_ttyOutputFile);
fclose(s_ttyInputFile);
return;
}
//-- Initialize the curses library.
s_initialWindow = initscr();
if (!s_initialWindow)
{
DEBUG_WARNING(true, ("DebugMonitor: initscr(): failed [%s].", strerror(errno)));
fclose(s_ttyOutputFile);
fclose(s_ttyInputFile);
return;
}
//-- Restore the stdout window to its previous state. We won't use stdout.
endwin();
//-- Set the default terminal to be the output TTY's terminal screen.
s_initialScreen = set_term(s_outputScreen);
if (!s_initialScreen)
{
DEBUG_WARNING(true, ("DebugMonitor: set_term(): failed [%s].", strerror(errno)));
delscreen(s_outputScreen);
fclose(s_ttyOutputFile);
fclose(s_ttyInputFile);
return;
}
//-- Create the curses WINDOW at the full size of the TTY.
s_outputWindow = newwin(0, 0, 0, 0);
if (!s_outputWindow)
{
DEBUG_WARNING(true, ("DebugMonitor: newwin(): failed [%s].", strerror(errno)));
delscreen(s_outputScreen);
fclose(s_ttyOutputFile);
fclose(s_ttyInputFile);
return;
}
//-- Destroy curses data structures associated with the stdout TTY
delwin(s_initialWindow);
delscreen(s_initialScreen);
//-- Additional profiler input setup.
// Allow translation of arrow keys.
if (keypad(s_outputWindow, true) == ERR)
{
DEBUG_WARNING(true, ("DebugMonitor: keypad() failed [%s].", strerror(errno)));
return;
}
//-- Add the removal routine to the ExitChain.
s_installed = true;
// NOTE: this can't go on the exit chain because the MemoryManager
// will write to it way late in processing.
//ExitChain::add(remove, "DebugMonitor");
}
// ----------------------------------------------------------------------
void DebugMonitor::remove(void)
{
if (!s_installed)
{
// Exit silently rather than FATAL. There's any number of reasons why
// we might not be installed, and the ExitChain does not call remove,
// so this should be valid.
return;
}
s_installed = false;
//-- Restore the TTY's state.
endwin();
//-- Delete curses data structures associated with the output terminal.
delwin(s_outputWindow);
s_outputWindow = 0;
delscreen(s_outputScreen);
s_outputScreen = 0;
//-- Close file handle to output terminal.
fclose(s_ttyOutputFile);
s_ttyOutputFile = 0;
fclose(s_ttyInputFile);
s_ttyInputFile = 0;
}
// ----------------------------------------------------------------------
/**
* Set the debug window's z-order.
*/
void DebugMonitor::setBehindWindow(HWND window)
{
UNREF(window);
}
// ----------------------------------------------------------------------
/**
* Clear the debug monitor and home the cursor.
*
* If the mono monitor is not installed, this routine does nothing.
*
* This routine will clear the contents of the debug monitor, reset the screen
* offset to 0, and move the cursor to the upper left corner of the screen.
*
* @see DebugMonitor::home(), DebugMonitor::clearToCursor()
*/
void DebugMonitor::clearScreen(void)
{
//-- Ignore request if DebugMonitor isn't installed.
if (!s_installed)
return;
//-- Tell curses to clear the virtual screen. The actual
// clear will not take effect until the next showOutput() call
// is made.
IGNORE_RETURN(wclear(s_outputWindow));
//-- Goto upper left corner.
gotoXY(0, 0);
}
// ----------------------------------------------------------------------
/**
* Clear the debug monitor to the current cursor position and home the cursor.
*
* If the debug monitor is not installed, this routine does nothing.
*
* This routine will clear the contents of the debug monitor only up to the
* cursor position. If the cursor is not very far down on the screen,
* this routine may be significantly more efficient clearing the screen.
*
* It will also move the cursor to the upper left corner of the screen.
*
* @see DebugMonitor::clearScreen(), DebugMonitor::home()
*/
void DebugMonitor::clearToCursor(void)
{
//-- Ignore request if DebugMonitor isn't installed.
if (!s_installed)
return;
//-- I don't see this functionality in curses. Just clear
// the entire screen.
clearScreen();
}
// ----------------------------------------------------------------------
/**
* Position the cursor on the debug monitor screen.
*
* If the debug monitor is not installed, this routine does nothing.
*
* All printing happens at the cursor position.
*
* @param x New X position for the cursor
* @param y New Y position for the cursor
*/
void DebugMonitor::gotoXY(int x, int y)
{
//-- Ignore request if DebugMonitor isn't installed.
if (!s_installed)
return;
//-- Move the cursor position to the specified location.
const int result = wmove(s_outputWindow, y, x);
DEBUG_REPORT_LOG(result == ERR, ("DebugMonitor: wmove(%d, %d) failed [%s].\n", y, x, strerror(errno)));
UNREF(result);
}
// ----------------------------------------------------------------------
/**
* Display a string on the debug monitor.
* * If the debug monitor is not installed, this routine does nothing.
*
* Printing occurs from the cursor position.
*
* Newline characters '\n' will cause the cursor position to advance to the
* beginning of the next line. If the cursor is already on the last line of
* the screen, the screen will scroll up one line and the cursor will move to
* the beginning of the last line.
*
* The backspace character '\b' will cause the cursor to move one character
* backwards. If at the beginning of the line, the cursor will move to the
* end of the previous line. If already on the first line of the screen, the
* cursor position and screen contents will be unchanged.
*
* All other characters are placed directly into the text frame buffer.
* After each character, the cursor will be logically advanced one
* character forward. If the cursor was on the last column, it will advance
* to the next line. If the cursor was already on the last line, the screen
* will be scrolled up one line and the cursor will move to the beginning of
* the last line.
*
* @param string String to display on the debug monitor
*/
void DebugMonitor::print(const char *string)
{
//-- Ignore request if DebugMonitor isn't installed.
if (!s_installed)
return;
const int result = wprintw(s_outputWindow, const_cast<char*>(string));
DEBUG_REPORT_LOG(result == ERR, ("WARNING: DebugMonitor: wprintw failed [%s].\n", strerror(errno)));
UNREF(result);
}
// ----------------------------------------------------------------------
/**
* Ensure all changes to the DebugMonitor have taken effect by the time
* this function returns.
*
* Note: some platforms may do nothing here. The Win32 platform does not
* require flushing. The Linux platform does. Call it assuming
* that it is needed. It will be a no-op when not required.
*/
void DebugMonitor::flushOutput()
{
//-- Ignore request if DebugMonitor isn't installed.
if (!s_installed)
return;
//-- Tell curses to refresh the output window so that
// the virtual curses display is rendered to the real
// terminal display.
const int result = wrefresh(s_outputWindow);
DEBUG_REPORT_LOG(result == ERR, ("WARNING: DebugMonitor: wrefresh failed [%s].\n", strerror(errno)));
UNREF(result);
//-- Handle tty input here. This is somewhat hacky. Unix tty input
// and output currently are intimately tied to the profiler. Later
// this can be separated out so we can handle multiple TTYs for
// multiple purposes, such as for handling a TTY-based popup debug
// menu for on-the-fly options changing.
const int input = wgetch(s_outputWindow);
if (input != ERR)
{
#if 0
DEBUG_REPORT_LOG(true, ("DebugMonitor: received key [index=%d].\n", input));
#endif
//-- Handle input.
switch (input)
{
case '8':
case KEY_UP:
Profiler::selectionMoveUp();
break;
case '9':
case KEY_DOWN:
Profiler::selectionMoveDown();
break;
case '0':
case 10:
case KEY_LEFT:
case KEY_RIGHT:
Profiler::selectionToggleExpanded();
break;
default:
// Nothing to do.
break;
}
}
}
// ======================================================================
#endif
@@ -1,67 +0,0 @@
// ======================================================================
//
// DebugMonitor.h
// Portions Copyright 1998, Bootprint Entertainment, Inc.
// Portions Copyright 2002, Sony Online Entertainment, Inc.
//
// ======================================================================
#ifndef INCLUDED_DebugMonitor_H
#define INCLUDED_DebugMonitor_H
// ======================================================================
#ifdef _DEBUG
class DebugMonitor
{
private:
public:
static void install(void);
static void remove(void);
typedef void* HWND;
static void setBehindWindow(HWND window);
static void clearScreen(void);
static void clearToCursor(void);
static void home(void);
static void gotoXY(int x, int y);
static void print(const char *string);
static void flushOutput();
};
#endif
// ======================================================================
// Move the cursor to the upper left hand corner of the mono monitor screen
//
// Remarks:
//
// If the debug monitor is not installed, this routine does nothing.
//
// All printing happens at the cursor position.
//
// This routine is identical to calling gotoXY(0,0);
//
// See Also:
//
// DebugMonitor::gotoXY()
#ifdef _DEBUG
inline void DebugMonitor::home(void)
{
gotoXY(0,0);
}
#endif
// ======================================================================
#endif
@@ -1,125 +0,0 @@
//=================================================================== //
//
// PerformanceTimer.cpp
// copyright 2000-2004 Sony Online Entertainment
// All Rights Reserved
//
//===================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedDebug/PerformanceTimer.h"
//===================================================================
#include <cstdio>
//===================================================================
void PerformanceTimer::install()
{
}
//-------------------------------------------------------------------
PerformanceTimer::PerformanceTimer()
{
startTime.tv_sec = 0;
startTime.tv_usec = 0;
stopTime.tv_sec = 0;
stopTime.tv_usec = 0;
}
//-------------------------------------------------------------------
PerformanceTimer::~PerformanceTimer()
{
}
//-------------------------------------------------------------------
void PerformanceTimer::start()
{
int const result = gettimeofday(&startTime, NULL);
FATAL(result != 0,("PerformanceTimer::start failed"));
}
//-------------------------------------------------------------------
void PerformanceTimer::resume()
{
long sec = stopTime.tv_sec - startTime.tv_sec;
long usec = stopTime.tv_usec - startTime.tv_usec;
if(usec < 0)
{
--sec;
usec += 1000000;
}
int const result = gettimeofday(&startTime, NULL);
FATAL(result != 0,("PerformanceTimer::resume failed"));
startTime.tv_sec -= sec;
startTime.tv_usec -= usec;
if(startTime.tv_usec < 0)
{
--startTime.tv_sec;
startTime.tv_usec += 1000000;
}
}
//-------------------------------------------------------------------
void PerformanceTimer::stop()
{
int result = gettimeofday(&stopTime, NULL);
FATAL(result != 0,("PerformanceTimer::start failed"));
}
//-------------------------------------------------------------------
float PerformanceTimer::getElapsedTime() const
{
long sec = stopTime.tv_sec - startTime.tv_sec;
long usec = stopTime.tv_usec - startTime.tv_usec;
if(usec < 0)
{
--sec;
usec += 1000000;
}
return static_cast<float>(sec) +(static_cast<float>(usec) / 1000000.0f);
}
//-------------------------------------------------------------------
float PerformanceTimer::getSplitTime() const
{
timeval currentTime;
int const result = gettimeofday(&currentTime, NULL);
FATAL(result != 0,("PerformanceTimer::getSplitTime failed"));
long sec = currentTime.tv_sec - startTime.tv_sec;
long usec = currentTime.tv_usec - startTime.tv_usec;
if(usec < 0)
{
--sec;
usec += 1000000;
}
return static_cast<float>(sec) +(static_cast<float>(usec) / 1000000.0f);
}
//-------------------------------------------------------------------
void PerformanceTimer::logElapsedTime(const char* string) const
{
UNREF(string);
#ifdef _DEBUG
static char buffer [1000];
sprintf(buffer, "%s : %1.5f seconds\n", string ? string : "null", getElapsedTime());
DEBUG_REPORT_LOG_PRINT(true, ("%s", buffer));
#endif
}
//-------------------------------------------------------------------
@@ -1,51 +0,0 @@
//=================================================================== //
//
// PerformanceTimer.h
// copyright 2000-2004 Sony Online Entertainment
// All Rights Reserved
//
//===================================================================
#ifndef INCLUDED_PerformaceTimer_H
#define INCLUDED_PerformaceTimer_H
//===================================================================
#include <unistd.h>
#include <sys/time.h>
//===================================================================
class PerformanceTimer
{
public:
static void install();
public:
PerformanceTimer();
~PerformanceTimer();
void start();
void resume();
void stop();
float getElapsedTime() const;
float getSplitTime() const;
void logElapsedTime(const char* string) const;
private:
timeval startTime;
timeval stopTime;
private:
PerformanceTimer(PerformanceTimer const &);
PerformanceTimer & operator=(PerformanceTimer const &);
};
//===================================================================
#endif
@@ -1,39 +0,0 @@
// ======================================================================
//
// ProfilerTimer.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedDebug/FirstSharedDebug.h"
#include "sharedDebug/ProfilerTimer.h"
// ======================================================================
void ProfilerTimer::install()
{
}
// ----------------------------------------------------------------------
void ProfilerTimer::getTime(Type &time)
{
timeval tv;
gettimeofday(&tv, 0);
time = static_cast<Type>(tv.tv_sec)*static_cast<Type>(1000000)+static_cast<Type>(tv.tv_usec);
}
// ----------------------------------------------------------------------
void ProfilerTimer::getCalibratedTime(Type &time, Type &frequency)
{
getTime(time);
frequency = 1000000;
}
void ProfilerTimer::getFrequency(Type &frequency)
{
frequency = 1000000;
}
// ======================================================================
@@ -1,29 +0,0 @@
// ======================================================================
//
// ProfilerTimer.h
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_ProfilerTimer_H
#define INCLUDED_ProfilerTimer_H
// ======================================================================
class ProfilerTimer
{
public:
typedef uint64 Type;
public:
static void install();
static void getTime(Type &type);
static void getCalibratedTime(Type &time, Type &frequency);
static void getFrequency(Type &frequency);
};
// ======================================================================
#endif
@@ -1,123 +0,0 @@
// ======================================================================
//
// OsFile.cpp
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFile/FirstSharedFile.h"
#include "sharedFile/OsFile.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
// ======================================================================
void OsFile::install()
{
}
// ----------------------------------------------------------------------
bool OsFile::exists(const char *fileName)
{
struct stat statBuffer;
if (stat(fileName, &statBuffer) != 0)
return false;
if (S_ISDIR(statBuffer.st_mode))
return false;
return true;
}
// ----------------------------------------------------------------------
int OsFile::getFileSize(const char *fileName)
{
struct stat statBuffer;
int fileSize = 0;
if (stat(fileName, &statBuffer) == 0)
{
fileSize = static_cast<int>(statBuffer.st_size);
}
return fileSize;
}
// ----------------------------------------------------------------------
OsFile *OsFile::open(const char *fileName, bool randomAccess)
{
UNREF(randomAccess);
if (!exists(fileName))
return 0;
// attempt to open the file
const int handle = ::open(fileName, O_RDONLY);
FATAL(handle < 0, ("OsFile::open failed to open file %s, errno=%d, which does exist.", fileName, errno));
return new OsFile(handle, DuplicateString(fileName));
}
// ----------------------------------------------------------------------
OsFile::OsFile(int handle, char *fileName)
:
m_handle(handle),
m_length(0),
m_offset(0),
m_fileName(fileName)
{
m_length = lseek(m_handle, 0, SEEK_END);
lseek(m_handle, 0, SEEK_SET);
}
// ----------------------------------------------------------------------
OsFile::~OsFile()
{
close(m_handle);
delete [] m_fileName;
}
// ----------------------------------------------------------------------
int OsFile::length() const
{
return m_length;
}
// ----------------------------------------------------------------------
void OsFile::seek(int newFilePosition)
{
if (m_offset != newFilePosition)
{
const int result = lseek(m_handle, newFilePosition, SEEK_SET);
DEBUG_FATAL(result != newFilePosition, ("SetFilePointer failed"));
UNREF(result);
m_offset = newFilePosition;
}
}
// ----------------------------------------------------------------------
int OsFile::read(void *destinationBuffer, int numberOfBytes)
{
int result = 0;
do
{
result = ::read(m_handle, destinationBuffer, numberOfBytes);
DEBUG_FATAL((result < 0 && errno != EAGAIN), ("Read failed for %s: %d %d %s", m_fileName, result, errno, strerror(errno)));
} while (result < 0);
m_offset += result;
return result;
}
// ======================================================================
@@ -1,51 +0,0 @@
// ======================================================================
//
// OsFile.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_OsFile_H
#define INCLUDED_OsFile_H
// ======================================================================
class OsFile
{
public:
static void install();
static bool exists(const char *fileName);
static int getFileSize(const char *fileName);
static OsFile *open(const char *fileName, bool randomAccess=false);
public:
~OsFile();
int length() const;
int tell() const;
void seek(int newFilePosition);
int read(void *destinationBuffer, int numberOfBytes);
private:
OsFile(int handle, char *fileName);
OsFile();
OsFile(const OsFile &);
OsFile &operator =(const OsFile &);
private:
int m_handle;
int m_length;
int m_offset;
char *m_fileName;
};
// ======================================================================
#endif
@@ -1,20 +0,0 @@
// ======================================================================
//
// ByteOrder.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef BYTE_ORDER_H
#define BYTE_ORDER_H
// ======================================================================
#include "../../../../../../engine/shared/library/sharedFoundation/include/public/sharedFoundation/FirstPlatform.h"
// ======================================================================
#endif
@@ -1,289 +0,0 @@
// ======================================================================
//
// ConfigSharedFoundation.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedFoundation/ConfigFile.h"
// ======================================================================
const int c_defaultFatalCallStackDepth = 32;
const int c_defaultWarningCallStackDepth = 8;
// ======================================================================
namespace ConfigSharedFoundationNamespace
{
real ms_frameRateLimit;
real ms_minFrameRate;
bool ms_noExceptionHandling;
bool ms_fpuExceptionPrecision;
bool ms_fpuExceptionUnderflow;
bool ms_fpuExceptionOverflow;
bool ms_fpuExceptionZeroDivide;
bool ms_fpuExceptionDenormal;
bool ms_fpuExceptionInvalid;
bool ms_demoMode;
bool ms_useRemoteDebug;
int ms_defaultRemoteDebugPort;
bool ms_profilerExpandAllBranches = true;
bool ms_memoryManagerReportAllocations;
bool ms_memoryManagerReportOnOutOfMemory;
bool ms_useMemoryBlockManager;
bool ms_memoryBlockManagerDebugDumpOnRemove;
int ms_fatalCallStackDepth;
int ms_warningCallStackDepth;
bool ms_lookUpCallStackNames;
bool ms_alwaysCanSeeWorldCell;
bool ms_verboseWarnings;
float ms_debugReportLongFrameTime;
}
using namespace ConfigSharedFoundationNamespace;
// ======================================================================
#define KEY_INT(a,b) (ms_ ## a = ConfigFile::getKeyInt("SharedFoundation", #a, b))
#define KEY_BOOL(a,b) (ms_ ## a = ConfigFile::getKeyBool("SharedFoundation", #a, b))
#define KEY_FLOAT(a,b) (ms_ ## a = ConfigFile::getKeyFloat("SharedFoundation", #a, b))
// #define KEY_STRING(a,b) (ms_ ## a = ConfigFile::getKeyString("SharedFoundation", #a, b))
// ======================================================================
// Determine the Platform-specific configuration information
//
// Remarks:
//
// This routine inspects the ConfigFile class to set some variables for rapid access
// by the rest of the engine.
void ConfigSharedFoundation::install (const Defaults &defaults)
{
KEY_BOOL(noExceptionHandling, false);
KEY_BOOL(fpuExceptionPrecision, false);
KEY_BOOL(fpuExceptionUnderflow, false);
KEY_BOOL(fpuExceptionOverflow, false);
KEY_BOOL(fpuExceptionZeroDivide, false);
KEY_BOOL(fpuExceptionDenormal, false);
KEY_BOOL(fpuExceptionInvalid, false);
KEY_BOOL(demoMode, false);
KEY_FLOAT(frameRateLimit, defaults.frameRateLimit);
KEY_FLOAT(minFrameRate, 0.0f);
KEY_BOOL(useRemoteDebug, false);
KEY_INT(defaultRemoteDebugPort, 4445);
KEY_BOOL(profilerExpandAllBranches, true);
KEY_BOOL(memoryManagerReportAllocations, true);
KEY_BOOL(memoryManagerReportOnOutOfMemory, true);
KEY_BOOL(useMemoryBlockManager, true);
KEY_BOOL(memoryBlockManagerDebugDumpOnRemove, false);
KEY_INT(fatalCallStackDepth, c_defaultFatalCallStackDepth);
KEY_INT(warningCallStackDepth, c_defaultWarningCallStackDepth);
KEY_BOOL(lookUpCallStackNames, true);
KEY_BOOL(alwaysCanSeeWorldCell, false);
KEY_BOOL(verboseWarnings, false);
KEY_FLOAT(debugReportLongFrameTime, 0.25f);
}
// ======================================================================
/**
* Return the frame rate limit value for the game.
*
* @return The initial frame rate limiter value
*/
real ConfigSharedFoundation::getFrameRateLimit(void)
{
return ms_frameRateLimit;
}
// ----------------------------------------------------------------------
/**
* Return the minimum frame rate limit value for the game. Frame that take longer
* will be set to the minimum and a message will be logged.
*
* @return The minimum frame rate value
*/
real ConfigSharedFoundation::getMinFrameRate(void)
{
return ms_minFrameRate;
}
// ----------------------------------------------------------------------
/**
* Return whether to run with exception handling enabled.
*
* @return True to run without exception handling
*/
bool ConfigSharedFoundation::getNoExceptionHandling(void)
{
return ms_noExceptionHandling;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionPrecision(void)
{
return ms_fpuExceptionPrecision;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionUnderflow(void)
{
return ms_fpuExceptionUnderflow;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionOverflow(void)
{
return ms_fpuExceptionOverflow;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionZeroDivide(void)
{
return ms_fpuExceptionZeroDivide;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionDenormal(void)
{
return ms_fpuExceptionDenormal;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionInvalid(void)
{
return ms_fpuExceptionInvalid;
}
// ----------------------------------------------------------------------
int ConfigSharedFoundation::getFatalCallStackDepth()
{
return ms_fatalCallStackDepth;
}
// ----------------------------------------------------------------------
int ConfigSharedFoundation::getWarningCallStackDepth()
{
return ms_warningCallStackDepth;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getProfilerExpandAllBranches()
{
return ms_profilerExpandAllBranches;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getUseRemoteDebug()
{
return ms_useRemoteDebug;
}
// ----------------------------------------------------------------------
int ConfigSharedFoundation::getDefaultRemoteDebugPort()
{
return ms_defaultRemoteDebugPort;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getDemoMode()
{
return ms_demoMode;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getAlwaysCanSeeWorldCell()
{
return ms_alwaysCanSeeWorldCell;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getLookUpCallStackNames()
{
return ms_lookUpCallStackNames;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getMemoryManagerReportAllocations()
{
return ms_memoryManagerReportAllocations;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getMemoryManagerReportOnOutOfMemory()
{
return ms_memoryManagerReportOnOutOfMemory;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getUseMemoryBlockManager()
{
return ms_useMemoryBlockManager;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getMemoryBlockManagerDebugDumpOnRemove ()
{
return ms_memoryBlockManagerDebugDumpOnRemove;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getVerboseWarnings()
{
return ms_verboseWarnings;
}
// ----------------------------------------------------------------------
float ConfigSharedFoundation::getDebugReportLongFrameTime()
{
return ms_debugReportLongFrameTime;
}
// ======================================================================
@@ -1,64 +0,0 @@
// ======================================================================
//
// ConfigSharedFoundation.h
// copyright 1998 Bootprint Entertainment
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_ConfigSharedFoundation_H
#define INCLUDED_ConfigSharedFoundation_H
// ======================================================================
class ConfigSharedFoundation
{
public:
struct Defaults
{
real frameRateLimit;
};
public:
static void install (const Defaults &defaults);
static real getFrameRateLimit();
static real getMinFrameRate();
static bool getNoExceptionHandling();
static bool getFpuExceptionPrecision();
static bool getFpuExceptionUnderflow();
static bool getFpuExceptionOverflow();
static bool getFpuExceptionZeroDivide();
static bool getFpuExceptionDenormal();
static bool getFpuExceptionInvalid();
static bool getDemoMode();
static bool getUseRemoteDebug();
static int getDefaultRemoteDebugPort();
static bool getProfilerExpandAllBranches();
static bool getMemoryManagerReportAllocations();
static bool getMemoryManagerReportOnOutOfMemory();
static bool getUseMemoryBlockManager();
static bool getMemoryBlockManagerDebugDumpOnRemove();
static int getFatalCallStackDepth();
static int getWarningCallStackDepth();
static bool getLookUpCallStackNames();
static bool getAlwaysCanSeeWorldCell();
static bool getVerboseWarnings();
static float getDebugReportLongFrameTime();
};
// ======================================================================
#endif
@@ -1,54 +0,0 @@
// ======================================================================
//
// FirstPlatform.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef FIRST_PLATFORM_H
#define FIRST_PLATFORM_H
// ======================================================================
#include <cstdlib>
#define DLLEXPORT
// ======================================================================
// C4514 unreferenced inline function has been removed
// C4710 inline function not expanded
// C4291 no matching operator delete found; memory will not be freed if initialization throws an exception
#include <float.h>
#include <math.h>
#include <ctype.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdarg.h>
#include <string.h>
#include <wchar.h>
#include "../../../../../../engine/shared/library/sharedFoundation/include/public/sharedFoundation/PlatformGlue.h"
#include "sharedMemoryManager/MemoryManager.h"
// ======================================================================
template <class T>
inline int ComGetReferenceCount(T *t)
{
t->AddRef();
return t->Release();
}
// ======================================================================
#define FATAL_HR(a,b) FATAL(FAILED(b), (a, HRESULT_CODE(b)))
#define DEBUG_FATAL_HR(a,b) DEBUG_FATAL(FAILED(b), (a, HRESULT_CODE(b)))
// ======================================================================
#endif
@@ -1,266 +0,0 @@
// ======================================================================
//
// FloatingPointUnit.cpp
// jeff grills
//
// copyright 1999 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/FloatingPointUnit.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
// ======================================================================
int FloatingPointUnit::updateNumber;
WORD FloatingPointUnit::status;
FloatingPointUnit::Precision FloatingPointUnit::precision;
FloatingPointUnit::Rounding FloatingPointUnit::rounding;
bool FloatingPointUnit::exceptionEnabled[E_max];
// ======================================================================
const WORD PRECISION_MASK = BINARY4(0000,0011,0000,0000);
const WORD PRECISION_24 = BINARY4(0000,0000,0000,0000);
const WORD PRECISION_53 = BINARY4(0000,0010,0000,0000);
const WORD PRECISION_64 = BINARY4(0000,0011,0000,0000);
const WORD ROUND_MASK = BINARY4(0000,1100,0000,0000);
const WORD ROUND_NEAREST = BINARY4(0000,0000,0000,0000);
const WORD ROUND_CHOP = BINARY4(0000,1100,0000,0000);
const WORD ROUND_DOWN = BINARY4(0000,0100,0000,0000);
const WORD ROUND_UP = BINARY4(0000,1000,0000,0000);
const WORD EXCEPTION_PRECISION = BINARY4(0000,0000,0010,0000);
const WORD EXCEPTION_UNDERFLOW = BINARY4(0000,0000,0001,0000);
const WORD EXCEPTION_OVERFLOW = BINARY4(0000,0000,0000,1000);
const WORD EXCEPTION_ZERO_DIVIDE = BINARY4(0000,0000,0000,0100);
const WORD EXCEPTION_DENORMAL = BINARY4(0000,0000,0000,0010);
const WORD EXCEPTION_INVALID = BINARY4(0000,0000,0000,0001);
const WORD EXCEPTION_ALL = BINARY4(0000,0000,0011,1111);
// ======================================================================
void FloatingPointUnit::install(void)
{
precision = P_24;
rounding = R_roundToNearestOrEven;
memset(exceptionEnabled, 0, sizeof(exceptionEnabled));
// preserve all other bits
status = getControlWord();
status &= ~(PRECISION_MASK | ROUND_MASK | EXCEPTION_ALL);
// set to single precision, rounding, and all exceptions masked
status |= PRECISION_24 | ROUND_NEAREST | EXCEPTION_ALL;
// check the config platform flags to see if we should enable some exceptions
if (ConfigSharedFoundation::getFpuExceptionPrecision())
{
exceptionEnabled[E_precision] = true;
status &= ~EXCEPTION_PRECISION;
}
if (ConfigSharedFoundation::getFpuExceptionUnderflow())
{
exceptionEnabled[E_underflow] = true;
status &= ~EXCEPTION_UNDERFLOW;
}
if (ConfigSharedFoundation::getFpuExceptionOverflow())
{
exceptionEnabled[E_overflow] = true;
status &= ~EXCEPTION_OVERFLOW;
}
if (ConfigSharedFoundation::getFpuExceptionZeroDivide())
{
exceptionEnabled[E_zeroDivide] = true;
status &= ~EXCEPTION_ZERO_DIVIDE;
}
if (ConfigSharedFoundation::getFpuExceptionDenormal())
{
exceptionEnabled[E_denormal] = true;
status &= ~EXCEPTION_DENORMAL;
}
if (ConfigSharedFoundation::getFpuExceptionInvalid())
{
exceptionEnabled[E_invalid] = true;
status &= ~EXCEPTION_INVALID;
}
setControlWord(status);
}
// ----------------------------------------------------------------------
void FloatingPointUnit::update(void)
{
WORD currentStatus = getControlWord();
if (currentStatus != status)
{
DEBUG_REPORT_LOG_PRINT(true, ("FPU: update=%d, in mode=%04x, should be in mode=%04x", updateNumber, static_cast<int>(currentStatus), static_cast<int>(status)));
setControlWord(status);
}
++updateNumber;
}
// ----------------------------------------------------------------------
WORD FloatingPointUnit::getControlWord(void)
{
//TODO wtf is this asm statement?
#if 0
WORD controlWord = 0;
__asm fnstcw controlWord;
return controlWord;
#else
return status;
#endif
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setControlWord(WORD controlWord)
{
//TODO see above?
UNREF(controlWord);
#if 0
__asm fldcw controlWord;
#endif
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setPrecision(Precision newPrecision)
{
WORD bits = 0;
switch (precision)
{
case P_24:
bits = PRECISION_24;
break;
case P_53:
bits = PRECISION_53;
break;
case P_64:
bits = PRECISION_64;
break;
case P_max:
default:
DEBUG_FATAL(true, ("bad case"));
}
// record the current state
precision = newPrecision;
// set the proper bit pattern
status &= ~PRECISION_MASK;
status |= bits;
// slam it into the FPU
setControlWord(status);
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setRounding(Rounding newRounding)
{
WORD bits = 0;
switch (newRounding)
{
case R_roundToNearestOrEven:
bits = ROUND_NEAREST;
break;
case R_chop:
bits = ROUND_CHOP;
break;
case R_roundDown:
bits = ROUND_DOWN;
break;
case R_roundUp:
bits = ROUND_UP;
break;
case R_max:
default:
DEBUG_FATAL(true, ("bad case"));
}
// record the current state
rounding = newRounding;
// set the proper bit pattern
status &= ~ROUND_MASK;
status |= bits;
// slam it into the FPU
setControlWord(status);
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setExceptionEnabled(Exception exception, bool enabled)
{
WORD bits = 0;
switch (exception)
{
case E_precision:
bits = EXCEPTION_PRECISION;
break;
case E_underflow:
bits = EXCEPTION_UNDERFLOW;
break;
case E_overflow:
bits = EXCEPTION_OVERFLOW;
break;
case E_zeroDivide:
bits = EXCEPTION_ZERO_DIVIDE;
break;
case E_denormal:
bits = EXCEPTION_DENORMAL;
break;
case E_invalid:
bits = EXCEPTION_INVALID;
break;
case E_max:
default:
DEBUG_FATAL(true, ("bad case"));
}
// record the current state
exceptionEnabled[exception] = enabled;
// twiddle the bit appropriately. these bits masks, so set the bit to disable the exception, clear the bit to enable it.
if (enabled)
status &= ~bits;
else
status |= bits;
// slam it into the FPU
setControlWord(status);
}
// ======================================================================
@@ -1,102 +0,0 @@
// ======================================================================
//
// FloatingPointUnit.h
// jeff grills
//
// copyright 1999 Bootprint Entertainment
//
// ======================================================================
#ifndef FLOATING_POINT_UNIT_H
#define FLOATING_POINT_UNIT_H
// ======================================================================
class FloatingPointUnit
{
public:
enum Precision
{
P_24,
P_53,
P_64,
P_max
};
enum Rounding
{
R_roundToNearestOrEven,
R_chop,
R_roundDown,
R_roundUp,
R_max
};
enum Exception
{
E_precision,
E_underflow,
E_overflow,
E_zeroDivide,
E_denormal,
E_invalid,
E_max
};
private:
static int updateNumber;
static WORD status;
static Precision precision;
static Rounding rounding;
static bool exceptionEnabled[E_max];
public:
static WORD getControlWord(void);
static void setControlWord(WORD controlWord);
public:
static void install(void);
static void update(void);
static void setPrecision(Precision newPrecision);
static void setRounding(Rounding newRounding);
static void setExceptionEnabled(Exception exception, bool enabled);
static Precision getPrecision(void);
static Rounding getRounding(void);
static bool getExceptionEnabled(Exception exception);
};
// ======================================================================
inline FloatingPointUnit::Precision FloatingPointUnit::getPrecision(void)
{
return precision;
}
// ----------------------------------------------------------------------
inline FloatingPointUnit::Rounding FloatingPointUnit::getRounding(void)
{
return rounding;
}
// ----------------------------------------------------------------------
inline bool FloatingPointUnit::getExceptionEnabled(Exception exception)
{
DEBUG_FATAL(static_cast<int>(exception) < 0 || static_cast<int>(exception) >= static_cast<int>(E_max), ("exception out of range")); //lint !e568 // non-negative quantity is never less than 0
return exceptionEnabled[exception];
}
// ======================================================================
#endif
@@ -1,468 +0,0 @@
// ======================================================================
//
// Os.cpp
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedDebug/DebugMonitor.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/FloatingPointUnit.h"
#include "sharedIoWin/IoWinManager.h"
#include <stack>
#include <string>
// ======================================================================
bool Os::installed;
bool Os::runInBackground;
int Os::numberOfUpdates;
int Os::menuValue;
bool Os::paused;
bool Os::wasPaused;
bool Os::gameOver;
bool Os::shouldReturnFromAbort;
char Os::programName[PROGRAM_NAME_SIZE];
char *Os::shortProgramName;
pthread_t Os::mainThreadId;
bool Os::threadDied;
bool Os::isMp;
int Os::processorCount;
// ----------------------------------------------------------------------
namespace OsNamespace
{
class UncatchableException
{
};
}
// ----------------------------------------------------------------------
/**
* Install the Os subsystem for non-games.
*
* This routine is supported for all platforms, although different platforms may
* require different arguments to this routine.
*
* This routine will add Os::remove to the ExitChain.
*
* @see Os::remove()
*/
void Os::install(void)
{
installCommon();
}
// ----------------------------------------------------------------------
/**
* This routine will remove the Os subsystem.
*
* This routine should not be called directly. It will be called from the ExitChain.
*
* @see Os::install()
*/
void Os::remove(void)
{
DEBUG_FATAL(!installed, ("not installed"));
installed = false;
}
// ----------------------------------------------------------------------
void Os::installCommon(void)
{
DEBUG_FATAL(installed, ("already installed"));
ExitChain::add(Os::remove, "Os::remove", 0, true);
#if 0 //TODO For now we won't screw with the priority of the process
HANDLE threadHandle = GetCurrentThread();
DEBUG_FATAL(!SetThreadPriority(threadHandle, THREAD_PRIORITY_ABOVE_NORMAL), ("Failed to set game thread priority"));
#endif
numberOfUpdates = 0;
mainThreadId = pthread_self();
// get the name of the executable
//Can't find UNIX call for this: DWORD result = GetModuleFileName(NULL, programName, sizeof(programName));
strcpy(programName, "TempName");
DWORD result = 1;
FATAL(result == 0, ("GetModuleFileName failed"));
// get the file name without the path
shortProgramName = strrchr(programName, '\\');
if (shortProgramName)
++shortProgramName;
else
shortProgramName = programName;
// determine the number of processors by parsing /proc/cpuinfo
processorCount = 1;
FILE * f = fopen("/proc/cpuinfo", "r");
if (f)
{
char buffer[512];
while (!feof(f))
{
fgets(buffer, 512, f);
if (strncmp(buffer, "processor\t: ", 12)==0)
{
processorCount = atoi(buffer+12)+1;
}
}
fclose(f);
}
isMp = processorCount > 1;
// switch into single-precision floating point mode
FloatingPointUnit::install();
installed = true;
}
// ----------------------------------------------------------------------
bool Os::isMainThread(void)
{
// if the Os class hasn't been installed, then assume we are the main thread.
// otherwise, check to see if our thread id is the main thread id
return !installed || (pthread_self() == mainThreadId);
}
// ----------------------------------------------------------------------
/**
* Terminate the application because of an error condition.
*
* This routine is supported for all platforms.
*
* This routine should not be called directly. The engine and game should use the
* FATAL macro to terminate the application because of an error.
*
* Calling Os::returnFromAbort() will cause the routine to do nothing but return
* immediately.
*
* @see Os::returnFromAbort(), FATAL()
*/
#include <signal.h>
void Os::abort(void)
{
if (!isMainThread())
{
threadDied = true;
pthread_exit(NULL);
}
if (!shouldReturnFromAbort)
{
// let the C runtime deal with the abnormal termination
int * dummy = NULL;
int forceCrash = *dummy;
UNREF(forceCrash);
for (;;)
{
// One of these should work:
pthread_kill(pthread_self(), SIGSEGV);
::kill(0,SIGSEGV);
::abort();
OsNamespace::UncatchableException ex;
throw ex;
sleep(10);
}
}
}
//-----------------------------------------------------------------
/**
* Create the specified directory and all of it's parents.
* @param directory the path to a directory
* @return always true currently
*/
bool Os::createDirectories (const char *directory)
{
//-- construct list of subdirectories all the way down to root
std::stack<std::string> directoryStack;
std::string currentDirectory = directory;
static const char path_seps [] = { '\\', '/', 0 };
// build the stack
while (!currentDirectory.empty())
{
// remove trailing backslash
if (currentDirectory[currentDirectory.size()-1] == '\\' || currentDirectory[currentDirectory.size()-1] == '/')
IGNORE_RETURN(currentDirectory.erase(currentDirectory.size()-1));
if (currentDirectory[currentDirectory.size()-1] == ':')
{
// we've hit something like c:
break;
}
if (!currentDirectory.empty())
directoryStack.push(currentDirectory);
// now strip off current directory
size_t previousDirIndex = currentDirectory.find_last_of (path_seps);
if (previousDirIndex == currentDirectory.npos)
break;
else
IGNORE_RETURN(currentDirectory.erase(previousDirIndex));
}
//-- build all directories specified by the initial directory
while (!directoryStack.empty())
{
// get the directory
currentDirectory = directoryStack.top();
directoryStack.pop();
// try to create it (don't pass any security attributes)
IGNORE_RETURN (mkdir (currentDirectory.c_str(), 0));
}
return true;
}
// ----------------------------------------------------------------------
/**
* Write out a file.
*
* The file name and where the file is written is system-dependent.
*
* @param fileName Name of the file to write
* @param data Data buffer to write to the file
*/
bool Os::writeFile(const char *fileName, const void *data, int length) // Length of the data bufferto write
{
BOOL result;
HANDLE handle;
DWORD written;
// open the file for writing
handle = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// check if it was opened
if (handle == INVALID_HANDLE_VALUE)
return false;
// attempt to write the data
result = WriteFile(handle, data, static_cast<DWORD>(length), &written, NULL);
// make sure the data was written okay
if (!result || written != static_cast<DWORD>(length))
{
static_cast<void>(CloseHandle(handle));
return false;
}
// close the file
result = CloseHandle(handle);
// make sure the close was sucessful
if (!result)
return false;
return true;
}
// ----------------------------------------------------------------------
/**
* Update the Os subsystem.
*
* This routine is supported for all platforms.
*
* For the Win* platforms, this routine will process the windows message pump.
*/
bool Os::update(void)
{
static int ppid = getppid();
FloatingPointUnit::update();
++numberOfUpdates;
#if 0
#ifdef _DEBUG
if (DEBUG_FLAG_PLATFORM(validateHeap))
{
PROFILER_START("validate heap");
MemoryManager::validate();
PROFILER_STOP("validate heap");
}
#endif
#endif
Clock::update();
wasPaused = false;
// if our parent's pid has changed, we tell our caller it should exit
if (getppid() != ppid)
{
WARNING(true, ("Parent process exited!"));
// reset the parent process id, so we don't keep spamming warnings for processes that don't exit because of this
ppid = getppid();
return false;
}
return true;
}
// ----------------------------------------------------------------------
/**
* Formats a message error using GetLastError() and FormatMessge().
*
* The buffer returned from this function is dynamically allocated to prevent
* issues with this routine being called from multiple threads. The caller
* must delete the buffer when it is done.
*
* @return A dynamically allocated buffer containing the error message
*/
char *Os::getLastError(void)
{
return DuplicateString(strerror(errno));
}
// ----------------------------------------------------------------------
bool Os::getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize)
{
// realpath sucks and could cause a buffer overrun. however, it's better than writing it ourselves for now.
char *result = realpath(relativePath, absolutePath);
if (!result)
return false;
FATAL(istrlen(absolutePath)+1 > absolutePathBufferSize, ("buffer overrun"));
return true;
}
// ----------------------------------------------------------------------
/**
* Get the actual system time, in seconds since the epoch.
*
* Do not use this for most game systems, since it does not take into account
* clock sku, game loop times, etc.
*/
time_t Os::getRealSystemTime(void)
{
return time(0);
}
// ----------------------------------------------------------------------
/**
* Convert a time in seconds since the epoch to GMT.
*
*/
void Os::convertTimeToGMT(const time_t &time, tm &zulu)
{
zulu=*gmtime(&time); // gmtime uses a single static tm structure. Yuck!
}
// ----------------------------------------------------------------------
/**
* Convert a tm structure to the time in seconds since the epoch.
*
*/
time_t Os::convertGMTToTime(const tm &zulu)
{
return mktime(const_cast<tm*>(&zulu));
}
// ----------------------------------------------------------------------
/**
* Get a unique identifier for this thread.
*
* @return A unique identifier for this thread.
*/
Os::ThreadId Os::getThreadId()
{
return pthread_self();
}
// ----------------------------------------------------------------------
/**
* Assign the given thread a reasonable name (only works for MSDev 6.0 debugger)
* Since this is Linux-specific, make sure this fuction does nothing
*
*/
void Os::setThreadName(DWORD threadID, const char* threadName)
{
}
// ----------------------------------------------------------------------
/**
* Cause the current thread to sleep for a period of time. If the period is
* zero, the current thread yields it's timeslice.
*/
void Os::sleep(int ms)
{
if (ms == 0)
{
sched_yield();
}
else
{
usleep(ms * 1000);
}
}
// ----------------------------------------------------------------------
/**
* Copy text to the system clipboard.
*
* This routine can be used if the application wants to make some data easily available for pasting (like crash call stacks).
*/
bool Os::copyTextToClipboard(const char *text)
{
UNREF(text);
return false;
}
// ----------------------------------------------------------------------
Os::OsPID_t Os::getProcessId()
{
return getpid();
}
// ----------------------------------------------------------------------
void Os::setProgramName(const char * name)
{
strncpy(programName, name, Os::PROGRAM_NAME_SIZE);
}
// ----------------------------------------------------------------------
bool Os::isFocused()
{
return true;
}
// ----------------------------------------------------------------------
@@ -1,264 +0,0 @@
// ======================================================================
//
// Os.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef OS_H
#define OS_H
#include <pthread.h>
// ======================================================================
struct DebugMenuEntry;
// ======================================================================
class Os
{
public:
typedef pthread_t ThreadId;
typedef pid_t OsPID_t;
enum
{
MAX_PATH_LENGTH = 512
};
typedef void (*QueueCharacterHookFunction)(int keyboard, int character);
typedef void (*SetSystemMouseCursorPositionHookFunction)(int x, int y);
typedef void (*QueueKeyDownHookFunction)(int keyboard, int character);
private:
Os(void);
Os(const Os &);
Os &operator =(const Os &);
enum
{
PROGRAM_NAME_SIZE = 512
};
private:
static void remove(void);
static void installCommon(void);
private:
static bool installed;
static bool runInBackground;
static int numberOfUpdates;
static int menuValue;
static DebugMenuEntry *debugMenuGame;
static bool paused;
static bool wasPaused;
static bool gameOver;
static bool shouldReturnFromAbort;
static bool wantPopupDebugMenu;
static char programName[PROGRAM_NAME_SIZE];
static char *shortProgramName;
static pthread_t mainThreadId;
static bool threadDied;
static bool isMp;
static int processorCount;
public:
static void install(void);
static bool isGameOver(void);
static bool isMainThread(void);
static bool wasApplicationPaused(void);
static bool update(void);
static void returnFromAbort(void);
static void abort(void);
static void requestPopupDebugMenu();
static bool createDirectories (const char *dirname);
static bool writeFile(const char *fileName, const void *data, int length);
static int getNumberOfUpdates(void);
static char *getLastError(void);
static void setThreadName(DWORD threadID, const char* name);
static ThreadId getThreadId();
static const char *getProgramName(void);
static const char *getShortProgramName(void);
static void setProgramName(const char * name);
static bool getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize);
static void sleep(int ms);
static time_t getRealSystemTime(void);
static void convertTimeToGMT(const time_t &time, tm &zulu);
static time_t convertGMTToTime(const tm &zulu);
static bool isMultiprocessor();
static int getProcessorCount();
static bool copyTextToClipboard(const char *text);
static bool wasFocusLost();
static void setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction);
static void setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction);
static OsPID_t getProcessId();
static bool isFocused();
static void setQueueKeyDownHookFunction(QueueKeyDownHookFunction queueKeyDownHookFunction);
};
// ----------------------------------------------------------------------
/**
* Return the full name of the running executable.
*
* The program name will include the path as well.
*
* @return The full name of the running executable
* @see Os::getShortProgramName()
*/
inline const char *Os::getProgramName(void)
{
return programName;
}
// ----------------------------------------------------------------------
/**
* Return the short name of the running executable.
*
* The program name will not include the path, but will just be the file name.
*
* @return The short name of the running executable
* @see Os::getProgramName()
*/
inline const char *Os::getShortProgramName(void)
{
return shortProgramName;
}
// ----------------------------------------------------------------------
/**
* Cause Os::abort() to return instead of abort the process.
*
* This routine should not be called directly by users.
*
* This routine is provided so that structured exception handling can catch
* an exception, call Fatal to run the ExitChain, and rethrow the exception
* so that the debugger will catch it.
*/
inline void Os::returnFromAbort(void)
{
shouldReturnFromAbort = true;
}
// ----------------------------------------------------------------------
/**
* Check if the Os knows the game needs to shut down.
*
* The Os can decide that the game need to end for a number of reasons,
* including closing the application or shutting the machine down.
*
* @return True if the game should quit, otherwise false
*/
inline bool Os::isGameOver(void)
{
return gameOver;
}
// ----------------------------------------------------------------------
/**
* Return the number of updates that the have occurred.
*
* @return This value is updated during the Os::update() routine.
*/
inline int Os::getNumberOfUpdates(void)
{
return numberOfUpdates;
}
// ----------------------------------------------------------------------
/**
* Indicate whether or not the application was paused.
*
* @return True if the application was in the background (paused), otherwise false
*/
inline bool Os::wasApplicationPaused(void)
{
return wasPaused;
}
// ----------------------------------------------------------------------
/**
* Return a flag indicating whether we are running a multiprocessor machine or not.
*
* @return True if the machine has more than one processor, false if not.
*/
inline bool Os::isMultiprocessor(void)
{
return isMp;
}
// ----------------------------------------------------------------------
/**
* Return the number of processors.
*
* @return The number of processors in the machine.
*/
inline int Os::getProcessorCount(void)
{
return processorCount;
}
// ----------------------------------------------------------------------
inline bool Os::wasFocusLost()
{
return false;
}
// ----------------------------------------------------------------------
inline void Os::setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction)
{
}
// ----------------------------------------------------------------------
inline void Os::setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction)
{
}
// ----------------------------------------------------------------------
inline void Os::setQueueKeyDownHookFunction(QueueKeyDownHookFunction)
{
}
// ----------------------------------------------------------------------
#endif
@@ -1,161 +0,0 @@
// ======================================================================
//
// PerThreadData.cpp
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/PerThreadData.h"
#include "sharedSynchronization/Gate.h"
// ======================================================================
pthread_key_t PerThreadData::slot;
bool PerThreadData::slotCreated=false;
// ======================================================================
// Install the per-thread-data subsystem
//
// Remarks:
//
// This routine will install the per-thread-data subsystem that is required for several
// other subsystems in the engine. It should be called from the primary thread before
// any other threads have been created. It will also call threadInstall() for the
// primary thread.
//
// See Also:
//
// PerThreadData::remove()
void PerThreadData::install(void)
{
if (pthread_key_create(&slot, 0)!=0)
{
FATAL(true, ("pthread_key_create failed"));
}
slotCreated=true;
threadInstall();
}
// ----------------------------------------------------------------------
/**
* Remove the per-thread-subsystem.
*
* This routine should be called by the primary thread after all other threads have
* terminated, and no other uses of per-thread-data will occur.
*
* @see PerThreadData::install()
*/
void PerThreadData::remove(void)
{
threadRemove();
if (pthread_key_delete(slot)!=0)
{
FATAL(true, ("pthread_key_delete failed"));
}
slotCreated=false;
}
// ----------------------------------------------------------------------
/**
* Get access to the per-thread-data.
*
* This routine will verify the per-thread-data subsystem has been installed and the
* threadInstall() function has been called for the current thread.
*
* @return A pointer to the per-thread-data.
*/
PerThreadData::Data *PerThreadData::getData(bool allowReturnNull)
{
UNREF(allowReturnNull);
if (!slotCreated)
{
DEBUG_FATAL(true && !allowReturnNull, ("not installed"));
return NULL;
}
Data * const data = reinterpret_cast<Data *>(pthread_getspecific(slot));
DEBUG_FATAL(!data && !allowReturnNull, ("not installed for this thread"));
return data;
}
// ----------------------------------------------------------------------
/**
* Create the per-thread-data for a new thread.
*
* This routine should be called in a thread before the first usage of per-thread-data.
*
* If the client is calling this function on a thread that existed before the engine was
* installed, the client should set isNewThread to false. Setting isNewThread to false
* prevents the function from validating that the thread's TLS is NULL. For threads existing
* before the engine is installed, the TLS data for the thread is undefined.
*
* @param isNewThread [IN] true if the thread was created after the engine was installed, false otherwise
* @see PerThreadData::threadRemove()
*/
void PerThreadData::threadInstall(bool isNewThread)
{
UNREF(isNewThread);
DEBUG_FATAL(!slotCreated, ("not installed"));
// only check for already-set data if this is supposed to be a new thread
DEBUG_FATAL(isNewThread && pthread_getspecific(slot), ("already installed for this thread"));
// create the data
Data * const data = new Data;
// initialize the data
memset(data, 0, sizeof(*data));
//create the event for file streaming reads
data->readGate = new Gate(false);
// set the data into the thread slot
const BOOL result = pthread_setspecific(slot, data);
UNREF(result);
DEBUG_FATAL(result, ("pthread_setspecific failed")); //NB: unlike Windows, returns 0 on success.
} //lint !e429 // Warning -- Custodial pointer 'data' has not been freed or returned) // stored int thread-local-storage
// ----------------------------------------------------------------------
/**
* Destroythe per-thread-data for a terminating thread.
*
* This routine should be called in a thread after the last usage of per-thread-data.
*
* @see PerThreadData::threadInstall()
*/
void PerThreadData::threadRemove(void)
{
DEBUG_FATAL(!slotCreated, ("not installed"));
DEBUG_FATAL(!pthread_getspecific(slot), ("thread not installed"));
// get the data
Data *data = getData();
//close the event used for file streaming reads
delete data->readGate;
data->readGate = NULL;
// wipe the data in the thread slot
const BOOL result2 = pthread_setspecific(slot, NULL);
UNREF(result2);
DEBUG_FATAL(result2, ("TlsSetValue failed")); //NB: unlike Windows, returns 0 on success.
// free the memory
delete data;
}
// ======================================================================
@@ -1,232 +0,0 @@
// ======================================================================
//
// PerThreadData.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef PER_THREAD_DATA_H
#define PER_THREAD_DATA_H
// ======================================================================
#include "../../../../../../engine/shared/library/sharedFoundation/include/public/sharedFoundation/ExitChain.h"
class Gate;
// ======================================================================
/**
* Provide thread local storage functionality.
*
* This class' purpose is to allow each thread to maintain some storage that is local and private to each thread.
* The system must be installed before use. Each thread that may use per-thread-data will also need to call the
* threadInstall() routine after creation and threadRemove() just before termination of the thread.
*/
class PerThreadData
{
private:
struct Data
{
bool exitChainRunning;
bool exitChainFataling;
ExitChain::Entry *exitChainFirstEntry;
int debugPrintFlags;
Gate *readGate;
};
static pthread_key_t slot;
static bool slotCreated;
private:
static Data *getData(bool allowReturnNull=false);
private:
PerThreadData(void);
PerThreadData(const PerThreadData &);
PerThreadData &operator =(const PerThreadData &);
public:
static void install(void);
static void remove(void);
static void threadInstall(bool isNewThread = true);
static void threadRemove(void);
static bool isThreadInstalled(void);
static bool getExitChainRunning(void);
static void setExitChainRunning(bool newValue);
static bool getExitChainFataling(void);
static void setExitChainFataling(bool newValue);
static ExitChain::Entry *getExitChainFirstEntry(void);
static void setExitChainFirstEntry(ExitChain::Entry *newValue);
static int getDebugPrintFlags(void);
static void setDebugPrintFlags(int newValue);
static Gate *getFileStreamerReadGate(void);
};
// ======================================================================
/**
* Determine if the per-thread-data is available for this thread
*
* Return value:
*
* True if the per-thread-data is installed correctly, false otherwise
*
* Remarks:
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* -TRF- looks like Win98 does not zero out a new TLS slot for
* threads existing at the time of slot creation. Thus, if you build a
* plugin that only initializes the engine the first time it is
* used, and other threads already exist in the app, those threads
* will contain bogus non-null data in the TLS slot. If the plugin really
* wants to do lazy initialization of the engine, it will need
* to handle calling PerThreadData::threadInstall() for all existing threads
* (except the thread that initialized the engine, which already
* has its PerThreadData::threadInstall() called).
*/
inline bool PerThreadData::isThreadInstalled(void)
{
return (getData(true) != NULL);
}
// ----------------------------------------------------------------------
/**
* Get the exit chain running flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @return True if the exit chain is running, false otherwise.
* @see ExitChain::isRunning()
*/
inline bool PerThreadData::getExitChainRunning(void)
{
return getData()->exitChainRunning;
}
// ----------------------------------------------------------------------
/**
* Set the exit chain running flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @param newValue New value for the exit chain running flag
*/
inline void PerThreadData::setExitChainRunning(bool newValue)
{
getData()->exitChainRunning = newValue;
}
// ----------------------------------------------------------------------
/**
* Get the exit chain fataling flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @return True if the exit chain is fataling, false otherwise.
* @see ExitChain::isFataling()
*/
inline bool PerThreadData::getExitChainFataling(void)
{
return getData()->exitChainFataling;
}
// ----------------------------------------------------------------------
/**
* Set the exit chain fataling flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @param newValue New value for the exit chain fataling flag
*/
inline void PerThreadData::setExitChainFataling(bool newValue)
{
getData()->exitChainFataling = newValue;
}
// ----------------------------------------------------------------------
/**
* Get the first entry for the exit chain.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
* This routine may return NULL.
*
* @return Pointer to the first entry on the exit chain
* @see ExitChain::isFataling()
*/
inline ExitChain::Entry *PerThreadData::getExitChainFirstEntry(void)
{
return getData()->exitChainFirstEntry;
}
// ----------------------------------------------------------------------
/**
* Set the exit chain fataling flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
* The parameter to this routine may be NULL.
*
* @param newValue New value for the exit chain first entry
*/
inline void PerThreadData::setExitChainFirstEntry(ExitChain::Entry *newValue)
{
getData()->exitChainFirstEntry = newValue;
}
// ----------------------------------------------------------------------
/**
* Get the debug print flags.
*
* This routine is not intended for general use; it should only be used by the DebugPrint functions.
*
* @return Current value of the debug print flags
*/
inline int PerThreadData::getDebugPrintFlags(void)
{
return getData()->debugPrintFlags;
}
// ----------------------------------------------------------------------
/**
* Set the debug print flags value.
*
* This routine is not intended for general use; it should only be used by the DebugPrint functions.
*/
inline void PerThreadData::setDebugPrintFlags(int newValue)
{
getData()->debugPrintFlags = newValue;
}
// ----------------------------------------------------------------------
inline Gate *PerThreadData::getFileStreamerReadGate(void)
{
return getData()->readGate;
}
// ======================================================================
#endif
@@ -1,273 +0,0 @@
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/PlatformGlue.h"
#include <ctime>
real abs(real x)
{
return fabs(x);
}
int _stricmp(const char* string1, const char* string2)
{
int first, second;
do
{
first = toupper(*string1);
second = toupper(*string2);
string1++;
string2++;
} while (first && first==second);
return (first - second);
}
char* _itoa(int value, char* stringOut, int radix)
{
DEBUG_FATAL((radix != 10), ("itoa only supprts base 10"));
sprintf(stringOut, "%d", value);
return stringOut;
}
bool QueryPerformanceCounter(__int64* time)
{
struct timeval tv;
gettimeofday(&tv, NULL);
*time = static_cast<LARGE_INTEGER>(tv.tv_sec);
*time = (*time * 1000000) + static_cast<LARGE_INTEGER>(tv.tv_usec);
return TRUE;
}
bool QueryPerformanceFrequency(__int64 *freq)
{
*freq = CLOCKS_PER_SEC;
return TRUE;
}
void Sleep(DWORD msecs)
{
//Sleep takes a time to sleep in milliseconds.
usleep(msecs*1000); //usleep works with microseconds
}
int GetLastError()
{
return errno;
}
void OutputDebugString(const char* stringOut)
{
fprintf(stderr,"%s",stringOut);
}
//File Support
BOOL WriteFile(FILE* hFile, const void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesWritten, void* unsup)
{
int retval;
if(unsup)
return FALSE; //Windows doesn't support this overrlap buffer
retval = fwrite(lpBuffer, sizeof(char), numBytesToWrite, hFile);
*numBytesWritten = retval;
return (retval < 0) ? FALSE : TRUE;
}
BOOL ReadFile(FILE* hFile, void* lpBuffer, DWORD numBytesToRead, DWORD* numBytesRead, void* unsup)
{
int retval;
if(unsup)
return FALSE; //Windows doesn't support this overrlap buffer
retval = fread(lpBuffer, sizeof(char), numBytesToRead, hFile);
*numBytesRead = retval;
return (retval <= 0) ? FALSE : TRUE;
}
DWORD SetFilePointer(FILE* hFile, long lDistanceToMove, long* lpDistanceToMoveHigh, DWORD dwMoveMethod)
{
//Mimics the Win32 function to set the position of a file pointer. return -1 on failure else current position.
int retval;
retval = fseek(hFile, lDistanceToMove, dwMoveMethod);
return (retval == 0) ? ftell(hFile) : -1;
}
//TODO Consider using a call to open() instead of fopen() to get a better mapping of parameters to Win32
FILE* CreateFile(const char* fileName, DWORD access, DWORD shareMode, void* unsupA, DWORD creationDisposition, DWORD flagsAndAttributes, FILE* unsupB)
{
FILE* retval = 0;
DEBUG_FATAL(flagsAndAttributes != FILE_ATTRIBUTE_NORMAL, ("Unsupported File mode call to CreateFile()"));
DEBUG_FATAL(unsupB != NULL, ("Unsupported File mode call to CreateFile()"));
//DEBUG_FATAL(shareMode != 0, ("Unsupported File mode call to CreateFile()"));
DEBUG_FATAL(unsupA != 0, ("Unsupported File mode call to CreateFile()"));
switch(creationDisposition)
{
case CREATE_NEW:
retval = fopen(fileName, "r");
if (retval)
{
fclose(retval);
retval = NULL;
}
else
{
fclose(retval);
retval = fopen(fileName, "w");
}
break;
case CREATE_ALWAYS:
retval = fopen(fileName, "w");
break;
case OPEN_EXISTING:
retval = fopen(fileName, "r");
if ((access & GENERIC_WRITE) && retval)
{
fclose(retval);
retval = fopen(fileName, "a");
rewind(retval);
}
break;
case OPEN_ALWAYS:
if (access & GENERIC_WRITE)
{
retval = fopen(fileName, "a");
rewind(retval);
}
else
{
retval = fopen(fileName, "r");
}
break;
case TRUNCATE_EXISTING:
DEBUG_FATAL(!(access & GENERIC_WRITE),("Must open truncate file with write access"));
retval = fopen(fileName, "w");
break;
}
return retval;
}
BOOL CloseHandle(FILE* hFile)
{
int retval = fclose(hFile);
return (retval == 0) ? TRUE : FALSE;
}
//TODO There must be a more elegant UNIX command to get file size...fstat() needs filename
DWORD GetFileSize(FILE* hFile, DWORD* lpHighSize)
{
long int curPos;
DWORD endPos;
curPos = ftell(hFile);
fseek(hFile, 0, SEEK_END);
endPos = ftell(hFile);
fseek(hFile, curPos, SEEK_SET);
return endPos;
#if 0
//This is what I want to do, but I have no file des number
struct stat buf;
fstat(hFile, &buf);
return buf->st_size;
#endif
}
BOOL FileExists(const char* filename)
{
BOOL retval = false;
struct stat info;
if (stat(filename, &info) == 0)
{
if (S_ISREG(info.st_mode))
retval = true;
}
return retval;
}
//Memory Functions
void* VirtualAlloc(void* location, DWORD size, DWORD flAllocationType, DWORD flProtect)
{
if (location)
return location;
return malloc(size);
}
BOOL VirtualFree(void* location, DWORD size, DWORD freeType)
{
free(location);
return TRUE;
}
BOOL VirtualProtect(void* location, DWORD size, DWORD newProtect, DWORD* oldProect)
{
//Unused. Function stub for compatibility
return TRUE;
}
BOOL IsBadReadPtr(const void* location, unsigned int size)
{
//unused
return TRUE;
}
void MessageBox (void* unused, const char* message, const char* unused2, int flags)
{
OutputDebugString(message);
}
char *ConvertCommandLine(int argc, char ** argv)
{
static char buffer[2048];
int totalSize=0;
for (int i=0; i<argc; ++i)
{
totalSize+=strlen(argv[i])+1;
}
if(totalSize>1023)
{
int argIndex = 0;
fprintf(stderr, "Exceeded command line args length of %d. Total size is %d\n", sizeof(buffer), totalSize);
for(argIndex = 0; argIndex < argc; ++argIndex)
{
fprintf(stderr, "argv[%d]=\"%s\"\n", argIndex, argv[argIndex]);
}
FATAL(true,("Command line exceeds maximum length."));
}
buffer[0]='\0';
for (int i=0; i<argc; ++i)
{
strcat(buffer,argv[i]);
if (i!=argc-1)
{
strcat(buffer," ");
}
}
return buffer;
}
@@ -1,125 +0,0 @@
#ifndef INCLUDED_MISC_H
#define INCLUDED_MISC_H
#include <netinet/in.h>
#include <sys/time.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
typedef unsigned short int WORD;
typedef unsigned long int DWORD;
typedef bool BOOL;
typedef long long __int64; //lint !e13 !e19 // Error: 13 (Bad type), Error: 19 (Useless declaration) // -TRF- Lint preprocessor discrepency, @todo look into this.
typedef __int64 LARGE_INTEGER;
const BOOL FALSE = 0;
const BOOL TRUE = 1;
float abs(float x);
int _stricmp(const char* string1, const char* string2);
//String to numeric conversions
char* _itoa(int value, char* stringOut, int radix);
//Format specifier for non-portable printf
#define UINT64_FORMAT_SPECIFIER "%llu"
#define INT64_FORMAT_SPECIFIER "%lli"
//Constant definition macro for 64 bit values
#define UINT64_LITERAL(a) a ## ull
#define INT64_LITERAL(a) a ## ll
bool QueryPerformanceCounter(__int64 *time);
bool QueryPerformanceFrequency(__int64 *freq);
void Sleep(DWORD msecs);
int GetLastError();
void OutputDebugString(const char* stringOut);
//File Support
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
typedef FILE* HANDLE;
#define INVALID_HANDLE_VALUE NULL //Have to use a #define because this may be a FILE*
const int GENERIC_READ = 1 << 0;
const int GENERIC_WRITE = 1 << 1;
const int CREATE_NEW = 1;
const int CREATE_ALWAYS = 2;
const int OPEN_EXISTING = 3;
const int OPEN_ALWAYS = 4;
const int TRUNCATE_EXISTING = 5;
const DWORD FILE_ATTRIBUTE_NORMAL = 1;
const int FILE_CURRENT = SEEK_CUR;
const int FILE_BEGIN = SEEK_SET;
const int FILE_END = SEEK_END;
const int FILE_SHARE_READ = 1;
BOOL WriteFile(FILE* hFile, const void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesWritten, void* unsup=NULL);
BOOL ReadFile(FILE* hFile, void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesRead, void* unsup=NULL);
DWORD SetFilePointer(FILE* hFile, long lDistanceToMove, long* lpDistanceToMoveHigh, DWORD dwMoveMethod);
FILE* CreateFile(const char* fileName, DWORD access, DWORD shareMode, void* unsupA, DWORD creationDisposition, DWORD flagsAndAttributes, FILE* unsup2);
BOOL CloseHandle(FILE* hFile);
DWORD GetFileSize(FILE* hFile, DWORD* lpHighSize);
BOOL FileExists(const char* fileName);
//Memory Support
const int MEM_RESERVE = 0;
const int MEM_COMMIT = 1;
const int PAGE_READWRITE = 0;
const int MEM_RELEASE = 0;
const int PAGE_NOACCESS = 0;
void* VirtualAlloc(void* location, DWORD size, DWORD flAllocationType, DWORD flProtect);
BOOL VirtualFree(void* location, DWORD size, DWORD freeType);
BOOL VirtualProtect(void* location, DWORD size, DWORD newProtect, DWORD* oldProect);
BOOL IsBadReadPtr(const void* location, unsigned int size);
//Misc output stuff
const int MB_OK = 0;
const int MB_ICONEXCLAMATION = 1;
void MessageBox (void* unused, const char* message, const char* unused2, int flags);
char *ConvertCommandLine(int argc, char ** argv);
//String functions
#define _vsnprintf vsnprintf
//-----------------------------------------------------------------
inline int _strnicmp (const char * a, const char * b, size_t count)
{
return ::strncasecmp (a, b, count);
}
//-----------------------------------------------------------------
inline int _open(const char *filename, int oflag) { return open(filename, oflag); }
inline int _open(const char *filename, int oflag, mode_t pmode) { return open(filename, oflag, pmode); }
inline int _creat(const char *filename, mode_t pmode) { return creat(filename, pmode); }
inline int _close(int fd) { return close(fd); }
inline int _write(int fd, const void *buffer, unsigned int count) { return write(fd, buffer, count); }
inline int _dup(int fd) { return dup(fd); }
inline int _dup2(int oldfd, int newfd) { return dup2(oldfd, newfd); }
inline long _lseek(int fd, long offset, int origin) { return lseek(fd, offset, origin); }
inline int _read(int fd, void *buffer, unsigned int count) { return read(fd, buffer, count); }
inline long _tell(int fd) { return _lseek(fd,0,SEEK_CUR); }
inline int _umask(int pmode) { return umask(pmode); }
inline int _unlink(const char *pathname) { return unlink(pathname); }
//-----------------------------------------------------------------
#endif //INCLUDED_MISC_H
@@ -1,185 +0,0 @@
// ======================================================================
//
// SetupSharedFoundation.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2001 - 2002 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedDebug/ConfigSharedDebugLinux.h"
#include "sharedDebug/DebugMonitor.h"
#include "sharedDebug/Profiler.h"
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/CommandLine.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/PerThreadData.h"
#include "sharedFoundation/StaticCallbackEntry.h"
#include <ctime>
#include <math.h>
// ======================================================================
/**
* Install the engine.
*
* The settings in the Data structure will determine which subsystems
* get initialized.
*/
void SetupSharedFoundation::install(const Data &data)
{
// and get the command line stuff in quick so we can make decisions based on the command line settings
CommandLine::install();
ConfigFile::install();
if (data.lpCmdLine)
CommandLine::absorbString(data.lpCmdLine);
if (data.argc)
CommandLine::absorbStrings(const_cast<const char**>(data.argv+1), data.argc-1);
#if 0
//currently there's a problem that we cannot override the defaults here.
if (data.configFile)
IGNORE_RETURN(ConfigFile::loadFile(data.configFile));
#endif
// get the post command-line text for the ConfigFile (key-value pairs)
const char *configString = CommandLine::getPostCommandLineString();
if (configString)
ConfigFile::loadFromCommandLine(configString);
//@todo there is a lot of stuff in win32 setup not here...like exitchain
Profiler::registerDebugFlags();
#if _DEBUG
MemoryManager::registerDebugFlags();
#endif//_DEBUG
// Setup Linux DebugMonitor support.
// @todo fix this dependency: DebugMonitor really should be moved into Foundation the way things currently are. TRF is following the existing win32 setup.
#ifdef _DEBUG
ConfigSharedDebugLinux::install();
DebugMonitor::install();
#endif
// setup the engine configuration
ConfigSharedFoundation::Defaults defaults;
defaults.frameRateLimit = data.frameRateLimit;
ConfigSharedFoundation::install(defaults);
SetWarningStrictFatal(ConfigFile::getKeyBool("SharedDebug", "strict", false));
Report::install();
Clock::install(data.runInBackground, false);
PersistentCrcString::install();
CrcLowerString::install();
StaticCallbackEntry::install();
}
// ----------------------------------------------------------------------
// Call a function with appropriate exception handling (not)
//
// Remarks:
//
// this is stubbed and exception handling is ignored currently
void SetupSharedFoundation::callbackWithExceptionHandling(
void (*callback)(void) // Routine to call with exception handling
)
{
if (ConfigSharedFoundation::getNoExceptionHandling())
{
callback();
}
else
{
#if 0
try
{
callback();
}
catch (__exception * mathException)
{
FATAL(true, ("Math Exception: %s\n", mathException->name));
}
catch (const char* message)
{
FATAL(true, ("Character Exception: %s\n", message));
}
catch(std::exception & m)
{
const char * c = m.what();
FATAL(true, ("Std::exception: %s\n", c));
}
catch(...)
{
FATAL(true, ("Unknown exception\n"));
}
#else
callback();
#endif
}
}
// ----------------------------------------------------------------------
/**
* Uninstall the engine.
*
* This routine will properly uninstall the engine componenets that were
* installed by SetupSharedFoundation::install().
*/
void SetupSharedFoundation::remove(void)
{
ExitChain::quit();
if (GetNumberOfWarnings())
REPORT(true, Report::RF_print | Report::RF_log | Report::RF_dialog, ("%d warnings logged", GetNumberOfWarnings()));
// this routine can't be on the exit chain because the exit chain depends upon the PerThreadData class being around
//PerThreadData::remove();
}
// ----------------------------------------------------------------------
SetupSharedFoundation::Data::Data(Defaults defaults)
{
Zero(*this);
switch (defaults)
{
case D_game:
runInBackground = true;
lpCmdLine = NULL;
argc = 0;
argv = NULL;
configFile = NULL;
frameRateLimit = CONST_REAL(0);
break;
case D_console:
runInBackground = true;
lpCmdLine = NULL;
argc = 0;
argv = NULL;
configFile = NULL;
frameRateLimit = CONST_REAL(0);
break;
default:
DEBUG_FATAL(true, ("unknown case"));
}
}
// ======================================================================
@@ -1,58 +0,0 @@
// ======================================================================
//
// SetupSharedFoundation.h
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_SetupSharedFoundation_H
#define INCLUDED_SetupSharedFoundation_H
// ======================================================================
struct DebugMenuEntry;
// ======================================================================
class SetupSharedFoundation
{
public:
struct Data
{
// allow running in background
bool runInBackground;
// pointer to command line
char* lpCmdLine;
int argc;
char **argv;
const char *configFile;
real frameRateLimit;
public:
enum Defaults
{
D_game,
D_console
};
Data(Defaults defaults);
};
public:
static void install(const Data &data);
static void remove(void);
static void callbackWithExceptionHandling(void (*callback)(void));
};
// ======================================================================
#endif
@@ -1,35 +0,0 @@
// ======================================================================
//
// vsnprintf.cpp
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/vsnprintf.h"
#include <cstdio>
// ======================================================================
// Format a printf-style string into a text buffer of fixed size
//
// Return value:
//
// The number of characters written into the buffer, or -1 if the buffer was too small
//
// Remarks:
//
// If the buffer would overflow, the null terminating character is not written and -1
// will be returned.
#ifdef _MSC_VER
int vsnprintf(char *buffer, size_t count, const char *format, va_list va)
{
return _vsnprintf(buffer, count, format, va);
}
#endif
// ======================================================================
@@ -1,24 +0,0 @@
// ======================================================================
//
// vsnprintf.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef VSNPRINTF_H
#define VSNPRINTF_H
// ======================================================================
#ifdef _MSC_VER
int vsnprintf(char *buffer, size_t count, const char *format, va_list va);
#endif
// ======================================================================
#endif
@@ -18,7 +18,6 @@
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedFoundation/CrashReportInformation.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/FloatingPointUnit.h"
#include "sharedFoundation/Production.h"
@@ -80,7 +79,6 @@ namespace OsNamespace
Os::IMEHookFunction ms_IMEHookFunction;
Os::QueueKeyDownHookFunction ms_queueKeyDownHookFunction;
int ms_processorCount;
int ms_debugKeyIndex;
int ms_SystemMouseCursorPositionX;
int ms_SystemMouseCursorPositionY;
@@ -245,106 +243,6 @@ void Os::installCommon()
// switch into single-precision floating point mode
FloatingPointUnit::install();
// get the amount of memory
MEMORYSTATUS memoryStatus;
GlobalMemoryStatus(&memoryStatus);
CrashReportInformation::addStaticText("Ram: %dmb\n", memoryStatus.dwTotalPhys / (1024 * 1024));
// log the os information
{
OSVERSIONINFO versionInfo;
Zero(versionInfo);
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&versionInfo);
CrashReportInformation::addStaticText("Os1: %d.%d.%d\n", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion, versionInfo.dwBuildNumber);
char const * os = "Unknown";
char CDECL pwine_get_version;
HMODULE hntdll = GetModuleHandle("ntdll.dll");
switch (versionInfo.dwMajorVersion) {
case 4:
switch (versionInfo.dwMinorVersion){
case 10:
os = "Windows 98";
break;
case 90:
os = "Windows ME";
break;
}
break;
case 5:
switch (versionInfo.dwMinorVersion) {
case 0:
os = "Windows 2000";
break;
case 1:
os = "Windows XP";
break;
case 2:
os = "Windows 2003";
break;
}
break;
case 6:
switch (versionInfo.dwMinorVersion){
case 0:
os = "Windows Vista";
break;
case 1:
os = "Windows 7";
break;
case 2:
os = "Windows 8";
break;
case 3:
os = "Windows 8.1";
break;
}
break;
case 10:
os = "Windows 10";
break;
}
//detect WINE
if (hntdll)
{
pwine_get_version = (char)GetProcAddress(hntdll, "wine_get_version");
if (pwine_get_version)
{
os = strcat("Wine ", &pwine_get_version);
}
}
CrashReportInformation::addStaticText("Os2: %s %s\n", os, versionInfo.szCSDVersion);
}
// get the number of processors
SYSTEM_INFO si;
GetSystemInfo(&si);
ms_processorCount = static_cast<int>(si.dwNumberOfProcessors);
REPORT_LOG (ConfigSharedFoundation::getVerboseHardwareLogging(), ("Processor Count: %i\n", ms_processorCount));
CrashReportInformation::addStaticText("NumProc: %d\n", ms_processorCount);
{
HKEY key;
LONG result = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_EXECUTE, &key);
if (result == ERROR_SUCCESS)
{
DWORD data;
DWORD type = REG_DWORD;
DWORD size = sizeof (data);
result = RegQueryValueEx (key, "~MHz", NULL, &type, reinterpret_cast<LPBYTE> (&data), &size);
if ((result == ERROR_SUCCESS) && (size > 0))
REPORT_LOG (ConfigSharedFoundation::getVerboseHardwareLogging(), ("Processor Speed: %i MHz\n", data));
RegCloseKey (key);
}
}
if (!GetKeyboardLayoutName(ms_keyboardLayout))
ms_keyboardLayout[0] = '\0';
@@ -495,30 +393,6 @@ bool Os::wasFocusLost()
return ms_wasFocusLost;
}
// ----------------------------------------------------------------------
/**
* Return a flag indicating whether we are running a multiprocessor machine or not.
*
* @return True if the machine has more than one processor, false if not.
*/
bool Os::isMultiprocessor()
{
return ms_processorCount > 1;
}
// ----------------------------------------------------------------------
/**
* Return the number of processors.
*
* @return The number of processors in the machine.
*/
int Os::getProcessorCount()
{
return ms_processorCount;
}
// ----------------------------------------------------------------------
bool Os::isMainThread()
@@ -1662,10 +1536,7 @@ bool Os::isFocused()
bool Os::launchBrowser(std::string const & website)
{
std::string URL("http://");
if (strncmp(URL.c_str(), website.c_str(),7)!=0)
URL+=website;
else
URL=website;
URL=website;
int result = reinterpret_cast<int>(ShellExecute(NULL, "open", URL.c_str(), NULL, NULL, SW_SHOWNORMAL));
return (result > 32);
}
@@ -109,9 +109,6 @@ public:
static void convertTimeToGMT(const time_t &time, tm &zulu);
static time_t convertGMTToTime(const tm &zulu);
static bool isMultiprocessor();
static int getProcessorCount();
static void buildRelativePath(const char *baseDirectory, const char *targetPathname, std::string &relativePath);
static bool getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize);
@@ -1,30 +0,0 @@
// PRIVATE. Do not export this header file outside the package.
#ifndef INCLUDED_FoundationTypesLinux_H
#define INCLUDED_FoundationTypesLinux_H
// ======================================================================
// specify what platform we're running on.
#define PLATFORM_UNIX
#define PLATFORM_LINUX
#include <cstdio>
// ======================================================================
// basic types that we assume to be around
typedef unsigned int uint;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef signed char int8;
typedef signed short int16;
typedef signed long int32;
typedef signed long long int int64;
typedef unsigned long long int uint64;
typedef float real;
typedef FILE* FILE_HANDLE;
#endif
@@ -1,74 +0,0 @@
// ======================================================================
//
// StderrLogger.cpp
//
// Copyright 2003 Sony Online Entertainment
//
// ======================================================================
#include "sharedLog/FirstSharedLog.h"
#include "sharedLog/StderrLogger.h"
#include "sharedLog/Log.h"
#include <string>
#include <fcntl.h>
// ======================================================================
namespace StderrLoggerNamespace
{
bool s_installed;
int s_oldStderr;
int s_stderrPipe[2];
}
using namespace StderrLoggerNamespace;
// ======================================================================
void StderrLogger::install()
{
DEBUG_FATAL(s_installed, ("StderrLogger already installed"));
s_installed = true;
s_oldStderr = dup(2);
pipe(s_stderrPipe);
dup2(s_stderrPipe[1], 2);
fcntl(s_stderrPipe[0], F_SETFL, O_NONBLOCK);
}
// ----------------------------------------------------------------------
void StderrLogger::remove()
{
DEBUG_FATAL(!s_installed, ("StderrLogger not installed"));
dup2(s_oldStderr, 2);
close(s_stderrPipe[0]);
close(s_stderrPipe[1]);
s_installed = false;
}
// ----------------------------------------------------------------------
void StderrLogger::update()
{
if (!s_installed)
return;
char buf[8192];
int nRead = read(s_stderrPipe[0], buf, sizeof(buf)-1);
if (nRead > 0)
{
int startPos = 0;
while (startPos < nRead)
{
int endPos = startPos;
while (buf[endPos] != '\n' && endPos < nRead)
++endPos;
buf[endPos] = 0;
if (endPos > startPos)
LOG("stderr", ("%s", buf+startPos));
startPos = endPos+1;
}
}
}
// ======================================================================
@@ -1,40 +0,0 @@
// ======================================================================
//
// OsMemory.cpp
//
// Copyright 2002 Sony Online Entertainment
//
// ======================================================================
#include "sharedMemoryManager/FirstSharedMemoryManager.h"
#include "sharedMemoryManager/OsMemory.h"
// ======================================================================
void OsMemory::install()
{
}
// ----------------------------------------------------------------------
void OsMemory::remove()
{
}
// ----------------------------------------------------------------------
void *OsMemory::commit(void *, size_t bytes)
{
return ::malloc(bytes);
}
// ----------------------------------------------------------------------
bool OsMemory::free(void *addr, size_t)
{
::free(addr);
return true;
}
// ======================================================================
@@ -1,29 +0,0 @@
// ======================================================================
//
// OsMemory.h
//
// Copyright 2002 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_OsMemory_H
#define INCLUDED_OsMemory_H
// ======================================================================
class OsMemory
{
public:
static void install();
static void remove();
static void * reserve(size_t bytes);
static void * commit(void *addr, size_t bytes);
static bool free(void *addr, size_t bytes);
static bool protect(void *addr, size_t bytes, bool allowAccess);
};
// ======================================================================
#endif // INCLUDED_OsMemory_H
@@ -1,134 +0,0 @@
// ======================================================================
//
// OsNewDel.cpp
//
// Copyright 2002 Sony Online Entertainment
//
// ======================================================================
#include "sharedMemoryManager/FirstSharedMemoryManager.h"
#include "sharedMemoryManager/MemoryManager.h"
#include "sharedMemoryManager/OsNewDel.h"
#include <malloc.h>
#include <unistd.h>
#include <sys/mman.h>
static MemoryManager memoryManager __attribute__ ((init_priority (101)));
#define USE_LIBC_MALLOC_HOOKS 0
#if USE_LIBC_MALLOC_HOOKS
extern "C"
{
void memoryManagerFreeHook(__malloc_ptr_t __ptr, __const __malloc_ptr_t)
{
delete[] (char *)__ptr;
}
__malloc_ptr_t memoryManagerMallocHook(size_t __size, const __malloc_ptr_t)
{
return new char[__size];
}
__malloc_ptr_t memoryManagerReallocHook(__malloc_ptr_t __ptr, size_t size, __const __malloc_ptr_t)
{
if(! __ptr)
return new char[size];
return MemoryManager::reallocate(__ptr, size);
}
__malloc_ptr_t memoryManagerMemAlignHook(size_t alignment, size_t size, __const __malloc_ptr_t)
{
DEBUG_FATAL(true, ("memalign not implemented!"));
return new char[size];
}
static void memoryManagerMallocInitializeHook(void)
{
__free_hook = memoryManagerFreeHook;
__malloc_hook = memoryManagerMallocHook;
__realloc_hook = memoryManagerReallocHook;
__memalign_hook = memoryManagerMemAlignHook;
}
void (*__malloc_initialize_hook) (void) = memoryManagerMallocInitializeHook;
}
#endif//USE_LIBC_MALLOC_HOOKS
// ======================================================================
void *operator new(size_t size, MemoryManagerNotALeak) throw (std::bad_alloc)
{
return MemoryManager::allocate(size, reinterpret_cast<uint32>(__builtin_return_address(0)), false, false);
}
// ----------------------------------------------------------------------
void *operator new(size_t size) throw (std::bad_alloc)
{
return MemoryManager::allocate(size, reinterpret_cast<uint32>(__builtin_return_address(0)), false, true);
}
// ----------------------------------------------------------------------
void *operator new[](size_t size) throw (std::bad_alloc)
{
return MemoryManager::allocate(size, reinterpret_cast<uint32>(__builtin_return_address(0)), true, true);
}
// ----------------------------------------------------------------------
void *operator new(size_t size, const char *file, int line) throw (std::bad_alloc)
{
return MemoryManager::allocate(size, reinterpret_cast<uint32>(__builtin_return_address(0)), false, true);
}
// ----------------------------------------------------------------------
void *operator new[](size_t size, const char *file, int line) throw (std::bad_alloc)
{
return MemoryManager::allocate(size, reinterpret_cast<uint32>(__builtin_return_address(0)), true, true);
}
// ----------------------------------------------------------------------
void operator delete(void *pointer) throw()
{
if (pointer)
MemoryManager::free(pointer, false);
}
// ----------------------------------------------------------------------
void operator delete[](void *pointer) throw()
{
if (pointer)
MemoryManager::free(pointer, true);
}
// ----------------------------------------------------------------------
void operator delete(void *pointer, const char *file, int line) throw()
{
UNREF(file);
UNREF(line);
if (pointer)
MemoryManager::free(pointer, false);
}
// ----------------------------------------------------------------------
void operator delete[](void *pointer, const char *file, int line) throw()
{
UNREF(file);
UNREF(line);
if (pointer)
MemoryManager::free(pointer, true);
}
// ======================================================================
@@ -1,33 +0,0 @@
// ======================================================================
//
// OsNewDel.h
//
// Copyright 2002 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_OsNewDel_H
#define INCLUDED_OsNewDel_H
// ======================================================================
enum MemoryManagerNotALeak
{
MM_notALeak
};
void *operator new(size_t size, MemoryManagerNotALeak) throw(std::bad_alloc);
void *operator new(size_t size) throw(std::bad_alloc);
void *operator new[](size_t size) throw(std::bad_alloc);
void *operator new(size_t size, char const *file, int line) throw(std::bad_alloc);
void *operator new[](size_t size, char const *file, int line) throw(std::bad_alloc);
void operator delete(void *pointer) throw();
void operator delete[](void *pointer) throw();
void operator delete(void *pointer, char const *file, int line) throw();
void operator delete[](void *pointer, char const *file, int line) throw();
// ======================================================================
#endif // INCLUDED_OsNewDel_H
@@ -1,372 +0,0 @@
//---------------------------------------------------------------------
#include "FirstSharedNetwork.h"
#include "Address.h"
#include <cassert>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>
//---------------------------------------------------------------------
Address::Address() :
addr4(new struct sockaddr_in),
hostAddress("0.0.0.0")
{
memset(addr4, 0, sizeof(struct sockaddr_in));
addr4->sin_family = AF_INET;
}
//---------------------------------------------------------------------
Address::Address(const std::string & newHostAddress, unsigned short newHostPort) :
addr4(new struct sockaddr_in),
hostAddress(newHostAddress)
{
struct hostent * h;
unsigned long u;
memset(addr4, 0, sizeof(struct sockaddr_in));
addr4->sin_port = htons(newHostPort);
addr4->sin_family = AF_INET;
// was an address supplied?
if(hostAddress.size() > 0)
{
// Is the first byte a number? (IP names begin with an alpha)
if(!isdigit(hostAddress[0]))
{
// The first byte is a letter, resolve it
if( (h = gethostbyname(hostAddress.c_str())) != 0)
{
memcpy(&addr4->sin_addr, h->h_addr_list[0], sizeof(addr4->sin_addr));
}
else
{
// boom! grab the entry from the h_addr member instead!
if( (h = gethostbyname(hostAddress.c_str())) != 0)
{
memcpy(&addr4->sin_addr, h->h_addr, sizeof(addr4->sin_addr));
}
else
{
// no resolution, INADDR_ANY
memset(&addr4->sin_addr, 0, sizeof(addr4->sin_addr));
// in debug, fail, something is wrong.
// potential problems - an insanely bogus address was
// passed or the host system is misconfigured and cannot
// resolve the name
assert(false);
}
}
char addrbuf[17] = {"\0"};
unsigned char * a = (unsigned char *)&addr4->sin_addr;
snprintf(addrbuf, sizeof(addrbuf), "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
hostAddress = addrbuf;
}
else
{
// A dotted decimal ip number string was supplied. Convert for sin_addr
u = inet_addr(hostAddress.c_str());
memcpy(&addr4->sin_addr, &u, sizeof(addr4->sin_addr));
}
}
else
{
// nothing was supplied, assign INADDR_ANY
addr4->sin_addr.s_addr = INADDR_ANY;
}
}
//---------------------------------------------------------------------
Address::Address(const Address & source) :
addr4(new struct sockaddr_in),
hostAddress(source.hostAddress)
{
*addr4 = *source.addr4;
}
//---------------------------------------------------------------------
Address::Address(const struct sockaddr_in & ipv4addr) :
addr4(new struct sockaddr_in),
hostAddress("")
{
convertFromSockAddr(ipv4addr);
}
//---------------------------------------------------------------------
Address::~Address()
{
delete addr4;
}
//---------------------------------------------------------------------
Address & Address::operator = (const Address & rhs)
{
if(this != &rhs)
{
hostAddress = rhs.hostAddress;
*addr4 = *rhs.addr4;
}
return *this;
}
//---------------------------------------------------------------------
Address & Address::operator = (const struct sockaddr_in & rhs)
{
convertFromSockAddr(rhs);
return *this;
}
//---------------------------------------------------------------------
void Address::convertFromSockAddr(const struct sockaddr_in & source)
{
// extract IP bytes from ipv4add4
const unsigned char * ip;
char name[17] = {"\0"};
ip = reinterpret_cast<const unsigned char *>(&source.sin_addr);
snprintf(name, 17, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); //lint !e534
hostAddress = name;
*addr4 = source;
}
//---------------------------------------------------------------------
/**
@brief get a human readable host address
Example:
\code
void foo(struct sockaddr_in & a)
{
Address b(a);
printf("address = %%s\\n", b.getHostAddress().c_str());
}
\endcode
@return A human readable host address string
@author Justin Randall
*/
const std::string & Address::getHostAddress() const
{
return hostAddress;
}
//---------------------------------------------------------------------
/**
@brief get the port associated with this address
Example:
\code
void foo(struct sockaddr_in & a)
{
Address b(a);
printf("port = %%i\\n", b.getHostPort());
}
\endcode
@return A human readable port in host-byte order associated with
this address.
@author Justin Randall
*/
const unsigned short Address::getHostPort() const
{
return ntohs(addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief get the BSD sockaddr describing this address
Example:
\code
void foo(SOCKET s, unsigned char * d, int l, const Address & a)
{
int t = sizeof(struct sockaddr_in);
sendto(s, s, l, 0, reinterpret_cast<const struct sockaddr *>(&(a.getSockAddr4())), t);
}
\endcode
@return a BSD sockaddr that describes this IPv4 address
@author Justin Randall
*/
const struct sockaddr_in & Address::getSockAddr4() const
{
return *addr4;
}
//---------------------------------------------------------------------
/**
@brief equality operator
The equality operator compares the ip address, ip port,
and address family to establish equality.
Example:
\code
Address a("127.0.0.1", 55443);
Address b;
b = a;
assert(b == a);
\endcode
@return True of the right hand side is equal to this address
@author Justin Randall
*/
const bool Address::operator == (const Address & rhs) const
{
return (addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr &&
addr4->sin_family == rhs.addr4->sin_family &&
addr4->sin_port == rhs.addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief less-than comparison operator
The < comparison operator compares the IP number and port. If
the IP numbers are identical, but the left hand side port is
less than the right hand side port, the operator will return
true.
@return true if the left hand side's IP number is less than
the right hand side IP number. If the numbers are equal, it
will return true if the left hand side IP port is less
than the right hand side port. Otherwise it returns false.
@author Justin Randall
*/
const bool Address::operator < (const Address & rhs) const
{
return(addr4->sin_addr.s_addr < rhs.addr4->sin_addr.s_addr ||
addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr &&
addr4->sin_port < rhs.addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief inequality operator
Leverages the equality operator, so whenever == returns true,
this returns false, and visa versa.
@return true if the right hand side is not equal to the left
hand side. False if they are equal.
@see Adress::operator==
@author Justin Randall
*/
const bool Address::operator != (const Address & rhs) const
{
return(! (rhs == *this));
}
//---------------------------------------------------------------------
/**
@brief greater-than comparison operator
The > comparison operator compares the IP number and port. If
the IP numbers are identical, but the right hand side port is
lesser than the left hand side port, the operator will return
true.
@return true if the left hand side's IP number is greater than
the right hand side IP number. If the numbers are equal, it
will return true if the left hand side IP port is greater
than the right hand side port. Otherwise it returns false.
@author Justin Randall
*/
const bool Address::operator > (const Address & rhs) const
{
return(addr4->sin_addr.s_addr > rhs.addr4->sin_addr.s_addr ||
addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr &&
addr4->sin_port > rhs.addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief a hash_map support routine
The STL hash_map (present in most STL implementations) requires
a size_t return from a hash function to identify which bucket
a particular value should reside in. On 32 bit or better platforms
the sockaddr_in.sin_addr.s_addr member is small enough to
qualify as a hash-result, provides reasonably unique values
and is reproducable given an address input.
Example:
\code
typedef std::hash_map<Address, Connection *, Address::HashFunction, Address::EqualFunction> AddressMap;
\endcode
@return the ip number member of a sockaddr_in struct
@author Justin Randall
*/
size_t Address::hashFunction() const
{
return addr4->sin_addr.s_addr;
}
//---------------------------------------------------------------------
/**
@brief STL map support routine
STL maps (including hash_maps) require unique keys, and therefore
need to compare a key for equality with an existing target.
The functor uses Address::operator = for the comparison.
Example:
\code
typedef std::hash_map<Address, Connection *, Address::HashFunction, Address::EqualFunction> AddressMap;
\endcode
@return true if the left hand side and right hand side are equal
using Address::operator =
@see Address::operator=
*/
bool Address::EqualFunction::operator () (const Address & lhs, const Address & rhs) const
{
return lhs == rhs;
}
//---------------------------------------------------------------------
/**
@brief STL hash_map support routine
The HashFunction::operator() invokes Address::hashFunction to
determine an appropriate hash for the address.
Example:
\code
typedef std::hash_map<Address, Connection *, Address::HashFunction, Address::EqualFunction> AddressMap;
\endcode
@see Address::hashFunction
@author Justin Randall
*/
size_t Address::HashFunction::operator () (const Address & a) const
{
return a.hashFunction();
}
//---------------------------------------------------------------------
@@ -1,141 +0,0 @@
// NetworkGetHostName.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstSharedNetwork.h"
#include "Address.h"
#include "sharedNetwork/NetworkHandler.h"
#include <net/if.h>
#include <unistd.h>
#include <string>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
//-----------------------------------------------------------------------
struct HN
{
HN();
std::string hostName;
};
//-----------------------------------------------------------------------
HN::HN()
{
char name[512] = {"\0"};
if(gethostname(name, sizeof(name)) == 0)
{
Address a(name, 0);
//hostName = name;
hostName = a.getHostAddress();
}
}
//-----------------------------------------------------------------------
const std::string & NetworkHandler::getHostName()
{
static HN hn;
return hn.hostName;
}
//-----------------------------------------------------------------------
const std::string & NetworkHandler::getHumanReadableHostName()
{
char name[512] = {"\0"};
static std::string nameString;
if(nameString.empty())
{
if(gethostname(name, sizeof(name)) == 0)
{
name[sizeof(name) - 1] = 0;
//hostName = name;
nameString = name;
}
}
return nameString;
}
//-----------------------------------------------------------------------
struct HL
{
HL();
std::vector<std::pair<std::string, std::string> > addrList;
};
//-----------------------------------------------------------------------
HL::HL() :
addrList()
{
struct ifconf ifc;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
// create a socket to perform SIOCGIFCONF on
if(sock > -1)
{
// determine buffer size to receive array of if_req's, initialize it
// when length is appropriate
int reqSize = 100 * sizeof(struct ifreq);
int lastReqSize = reqSize;
for(;;)
{
char * buf = new char[reqSize];
ifc.ifc_len = reqSize;
ifc.ifc_buf = buf;
memset(ifc.ifc_buf, 0, reqSize);
if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
{
if (errno != EINVAL || lastReqSize != 0)
{
WARNING(true, ("Error getting interface list: %s", strerror(errno)));
delete buf;
return;
}
}
else
{
if(ifc.ifc_len == lastReqSize)
break; // we have the reqs
lastReqSize = ifc.ifc_len;
}
// need more buffer space for request
reqSize += sizeof(struct ifreq);
delete [] buf;
}
int reqCount = reqSize / sizeof(struct ifreq);
int i;
ifreq * reqs = (struct ifreq *)ifc.ifc_buf;
for(i = 0; i < reqCount; ++i)
{
struct sockaddr_in * sa = (struct sockaddr_in *)&reqs[i].ifr_addr;
if(sa->sin_family == AF_INET)
{
char addrbuf[17] = {"\0"};
unsigned char * a = (unsigned char *)&sa->sin_addr;
snprintf(addrbuf, sizeof(addrbuf), "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
addrList.push_back(std::make_pair(std::string(reqs[i].ifr_name), std::string(addrbuf)));
}
}
}
}
//-----------------------------------------------------------------------
const std::vector<std::pair<std::string, std::string> > & NetworkHandler::getInterfaceAddresses()
{
static HL hl;
return hl.addrList;
}
//-----------------------------------------------------------------------
@@ -1,236 +0,0 @@
//---------------------------------------------------------------------
#pragma warning(disable : 4127)
#include "FirstSharedNetwork.h"
#include <cassert>
#include "Sock.h"
#include <netdb.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
const int INVALID_SOCKET = 0xFFFFFFFF;
//---------------------------------------------------------------------
Sock::Sock() :
handle(INVALID_SOCKET),
lastError(Sock::SOCK_NO_ERROR),
bindAddress()
{
}
//---------------------------------------------------------------------
Sock::~Sock()
{
// ensure we don't block, and that pending
// data is sent with a graceful shutdown
int err;
err = close(handle);
assert(err == 0);
handle = INVALID_SOCKET;
}
//---------------------------------------------------------------------
/**
@brief Bind the socket to the specified local address
*/
bool Sock::bind(const Address & newBindAddress)
{
bool result = false;
int enable = 1;
setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
bindAddress = newBindAddress;
assert(handle != INVALID_SOCKET);
socklen_t namelen = sizeof(struct sockaddr_in);
int err = ::bind(handle, reinterpret_cast<const struct sockaddr *>(&(bindAddress.getSockAddr4())), namelen);
if(err == 0)
{
result = true;
struct sockaddr_in a;
int r;
r = getsockname(handle, reinterpret_cast<struct sockaddr *>(&a), &namelen);
assert(r == 0);
bindAddress = a;
}
else
{
result = false;
}
assert(err == 0);
return result;
}
//---------------------------------------------------------------------
bool Sock::bind()
{
bool result = false;
struct sockaddr_in a;
socklen_t namelen = sizeof(struct sockaddr_in);
memset(&a, 0, sizeof(struct sockaddr_in));
a.sin_family = AF_INET;
a.sin_port = 0;
a.sin_addr.s_addr = INADDR_ANY;
assert(handle != INVALID_SOCKET);
int err = ::bind(handle, reinterpret_cast<struct sockaddr *>(&a), namelen);
if(err == 0)
{
result = true;
int r;
r = getsockname(handle, reinterpret_cast<struct sockaddr *>(&a), &namelen);
assert(r == 0);
bindAddress = a;
}
assert(err == 0);
return result;
}
//---------------------------------------------------------------------
bool Sock::canRecv() const
{
pollfd r;
r.fd = handle;
r.events = POLLIN | POLLPRI | POLLERR;
int err = poll(&r, 1, 0);
if(err < 0)
{
switch(errno)
{
case EINTR: // the system has interrupted the call, it's too busy to send right now
break;
default:
break;
}
}
return (err > 0);
}
//---------------------------------------------------------------------
bool Sock::canSend() const
{
pollfd w;
w.fd = handle;
w.events = POLLOUT | POLLERR;
int err = poll(&w, 1, 0);
if(err < 0)
{
switch(errno)
{
case EINTR: // the system has interrupted the call, it's too busy to send right now
break;
default:
break;
}
}
return (err > 0);
}
//---------------------------------------------------------------------
const unsigned int Sock::getInputBytesPending() const
{
unsigned long int bytes = 0;
int err;
err = ioctl(handle, FIONREAD, &bytes); //lint !e1924 (I don't know WHAT Microsoft is doing here!)
assert(err == 0);
return bytes;
}
//---------------------------------------------------------------------
const std::string Sock::getLastError() const
{
std::string errString;
switch(errno)
{
case EBADF:
errString = "The argument s is not a valid descriptor.";
break;
case ENOTSOCK:
errString = "The argument s is a file, not a socket.";
break;
case ENOPROTOOPT:
errString = "The option is unknown at the level indicated.";
break;
case EFAULT:
errString = "The address pointed to by optval is not in a valid part of the process address space. For getsockopt, this error may also be returned if optlen is not in a valid part of the process address space.";
break;
case ENOTTY:
errString = "The scoket handle is not associated with a character special device.";
break;
case EINVAL:
errString = "argument is not valid.";
break;
case EAGAIN:
errString = "EAGAIN";
break;
case EDEADLK:
errString = "EDEADLK";
break;
case ECONNRESET:
errString = "The connection was reset by the peer.";
lastError = CONNECTION_RESET;
break;
default:
errString = strerror(errno);
break;
}
return errString;
}
//---------------------------------------------------------------------
void Sock::getPeerName(struct sockaddr_in & target, int s)
{
socklen_t namelen = sizeof(struct sockaddr_in);
int err;
err = getpeername(s, reinterpret_cast<sockaddr *>(&(target)), &namelen);
assert(err != -1);
}
//-----------------------------------------------------------------------
/** @brief determine the maximum message size that may be sent on this socket
*/
const unsigned int Sock::getMaxMessageSendSize() const
{
int maxMsgSize = 1500;
/** @todo get msg size via IP interface on Linux
int optlen = sizeof(int);
int result = getsockopt(handle, SOL_SOCKET, SO_MAX_MSG_SIZE, reinterpret_cast<char *>(&maxMsgSize), &optlen);
if(result != 0)
{
perror("Sock::getMaxMessageSendSize() : getsockopt()");
}
*/
return static_cast<unsigned int>(maxMsgSize);
}
//---------------------------------------------------------------------
void Sock::setNonBlocking() const
{
assert(handle != INVALID_SOCKET);
unsigned long int nb = 1;
int err;
err = ioctl(handle, FIONBIO, &nb); //lint !e569 // loss of precision in the FIONBIO macro, beyond my control
assert(err == 0);
}
//---------------------------------------------------------------------
@@ -1,128 +0,0 @@
// ======================================================================
//
// Sock.h
//
// Copyright 2003 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Sock_H
#define INCLUDED_Sock_H
// ======================================================================
#include "sharedNetwork/Address.h"
// ======================================================================
const unsigned int SOCK_ERROR = 0xFFFFFFFF;
/**
@brief a BSD socket abstraction
Sock abstracts BSD sockets for platform independant operation. It
also provides common socket operations to simplify socket management.
@see BroadcastSock
@see TcpSock
@see UdpSock
@author Justin Randall
*/
class Sock
{
public:
/**
@brief failure states for a socket
*/
enum ErrorCodes
{
SOCK_NO_ERROR,
CONNECTION_FAILED,
CONNECTION_CLOSED,
CONNECTION_RESET
};
Sock();
virtual ~Sock() = 0;
bool bind(const Address & bindAddress);
bool bind();
bool canSend() const;
bool canRecv() const;
const Address & getBindAddress() const;
const int getHandle() const;
const unsigned int getInputBytesPending() const;
const std::string getLastError() const;
const enum ErrorCodes getLastErrorCode() const;
const unsigned int getMaxMessageSendSize() const;
static void getPeerName(struct sockaddr_in & target, int s);
private:
// disabled
Sock(const Sock & source);
Sock & operator= (const Sock & source);
protected:
void setNonBlocking() const;
protected:
int handle;
/**
@brief support for setting/getting last error from derived
sock classes
*/
mutable enum ErrorCodes lastError;
private:
Address bindAddress;
};
//---------------------------------------------------------------------
/**
@brief return the local address of the socket
Until a socket is bound, the bind address may be reported as
0.0.0.0:0
@return a const Address reference describing the local address
of the socket.
@author Justin Randall
*/
inline const Address & Sock::getBindAddress() const
{
return bindAddress;
}
//---------------------------------------------------------------------
/**
@brief return the platform specific socket handle
the handle returned is not portable and should only be used locally
for Sock specific operations.
@author Justin Randall
*/
inline const int Sock::getHandle() const
{
return handle;
}
//---------------------------------------------------------------------
/**
@brief get the last error code on the socket
@return the last error code on the socket
@see Sock::ErrorCodes
@author Justin Randall
*/
inline const enum Sock::ErrorCodes Sock::getLastErrorCode() const
{
return lastError;
}
//---------------------------------------------------------------------
#endif // _Sock_H
@@ -1,610 +0,0 @@
//---------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "TcpClient.h"
#include "TcpServer.h"
#include "Archive/Archive.h"
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/Os.h"
#include "sharedLog/Log.h"
#include "sharedLog/NetLogConnection.h"
#include "sharedNetwork/Connection.h"
#include "sharedNetwork/ConfigSharedNetwork.h"
#include <map>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <set>
#include <vector>
//-----------------------------------------------------------------------
const unsigned long KEEPALIVE_MS = 1000;
//-----------------------------------------------------------------------
namespace TcpClientNamespace
{
std::set<TcpClient *> s_pendingConnectionSends;
std::set<TcpClient *> s_tcpClients;
bool s_installed = false;
}
using namespace TcpClientNamespace;
//---------------------------------------------------------------------
TcpClient::TcpClient (int sockHandle, TcpServer * server) :
m_socket(sockHandle),
m_tcpServer(server),
m_pendingSend(),
m_connection(0),
m_recvBuffer(0),
m_recvBufferLength(0),
m_remoteAddress(),
m_refCount(0),
m_connected (true),
m_lastSendTime(0),
m_bindPort(0),
m_rawTCP( false )
{
s_tcpClients.insert(this);
setSockOptions();
struct sockaddr_in target;
socklen_t namelen = sizeof(struct sockaddr_in);
if (getpeername(sockHandle, reinterpret_cast<sockaddr *>(&target), &namelen) == 0)
m_remoteAddress = target;
struct sockaddr_in bindAddr;
if(getsockname(sockHandle, reinterpret_cast<struct sockaddr *>(&bindAddr), &namelen) == 0)
{
m_bindPort = ntohs(bindAddr.sin_port);
}
}
// ----------------------------------------------------------------------
TcpClient::TcpClient (const std::string & a, const unsigned short port) :
m_socket(-1),
m_tcpServer(0),
m_connection(0),
m_recvBuffer(0),
m_recvBufferLength(0),
m_remoteAddress(a, port),
m_refCount(0),
m_connected (false),
m_lastSendTime(0),
m_bindPort(0),
m_rawTCP( false )
{
FATAL(! s_installed, ("TcpClient is not installed!"));
s_tcpClients.insert(this);
setupSocket();
}
//---------------------------------------------------------------------
TcpClient::~TcpClient()
{
FATAL(m_refCount > 0, ("Attempting to destroy a TcpClient while references still exist!"));
std::set<TcpClient *>::iterator f = s_tcpClients.find(this);
if(f != s_tcpClients.end())
s_tcpClients.erase(f);
f = s_pendingConnectionSends.find(this);
if(f != s_pendingConnectionSends.end())
s_pendingConnectionSends.erase(f);
delete[] m_recvBuffer;
if(m_socket != -1)
close (m_socket);
}
//---------------------------------------------------------------------
void TcpClient::addRef()
{
m_refCount++;
}
//---------------------------------------------------------------------
std::string const &TcpClient::getRemoteAddress() const
{
return m_remoteAddress.getHostAddress();
}
//---------------------------------------------------------------------
unsigned short TcpClient::getRemotePort() const
{
return m_remoteAddress.getHostPort();
}
//---------------------------------------------------------------------
void TcpClient::setSockOptions()
{
int optval = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
ioctl(m_socket, FIONBIO, &optval);
}
//---------------------------------------------------------------------
void TcpClient::commit()
{
int sent = 0;
const unsigned char * ptr = m_pendingSend.getBuffer();
const unsigned char * const end = ptr + m_pendingSend.getSize();
static Archive::ByteStream s_localScratchBuffer;
s_localScratchBuffer.clear();
int retries = 0;
static const int maxRetries = ConfigSharedNetwork::getMaxTCPRetries();
bool sentSomething = false;
do
{
// attempt to push pending data to socket
sent = ::send (m_socket, ptr, end - ptr, MSG_NOSIGNAL);
if(sent == -1)
{
// failed
switch(errno)
{
// because it would block on a non-blocking socket
case EAGAIN:
case ENOBUFS:
case ENOMEM:
case EINTR:
{
retries++;
// requeue
break;
}
// an unhandled error (connection reset, for example)
default:
{
m_pendingSend.clear();
perror("send: ");
if (m_connection)
m_connection->setDisconnectReason("TcpClient::commit send returned -1, errno=%d", errno);
onConnectionClosed();
return;
break;
}
}
}
else if(sent > 0)
{
sentSomething=true;
ptr += sent;
if(sent < end - ptr)
{
// data was passed to the socket, but not all
// of it could be committed, keep trying!
retries = 0;
Os::sleep(1);
}
}
else if(sent == 0)
{
// tried to send and got nothing through (should have returned an error, but be thorough)
retries ++;
Os::sleep(1);
}
} while(ptr < end && retries < maxRetries);
if(ptr == end)
{
// all data was committed, clear pending buffer
m_pendingSend.clear();
}
else
{
// bailed out before all data was committed, save unsent data for
// next pass on commit()
if (sentSomething)
{
s_localScratchBuffer.put(ptr, end - ptr);
m_pendingSend.clear();
m_pendingSend.put(s_localScratchBuffer.getBuffer(), s_localScratchBuffer.getSize());
}
s_pendingConnectionSends.insert(this);
}
// clean up local accounting
s_localScratchBuffer.clear();
}
//---------------------------------------------------------------------
void TcpClient::flush()
{
if (m_connected && m_pendingSend.getSize() > 0)
{
// flush pending buffer
commit();
}
}
//-----------------------------------------------------------------------
void TcpClient::flushPendingWrites()
{
std::set<TcpClient *> sends = s_pendingConnectionSends;
s_pendingConnectionSends.clear();
for (std::set<TcpClient *>::const_iterator i = sends.begin(); i != sends.end(); ++i)
{
TcpClient * const c = *i;
if (c->m_connected)
{
c->flush();
if ( c->m_connection
&& c->m_pendingSend.getSize()
&& ConfigSharedNetwork::getLogSendingTooMuchData()
&& !dynamic_cast<NetLogConnection const *>(c->m_connection))
{
WARNING(true, ("(%s) Failed to commit %d bytes this frame to %s:%d. This process is sending more data than the remote can receive!", c->m_connection->getConnectionDescription().c_str(), c->m_pendingSend.getSize(), c->getRemoteAddress().c_str(), c->getRemotePort()));
LOG("Network", ("(%s) Failed to commit %d bytes this frame to %s:%d. This process is sending more data than the remote can receive!", c->m_connection->getConnectionDescription().c_str(), c->m_pendingSend.getSize(), c->getRemoteAddress().c_str(), c->getRemotePort()));
}
}
}
}
//---------------------------------------------------------------------
unsigned short TcpClient::getBindPort() const
{
return m_bindPort;
}
//---------------------------------------------------------------------
int TcpClient::getSocket() const
{
return m_socket;
}
//---------------------------------------------------------------------
void TcpClient::install()
{
FATAL(s_installed, ("TcpClient is already installed!"));
s_installed = true;
signal(SIGPIPE, SIG_IGN);
}
//---------------------------------------------------------------------
void TcpClient::onConnectionClosed()
{
if (m_connection)
m_connection->setDisconnectReason("TcpClient::onConnectionClosed called");
m_connected = false;
shutdown(m_socket, SHUT_RDWR);
if(m_tcpServer)
{
m_tcpServer->removeClient(this);
}
close(m_socket);
m_socket = -1;
if(m_connection)
{
NetworkHandler::onTerminate(m_connection);
}
}
//---------------------------------------------------------------------
void TcpClient::onConnectionOpened()
{
// Get the local port this socket was bound to. If
// a client socket repeatedly attempts to connect to a local
// service that should be listening on a port that the operating
// system may assign AND the service isn't actually running and
// using the port, the client socket may connect to itself.
// For example, A client connecting to 127.0.0.1:50005, the operating
// system may assign the client socket port 50005 and the connection
// succeeds, but it is in fact a connection to itself, meaning the
// client isn't actually talking to any valid service.
struct sockaddr_in bindAddr;
socklen_t addrLen = sizeof(struct sockaddr_in);
if(getsockname(m_socket, reinterpret_cast<struct sockaddr *>(&bindAddr), &addrLen) == 0)
{
m_bindPort = ntohs(bindAddr.sin_port);
}
// this *might* be a valid connection to a remote address, but
// to easily catch all cases of loopback connections, attempt a
// reconnect if the remote port is identical to the local port
if(m_remoteAddress.getHostPort() == m_bindPort && ! m_tcpServer)
{
shutdown(m_socket, SHUT_RDWR);
DEBUG_FATAL(m_tcpServer, ("Detected a loopback client connection on a TCP SERVER!!!"));
close(m_socket);
m_socket = -1;
// reconnect the socket
// address and port info is initialized in the constructor
setupSocket();
LOG("Network", ("Detected a loopback, closing socket and reconnecting"));
}
else
{
m_connected = true;
if(m_connection)
{
m_connection->onConnectionOpened();
}
flush();
}
}
//---------------------------------------------------------------------
void TcpClient::onReceive (const unsigned char * const recvBuf, const int bytes)
{
if(m_connection)
{
m_connection->receive(recvBuf, bytes);
}
}
//---------------------------------------------------------------------
void TcpClient::queryConnect ()
{
struct pollfd pfd;
pfd.fd = m_socket;
pfd.events = POLLOUT;
pfd.revents = 0;
int pollResult = poll(&pfd, 1, 0);
if(pollResult > 0)
{
if (pfd.revents & POLLERR)
{
if (m_connection)
m_connection->setDisconnectReason("TcpClient::queryConnect POLLERR");
onConnectionClosed();
}
else if (pfd.revents & POLLHUP)
{
if (m_connection)
m_connection->setDisconnectReason("TcpClient::queryConnect POLLHUP");
onConnectionClosed();
}
else
{
onConnectionOpened();
}
}
}
//-----------------------------------------------------------------------
void TcpClient::release()
{
m_refCount--;
if(m_refCount == 0)
{
if (m_connected)
{
if (m_connection)
m_connection->setDisconnectReason("TcpClient::release called");
onConnectionClosed();
}
delete this;
}
}
//-----------------------------------------------------------------------
void TcpClient::remove()
{
FATAL(!s_installed, ("TcpClient already removed!"));
std::set<TcpClient *>::iterator i;
for(i = s_tcpClients.begin(); i != s_tcpClients.end(); ++i)
{
TcpClient * c = (*i);
c->release();
}
s_installed = false;
}
//---------------------------------------------------------------------
void TcpClient::send(const unsigned char * const buffer, const int bufferLen)
{
if (bufferLen)
{
m_lastSendTime = Clock::getFrameStartTimeMs();
s_pendingConnectionSends.insert(this);
if( !m_rawTCP )
Archive::put(m_pendingSend, bufferLen);
m_pendingSend.put(buffer, bufferLen);
static int const tcpMinimumFrame = ConfigSharedNetwork::getTcpMinimumFrame();
if (static_cast<int>(m_pendingSend.getSize()) >= tcpMinimumFrame)
flush();
}
}
//-----------------------------------------------------------------------
void TcpClient::setConnection(Connection * c)
{
m_connection = c;
}
//---------------------------------------------------------------------
void TcpClient::checkKeepalive()
{
if (m_connected)
{
unsigned long const timeNow = Clock::getFrameStartTimeMs();
if (timeNow-m_lastSendTime > KEEPALIVE_MS)
{
m_lastSendTime = timeNow;
s_pendingConnectionSends.insert(this);
Archive::put(m_pendingSend, 0);
}
}
}
//---------------------------------------------------------------------
void TcpClient::update()
{
addRef();
if(!m_connected)
{
queryConnect();
}
if(m_connected)
{
struct pollfd pfd;
pfd.fd = m_socket;
pfd.events = POLLIN|POLLHUP;
pfd.revents = 0;
int pollResult = poll (&pfd, 1, 0);
// POLLERR is mutually exclusive with POLLIN and POLLHUP.
// POLLIN and POLLHUP are not consistent cross-platform. Additionally,
// a POLLHUP doesn't mean that there's not data available. The best,
// cross-platform way to check for disconnection is to see if either
// POLLHUP or POLLIN are set, and then read from the socket.
// In cases where there's data, we'll just end up checking it next
// frame anyway. In cases where there's no data, it means we've
// disconnected so we can handle cleanup.
if (pollResult)
{
if (m_recvBuffer == NULL)
{
m_recvBufferLength = 1500;
m_recvBuffer = new unsigned char [m_recvBufferLength];
}
int bytesReceived = recv(m_socket, m_recvBuffer, m_recvBufferLength, 0);
if (bytesReceived > 0)
{
onReceive(m_recvBuffer, bytesReceived);
}
else if (bytesReceived == -1)
{
switch (errno)
{
case EAGAIN:
case EINTR:
break;
default:
if (m_connection)
m_connection->setDisconnectReason("TcpClient::update recv returned -1, errno=%d", errno);
onConnectionClosed();
break;
}
}
else if (bytesReceived == 0)
{
// peer closed connection
if (m_connection)
{
// Log this, as it's a pretty deep change.
LOG("Network", ("(%s) Read zero bytes on a successful poll (POLLIN|POLLHUP). Closing socket since we think it is closed.", m_connection->getConnectionDescription().c_str()));
m_connection->setDisconnectReason("TcpClient::update recv returned 0");
}
else
{
LOG("Network", ("(null connection object) Read zero bytes on a successful poll (POLLIN|POLLHUP). Closing socket since we think it is closed."));
}
onConnectionClosed();
}
if (bytesReceived == m_recvBufferLength)
{
// grow the buffer
delete [] m_recvBuffer;
m_recvBufferLength = m_recvBufferLength * 2;
m_recvBuffer = new unsigned char [m_recvBufferLength];
}
}
}
release();
}
// ----------------------------------------------------------------------
void TcpClient::setupSocket()
{
FATAL(! s_installed, ("TcpClient is not installed!"));
protoent * p = getprotobyname ("tcp");
const int entry = p->p_proto;
m_socket = socket (AF_INET, SOCK_STREAM, entry);
if (m_socket != -1)
{
setSockOptions();
int nameLen = sizeof (struct sockaddr_in);
int result;
result = connect (m_socket, reinterpret_cast<const struct sockaddr *> (&m_remoteAddress.getSockAddr4 () ), nameLen);
if(result == -1)
{
switch(errno)
{
case EINPROGRESS:
case EALREADY:
break;
default:
perror("connect ");
if (m_connection)
m_connection->setDisconnectReason("TcpClient::TcpClient connect returned -1, errno=%d", errno);
onConnectionClosed();
break;
}
}
else
{
struct sockaddr_in bindAddr;
socklen_t addrLen = sizeof(struct sockaddr_in);
if(getsockname(m_socket, reinterpret_cast<struct sockaddr *>(&bindAddr), &addrLen) == 0)
{
m_bindPort = ntohs(bindAddr.sin_port);
}
}
}
}
// ----------------------------------------------------------------------
void TcpClient::setRawTCP( bool bNewValue )
{
m_rawTCP = bNewValue;
}
// ----------------------------------------------------------------------
void TcpClient::clearTcpServer()
{
m_tcpServer = 0;
}
// ======================================================================
@@ -1,89 +0,0 @@
// TcpClient.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TcpClient_H
#define _INCLUDED_TcpClient_H
//-----------------------------------------------------------------------
#include "Archive/ByteStream.h"
#include "sharedNetwork/Address.h"
#include <string>
//-----------------------------------------------------------------------
class Connection;
class TcpServer;
//-----------------------------------------------------------------------
class TcpClient
{
public:
TcpClient(int sock, TcpServer *);
TcpClient(const std::string & address, const unsigned short port);
void addRef();
static void install();
void release();
static void remove();
void send(const unsigned char * const buffer, const int length);
unsigned short getBindPort() const;
std::string const &getRemoteAddress() const;
unsigned short getRemotePort() const;
void setPendingSendAllocatedSizeLimit(unsigned int limit);
// only used by clients
void update();
static void flushPendingWrites();
protected:
friend class TcpServer;
friend class Connection;
void setSockOptions();
void commit();
int getSocket() const;
void onConnectionClosed();
void onConnectionOpened();
void onReceive(const unsigned char * const recvBuf, const int bytes);
void queryConnect();
void queueReceive();
void setConnection(Connection *);
void checkKeepalive();
void clearTcpServer();
void setRawTCP( bool bNewValue );
private:
TcpClient & operator = (const TcpClient & rhs);
TcpClient(const TcpClient & source);
~TcpClient();
void flush ();
void setupSocket();
int m_socket;
TcpServer * m_tcpServer;
Archive::ByteStream m_pendingSend;
Connection * m_connection;
unsigned char * m_recvBuffer;
int m_recvBufferLength;
Address m_remoteAddress;
int m_refCount;
bool m_connected;
unsigned long m_lastSendTime;
unsigned short m_bindPort;
bool m_rawTCP;
};
//-----------------------------------------------------------------------
inline void TcpClient::setPendingSendAllocatedSizeLimit(const unsigned int limit)
{
m_pendingSend.setAllocatedSizeLimit(limit);
}
//-----------------------------------------------------------------------
#endif // _INCLUDED_TcpClient_H
@@ -1,238 +0,0 @@
// TcpServer.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//---------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "TcpServer.h"
#include "sharedNetwork/Connection.h"
#include "sharedNetwork/Service.h"
#include "TcpClient.h"
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <vector>
//---------------------------------------------------------------------
TcpServer::TcpServer(Service * service, const std::string & a, const unsigned short port) :
m_bindAddress(a, port),
m_handle(-1),
m_service(service),
m_connections(),
m_connectionSockets(),
m_inputBuffer(0),
m_inputBufferSize(0)
{
protoent * p = getprotobyname("tcp");
if(p)
{
int entry = p->p_proto;
m_handle = socket(AF_INET, SOCK_STREAM, entry);
FATAL(m_handle == -1, ("Failed to create a server socket %s:%d", a.c_str(), port));
int optval = 1;
if(m_handle != -1)
{
int optResult = setsockopt(m_handle, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
FATAL(optResult == -1, ("Failed to set socket option SO_REUSEADDR"));
unsigned long nb = 1;
int ctlResult = ioctl(m_handle, FIONBIO, &nb);
FATAL(ctlResult == -1, ("Failed to set socket non-blocking"));
socklen_t addrlen = sizeof(struct sockaddr_in);
int bindResult = bind(m_handle, (struct sockaddr *)(&m_bindAddress.getSockAddr4()), addrlen);
FATAL(bindResult != 0, ("Failed to bind to port %d", port));
if(bindResult == 0)
{
int result = listen(m_handle, 256);
if(result == -1)
perror("listen ");
FATAL(result == -1, ("Failed to start listening on port %d", port));
struct sockaddr_in b;
getsockname(m_handle, (struct sockaddr *)(&b), &addrlen);
m_bindAddress = b;
}
}
}
}
//---------------------------------------------------------------------
TcpServer::~TcpServer()
{
close(m_handle);
for (std::map<int, TcpClient *>::const_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
(*i).second->clearTcpServer();
}
//---------------------------------------------------------------------
const std::string & TcpServer::getBindAddress() const
{
return m_bindAddress.getHostAddress();
}
//---------------------------------------------------------------------
const unsigned short TcpServer::getBindPort() const
{
return m_bindAddress.getHostPort();
}
//---------------------------------------------------------------------
void TcpServer::onConnectionClosed(TcpClient * c)
{
if(c)
{
std::set<TcpClient *>::iterator f = m_pendingDestroys.find(c);
if(f == m_pendingDestroys.end())
{
m_pendingDestroys.insert(c);
}
}
}
//---------------------------------------------------------------------
void TcpServer::removeClient(TcpClient * c)
{
std::map<int, TcpClient *>::iterator f = m_connections.find(c->getSocket());
if(f != m_connections.end())
{
// c->release();
m_connections.erase(f);
}
std::vector<pollfd>::iterator s;
for(s = m_connectionSockets.begin(); s != m_connectionSockets.end(); ++s)
{
if((*s).fd == c->getSocket())
{
m_connectionSockets.erase(s);
break;
}
}
}
//---------------------------------------------------------------------
void TcpServer::update()
{
struct pollfd pfd;
pfd.fd = m_handle;
pfd.events = POLLIN;
pfd.revents = 0;
int result = poll(&pfd, 1, 0);
if(result > 0)
{
// connection established
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
int newSock = accept(m_handle, (struct sockaddr *)(&addr), &len);
if(newSock != -1)
{
TcpClient * ptc = new TcpClient(newSock, this);
ptc->addRef();
m_connections.insert(std::make_pair(newSock, ptc));
struct pollfd readFd;
readFd.fd = ptc->getSocket();
readFd.events = POLLIN|POLLERR|POLLHUP;
readFd.revents = 0;
m_connectionSockets.push_back(readFd);
ptc->onConnectionOpened();
if(m_service)
m_service->onConnectionOpened(ptc);
ptc->release();
}
}
struct pollfd * clients = &m_connectionSockets[0];
int readResult = poll (clients, m_connectionSockets.size (), 0);
if (readResult > 0)
{
std::vector<struct pollfd>::iterator i;
std::vector<struct pollfd> cs = m_connectionSockets;
for (i = cs.begin (); i != cs.end (); ++i)
{
if ((*i).revents & POLLERR)
{
std::map<int, TcpClient *>::iterator f = m_connections.find ( (*i).fd );
if (f != m_connections.end ())
{
TcpClient * c = (*f).second;
if (c->m_connection)
c->m_connection->setDisconnectReason("TcpServer::update POLLERR");
c->onConnectionClosed();
}
}
// POLLERR is mutually exclusive with POLLIN and POLLHUP.
// POLLIN and POLLHUP are not consistent cross-platform. Additionally,
// a POLLHUP doesn't mean that there's not data available. The best,
// cross-platform way to check for disconnection is to see if either
// POLLHUP or POLLIN are set, and then read from the socket.
// In cases where there's data, we'll just end up checking it next
// frame anyway. In cases where there's no data, it means we've
// disconnected so we can handle cleanup.
else if( (*i).revents & (POLLIN|POLLHUP) )
{
if (m_inputBuffer == 0)
{
m_inputBuffer = new unsigned char[1500];
m_inputBufferSize = 1500;
}
int bytesReceived = recv ( (*i).fd, m_inputBuffer, m_inputBufferSize, 0);
std::map<int, TcpClient *>::iterator f = m_connections.find ( (*i).fd );
if (f != m_connections.end ())
{
TcpClient * c = (*f).second;
std::set<TcpClient *>::iterator pd = m_pendingDestroys.find(c);
if(pd == m_pendingDestroys.end())
{
c->addRef();
if(bytesReceived > 0)
{
c->onReceive(m_inputBuffer, bytesReceived);
}
else if (bytesReceived == -1)
{
if (c->m_connection)
c->m_connection->setDisconnectReason("TcpServer::update recv returned %d, errno=%d", bytesReceived, errno);
c->onConnectionClosed();
}
else if (bytesReceived == 0)
{
// 0 bytes received on a read is the guaranteed signal for a
// closed connection.
if (c->m_connection)
c->m_connection->setDisconnectReason("TcpServer::update recv returned no bytes, singaling a closed socket (bytes=%d, errno=%d", bytesReceived, errno);
c->onConnectionClosed();
}
c->release();
}
}
if (bytesReceived == m_inputBufferSize)
{
delete [] m_inputBuffer;
m_inputBufferSize = m_inputBufferSize * 2;
m_inputBuffer = new unsigned char [m_inputBufferSize];
}
}
}
std::set<TcpClient *>::iterator pdIter;
for(pdIter = m_pendingDestroys.begin(); pdIter != m_pendingDestroys.end(); ++pdIter)
{
removeClient((*pdIter));
}
m_pendingDestroys.clear();
}
}
//---------------------------------------------------------------------
@@ -1,52 +0,0 @@
// TcpServer.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TcpServer_H
#define _INCLUDED_TcpServer_H
//-----------------------------------------------------------------------
#include "Address.h"
#include <string>
#include <vector>
#include <map>
#include <set>
//-----------------------------------------------------------------------
class Service;
class TcpClient;
//-----------------------------------------------------------------------
class TcpServer
{
public:
TcpServer(Service * service, const std::string & bindAddress, const unsigned short bindPort);
~TcpServer();
const std::string & getBindAddress () const;
const unsigned short getBindPort () const;
void onConnectionClosed (TcpClient *);
void removeClient (TcpClient *);
void update ();
private:
TcpServer & operator = (const TcpServer & rhs);
TcpServer(const TcpServer & source);
private:
Address m_bindAddress;
int m_handle;
Service * m_service;
std::map<int, TcpClient *> m_connections;
std::vector<struct pollfd> m_connectionSockets;
unsigned char * m_inputBuffer;
int m_inputBufferSize;
std::set<TcpClient *> m_pendingDestroys;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_TcpServer_H
@@ -1,63 +0,0 @@
//---------------------------------------------------------------------
#include "FirstSharedNetwork.h"
#include <cassert>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "sharedNetwork/UdpSock.h"
const int INVALID_SOCKET = 0xFFFFFFFF;
//---------------------------------------------------------------------
UdpSock::UdpSock() :
Sock()
{
handle = socket(AF_INET, SOCK_DGRAM, 17);
assert(handle != INVALID_SOCKET);
setNonBlocking();
}
//---------------------------------------------------------------------
UdpSock::~UdpSock()
{
}
//---------------------------------------------------------------------
const unsigned int UdpSock::recvFrom(Address & outAddr, void * targetBuffer, const unsigned int bufferSize) const
{
socklen_t fromLen = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
unsigned int result = ::recvfrom(handle, static_cast<char *>(targetBuffer), static_cast<int>(bufferSize), 0, reinterpret_cast<struct sockaddr *>(&addr), &fromLen); //lint !e732 // MS wants an int, should be unsigned IMO
outAddr = addr;
return result;
}
//---------------------------------------------------------------------
const unsigned int UdpSock::sendTo(const Address & targetAddress, const void * sourceBuffer, const unsigned int length) const
{
unsigned int bytesSent = 0;
if(canSend())
{
socklen_t toLen = sizeof(struct sockaddr_in);
bytesSent = ::sendto(handle, sourceBuffer, static_cast<const int>(length), 0, reinterpret_cast<const struct sockaddr *>(&(targetAddress.getSockAddr4())), toLen); //lint !e732 // MS wants an int, should be unsigned IMO
}
return bytesSent;
}
//-----------------------------------------------------------------------
void UdpSock::enableBroadcast()
{
int optval = 1;
socklen_t optlen = sizeof(int);
setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &optval, optlen);
}
//---------------------------------------------------------------------
@@ -1,26 +0,0 @@
// ======================================================================
//
// RegexServices.cpp
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedRegex/FirstSharedRegex.h"
#include "sharedRegex/RegexServices.h"
// ======================================================================
void *RegexServices::allocateMemory(size_t byteCount)
{
return new char[byteCount];
}
// ----------------------------------------------------------------------
void RegexServices::freeMemory(void *pointer)
{
delete [] reinterpret_cast<char *>(pointer);
}
// ======================================================================
@@ -1,25 +0,0 @@
// ======================================================================
//
// RegexServices.h
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_RegexServices_H
#define INCLUDED_RegexServices_H
// ======================================================================
class RegexServices
{
public:
static void *allocateMemory(size_t byteCount);
static void freeMemory(void *pointer);
};
// ======================================================================
#endif
@@ -1,38 +0,0 @@
// ======================================================================
//
// ConditionVariable.cpp
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedSynchronization/ConditionVariable.h"
ConditionVariable::ConditionVariable(Mutex &m)
: _mutex(m)
{
pthread_cond_init(&cond, 0);
}
ConditionVariable::~ConditionVariable()
{
pthread_cond_destroy(&cond);
}
void ConditionVariable::wait()
{
pthread_cond_wait(&cond, &_mutex.getInternalMutex());
}
void ConditionVariable::signal()
{
pthread_cond_signal(&cond);
}
void ConditionVariable::broadcast()
{
pthread_cond_broadcast(&cond);
}
@@ -1,34 +0,0 @@
// ======================================================================
//
// ConditionVariable.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_ConditionVariable_h
#define INCLUDED_ConditionVariable_h
#include "sharedSynchronization/Mutex.h"
class ConditionVariable
{
public:
ConditionVariable(Mutex &m);
~ConditionVariable();
void wait();
// You must own the mutex before calling signal.
void signal();
void broadcast();
Mutex &mutex() { return _mutex; }
private:
ConditionVariable(const ConditionVariable &o);
ConditionVariable &operator =(const ConditionVariable &o);
Mutex &_mutex;
pthread_cond_t cond;
};
#endif
@@ -1,45 +0,0 @@
// ======================================================================
//
// Gate.cpp
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedSynchronization/Gate.h"
Gate::Gate(bool open)
: cond(lock)
{
opened = open;
}
Gate::~Gate()
{
}
void Gate::wait()
{
lock.enter();
while (!opened)
cond.wait();
lock.leave();
}
void Gate::close()
{
lock.enter();
opened = false;
lock.leave();
}
void Gate::open()
{
lock.enter();
opened = true;
cond.broadcast();
lock.leave();
}
@@ -1,35 +0,0 @@
// ======================================================================
//
// Gate.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Gate_h
#define INCLUDED_Gate_h
#include "sharedSynchronization/ConditionVariable.h"
class Gate
{
public:
Gate(bool open);
~Gate();
void wait();
void close();
void open();
private:
Gate(const Gate &o);
Gate &operator =(const Gate &o);
Mutex lock;
bool opened;
ConditionVariable cond;
};
#endif
@@ -1,63 +0,0 @@
// ======================================================================
//
// InterlockedInteger.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_InterlockedInteger_h
#define INCLUDED_InterlockedInteger_h
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class InterlockedInteger
{
public:
explicit InterlockedInteger(int initialValue=0);
int operator =(int); // returns prior value (exchange)
int operator ++(); // returns new value
int operator --(); // returns new value
operator int() const { return value; }
private:
InterlockedInteger(const InterlockedInteger &o);
InterlockedInteger &operator =(const InterlockedInteger &o);
pthread_mutex_t lock;
volatile int value;
};
inline InterlockedInteger::InterlockedInteger(int i_value)
: value(i_value)
{
pthread_mutex_init(&lock, 0);
}
inline int InterlockedInteger::operator =(int i_value)
{
pthread_mutex_lock(&lock);
int oldvalue = value;
value = i_value;
pthread_mutex_unlock(&lock);
return oldvalue;
}
inline int InterlockedInteger::operator ++()
{
pthread_mutex_lock(&lock);
int newvalue = value+1;
value = newvalue;
pthread_mutex_unlock(&lock);
return newvalue;
}
inline int InterlockedInteger::operator --()
{
pthread_mutex_lock(&lock);
int newvalue = value-1;
value = newvalue;
pthread_mutex_unlock(&lock);
return newvalue;
}
#endif
@@ -1,53 +0,0 @@
// ======================================================================
//
// InterlockedVoidPointer.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_InterlockedVoidPointer_h
#define INCLUDED_InterlockedVoidPointer_h
#include "sharedSynchronization/Mutex.h"
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class InterlockedVoidPointer
{
public:
explicit InterlockedVoidPointer(void * initialValue=0);
void * compareExchange(void * compare, void * exchange); // compare and exchange if same
operator void * () const { return reinterpret_cast<void *>(value); }
private:
InterlockedVoidPointer(const InterlockedVoidPointer &o);
InterlockedVoidPointer &operator =(const InterlockedVoidPointer &o);
Mutex lock;
void * volatile value;
};
template <class T>
class InterlockedPointer: public InterlockedVoidPointer
{
public:
explicit InterlockedPointer(T * initialValue): InterlockedVoidPointer(initialValue) {}
operator T * () const { return static_cast<const T *>(value); }
};
inline InterlockedVoidPointer::InterlockedVoidPointer(void * initialValue)
: value(initialValue)
{
}
inline void * InterlockedVoidPointer::compareExchange(void * compare, void * exchange)
{
lock.enter();
void * temp = value;
if (temp == compare)
value = exchange;
lock.leave();
return temp;
}
#endif
@@ -1,32 +0,0 @@
// ======================================================================
//
// Mutex.cpp
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedSynchronization/Mutex.h"
Mutex::Mutex()
{
pthread_mutex_init(&mutex, 0);
}
Mutex::~Mutex()
{
pthread_mutex_destroy(&mutex);
}
void Mutex::enter()
{
pthread_mutex_lock(&mutex);
}
void Mutex::leave()
{
pthread_mutex_unlock(&mutex);
}
@@ -1,31 +0,0 @@
// ======================================================================
//
// Mutex.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Mutex_h
#define INCLUDED_Mutex_h
class Mutex
{
public:
Mutex();
~Mutex();
void enter();
void leave();
pthread_mutex_t &getInternalMutex() { return mutex; }
private:
Mutex(const Mutex &o);
Mutex &operator =(const Mutex &o);
pthread_mutex_t mutex;
};
#endif
@@ -1,37 +0,0 @@
// ======================================================================
//
// RecursiveMutex.cpp
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedSynchronization/RecursiveMutex.h"
RecursiveMutex::RecursiveMutex()
{
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes,PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex,&attributes);
pthread_mutexattr_destroy(&attributes);
}
RecursiveMutex::~RecursiveMutex()
{
pthread_mutex_destroy(&mutex);
}
void RecursiveMutex::enter()
{
pthread_mutex_lock(&mutex);
}
void RecursiveMutex::leave()
{
pthread_mutex_unlock(&mutex);
}
@@ -1,31 +0,0 @@
// ======================================================================
//
// RecursiveMutex.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_RecursiveMutex_h
#define INCLUDED_RecursiveMutex_h
#include "sharedSynchronization/InterlockedInteger.h"
class RecursiveMutex
{
public:
RecursiveMutex();
~RecursiveMutex();
void enter();
void leave();
private:
RecursiveMutex(const RecursiveMutex &o);
RecursiveMutex &operator =(const RecursiveMutex &o);
pthread_mutex_t mutex;
};
#endif
@@ -1,40 +0,0 @@
// ======================================================================
//
// Semaphore.cpp
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedSynchronization/Semaphore.h"
Semaphore::Semaphore(int count, int initial)
{
sem_init(&sem, false, initial);
}
Semaphore::~Semaphore()
{
sem_destroy(&sem);
}
void Semaphore::wait()
{
sem_wait(&sem);
}
void Semaphore::wait(unsigned int maxDurationMs)
{
timespec ts;
ts.tv_sec = maxDurationMs/1000000;
ts.tv_nsec = maxDurationMs%1000000;
sem_timedwait(&sem, &ts);
}
void Semaphore::signal(int count)
{
sem_post(&sem);
}
@@ -1,30 +0,0 @@
// ======================================================================
//
// Semaphore.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Semaphore_h
#define INCLUDED_Semaphore_h
class Semaphore
{
public:
Semaphore(int count=0x7FFFFFFF, int initial=0);
~Semaphore();
void wait();
void wait(unsigned int maxDurationMs);
void signal(int count=1);
private:
Semaphore(const Semaphore &o);
Semaphore &operator =(const Semaphore &o);
sem_t sem;
};
#endif
@@ -1 +0,0 @@
#include "sharedTemplateDefinition/FirstSharedTemplateDefinition.h"
@@ -1,159 +0,0 @@
// ======================================================================
//
// Thread.cpp
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedThread/Thread.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/PerThreadData.h"
#include <cstdio>
class MainThread: public Thread
{
public:
MainThread(const std::string &name): Thread(name) {}
protected:
void run() {}
private:
MainThread(const MainThread &o);
MainThread &operator =(const MainThread &o);
};
pthread_key_t Thread::implindex;
Thread * Thread::mainThread;
void Thread::install()
{
DEBUG_FATAL(mainThread, ("Thread::install: already installed"));
ExitChain::add(remove, "Thread::remove");
pthread_key_create(&implindex, 0);
mainThread = new MainThread("Main");
mainThread->attach();
}
void Thread::remove()
{
DEBUG_FATAL(!mainThread, ("Thread::remove: not installed"));
DEBUG_FATAL(mainThread->refcount > 1, ("Someone still holds the main thread"));
delete mainThread;
pthread_key_delete(implindex);
mainThread = 0;
}
Thread::Thread(const std::string &i_name)
: refcount(1), name(i_name)
{
doneFlag = false;
}
void Thread::start()
{
pthread_create(&thread, 0, threadFunc, this);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
}
void Thread::attach()
{
thread = pthread_self();
pthread_setspecific(implindex, this);
}
Thread::~Thread()
{
pthread_detach(thread);
}
void * Thread::threadFunc(void * i)
{
Thread * impl = static_cast<Thread *>(i);
pthread_setspecific(implindex, impl);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
Os::setThreadName(impl->thread, impl->name.c_str());
PerThreadData::threadInstall(true);
impl->run();
PerThreadData::threadRemove();
impl->kill();
return 0;
}
void Thread::kill()
{
int t = getCurrentThread()->thread;
doneFlag = true;
deref();
if (this == getCurrentThread())
{
pthread_exit(0);
}
else
{
pthread_cancel(t);
}
}
bool Thread::done()
{
return doneFlag;
}
void Thread::wait()
{
if (!doneFlag)
{
void * junk;
pthread_join(thread, &junk);
}
}
static inline int interpPriority(float t, int policy)
{
return (int)(sched_get_priority_max(policy)*t + sched_get_priority_min(policy)*(1-t));
}
void Thread::setPriority(ePriority priority)
{
static int policies[] =
{
SCHED_OTHER,
SCHED_OTHER,
SCHED_OTHER,
SCHED_OTHER,
SCHED_FIFO
};
static int priorities[] =
{
interpPriority(0.0, SCHED_OTHER),
interpPriority(0.25, SCHED_OTHER),
interpPriority(0.5, SCHED_OTHER),
interpPriority(0.75, SCHED_OTHER),
interpPriority(0.75, SCHED_FIFO)
};
sched_param p;
p.sched_priority = priorities[priority];
pthread_setschedparam(thread, policies[priority], &p);
}
// Make sure the header-only files compile :)
#if 0
#include "sharedSynchronization/CountingSemaphore.h"
#include "sharedSynchronization/BlockingPointer.h"
#include "sharedSynchronization/BlockingQueue.h"
#include "sharedSynchronization/WriteOnce.h"
Mutex t;
BlockingQueue<int> bqint(t, 0, 0);
BlockingPointer<int> bpint(t, 0, 0);
WriteOnce<int> woint;
#endif
@@ -1,100 +0,0 @@
// ======================================================================
//
// Thread.h
// Acy Stapp
//
// Copyright 6/19/2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Thread_h
#define INCLUDED_Thread_h
#include "sharedSynchronization/InterlockedInteger.h"
#include <string>
class Thread
{
template <class T> friend class TypedThreadHandle;
public:
static void install();
static void remove();
Thread(const std::string &i_name=std::string());
void kill();
bool done();
void wait();
enum ePriority
{
kIdle = 0,
kLow = 1,
kNormal = 2,
kHigh = 3,
kCritical = 4
};
void setPriority(ePriority priority);
const std::string &getName() const;
void setName(const std::string &i_name);
static Thread * getCurrentThread();
static Thread * getMainThread();
protected:
virtual ~Thread();
virtual void run()=0;
pthread_t thread;
InterlockedInteger refcount;
private:
Thread(const Thread &o);
Thread &operator =(const Thread &o);
void start();
void attach(); // pick up the currently running thread
void ref();
void deref();
bool doneFlag;
std::string name;
static pthread_key_t implindex;
static Thread * mainThread;
static void * threadFunc(void * data);
};
inline void Thread::ref()
{
++refcount;
}
inline void Thread::deref()
{
if (--refcount == 0) delete this;
}
inline Thread * Thread::getCurrentThread()
{
return static_cast<Thread *>(pthread_getspecific(implindex));
}
inline Thread * Thread::getMainThread()
{
return mainThread;
}
inline const std::string &Thread::getName() const
{
return name;
}
inline void Thread::setName(const std::string &i_name)
{
name = i_name;
}
#endif