You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(47) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(140) |
Feb
(98) |
Mar
(152) |
Apr
(104) |
May
(71) |
Jun
(94) |
Jul
(169) |
Aug
(83) |
Sep
(47) |
Oct
(134) |
Nov
(7) |
Dec
(20) |
2004 |
Jan
(41) |
Feb
(14) |
Mar
(42) |
Apr
(47) |
May
(68) |
Jun
(143) |
Jul
(65) |
Aug
(29) |
Sep
(40) |
Oct
(34) |
Nov
(33) |
Dec
(97) |
2005 |
Jan
(29) |
Feb
(30) |
Mar
(9) |
Apr
(37) |
May
(13) |
Jun
(31) |
Jul
(22) |
Aug
(23) |
Sep
|
Oct
(37) |
Nov
(34) |
Dec
(117) |
2006 |
Jan
(48) |
Feb
(6) |
Mar
(2) |
Apr
(71) |
May
(10) |
Jun
(16) |
Jul
(7) |
Aug
(1) |
Sep
(14) |
Oct
(17) |
Nov
(25) |
Dec
(26) |
2007 |
Jan
(8) |
Feb
(2) |
Mar
(7) |
Apr
(26) |
May
|
Jun
(12) |
Jul
(30) |
Aug
(14) |
Sep
(9) |
Oct
(4) |
Nov
(7) |
Dec
(6) |
2008 |
Jan
(10) |
Feb
(10) |
Mar
(6) |
Apr
(8) |
May
|
Jun
(10) |
Jul
(18) |
Aug
(15) |
Sep
(16) |
Oct
(5) |
Nov
(3) |
Dec
(10) |
2009 |
Jan
(11) |
Feb
(2) |
Mar
|
Apr
(15) |
May
(31) |
Jun
(18) |
Jul
(11) |
Aug
(26) |
Sep
(52) |
Oct
(17) |
Nov
(4) |
Dec
|
2010 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sv...@ww...> - 2004-06-27 08:14:28
|
Author: mkrose Date: 2004-06-27 01:14:22 -0700 (Sun, 27 Jun 2004) New Revision: 1075 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/ThreadQueue.h Log: Added doxygen comments to ThreadQueue.h, and generalized ThreadSafePriorityQueue to support all the template parameters of std::priority_queue. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1075 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-27 07:56:34 UTC (rev 1074) +++ trunk/CSP/SimData/CHANGES.current 2004-06-27 08:14:22 UTC (rev 1075) @@ -26,6 +26,10 @@ * Add doxygen comments to ThreadLog.h + * Added doxygen comments to ThreadQueue.h, and generalized + ThreadSafePriorityQueue to support all the template parameters + of std::priority_queue. + 2004-06-22: onsight * Added a ScopedUnlock (trivial reversal of ScopedLock) Modified: trunk/CSP/SimData/Include/SimData/ThreadQueue.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadQueue.h 2004-06-27 07:56:34 UTC (rev 1074) +++ trunk/CSP/SimData/Include/SimData/ThreadQueue.h 2004-06-27 08:14:22 UTC (rev 1075) @@ -47,11 +47,29 @@ class ThreadSafeQueueBase: public NonCopyable { public: typedef TYPE ValueType; + + /** Exception class used to signal that the queue is full. + */ class Full: public std::exception { }; + + /** Exception class used to signal that the queue is empty. + */ class Empty: public std::exception { }; + + /** Return the number of elements in the queue. + */ virtual int size() const = 0; + + /** Test if the queue is empty. + */ bool empty() const { return size() == 0; } + + /** Test if the queue is full. + */ bool full() const { return m_maxsize > 0 && size() >= m_maxsize; } + + /** Put an element into the queue. + */ void put(TYPE item, bool block = true) { m_notFull.lock(); while (full()) { @@ -65,6 +83,14 @@ m_notFull.unlock(); m_notEmpty.signal(); } + + /** Retrieve (and remove) the element at the front of the queue. + * + * @param item (output) item retrieved from the queue. + * @param block if true, this method will wait until an element is + * available; otherwise it will return immediately. + * @return true if an item was retrieved, false otherwise. + */ bool get(TYPE &item, bool block = true) { m_notEmpty.lock(); while (empty()) { @@ -79,6 +105,14 @@ m_notFull.signal(); return true; } + + /** Retrieve (and remove) the element at the front of the queue. + * + * @param item (output) item retrieved from the queue. + * @param timeout the maximum time (in seconds) to wait for an item to + * retrieve. + * @return true if an item was retrieved, false otherwise. + */ bool get(TYPE &item, double timeout) { m_notEmpty.lock(); while (empty()) { @@ -92,12 +126,27 @@ m_notFull.signal(); return true; } + protected: + /** Construtor. + * + * @param maxsize the upper limit on the size of the queue; or zero for no limit. + */ ThreadSafeQueueBase(int maxsize) : m_mutex(), m_notEmpty(m_mutex), m_notFull(m_mutex), m_maxsize(maxsize) {} + + /** Destructor. + */ virtual ~ThreadSafeQueueBase() { } + + /** Add an item to the queue. + */ virtual void pushItem(TYPE &item) = 0; + + /** Retrieve and remove an item from the queue. + */ virtual TYPE popItem() = 0; + private: ThreadMutex m_mutex; ThreadCondition m_notEmpty; @@ -111,18 +160,32 @@ template <typename TYPE> class ThreadSafeQueue: public ThreadSafeQueueBase<TYPE> { public: + /** Create a new thread-safe queue. + * + * @param maxsize the upper limit on the size of the queue; or zero for no limit. + */ ThreadSafeQueue(int maxsize = 0): ThreadSafeQueueBase<TYPE>(maxsize) {} + + /** Return the number of elements in the queue. + */ virtual int size() const { return m_queue.size(); } + protected: + /** Add an item to the bottom of the queue. + */ virtual void pushItem(TYPE &item) { m_queue.push(item); } + + /** Retrieve and remove an item from the top of the queue. + */ virtual TYPE popItem() { assert(size() > 0); TYPE item = m_queue.front(); m_queue.pop(); return item; } + private: std::queue<TYPE> m_queue; }; @@ -130,23 +193,38 @@ /** A thread-safe priority queue that supports multiple producers and consumers. */ -template <typename TYPE> +template <typename TYPE, typename SEQUENCE = std::vector<TYPE>, + typename COMPARE = std::less<typename SEQUENCE::value_type> > class ThreadSafePriorityQueue: public ThreadSafeQueueBase<TYPE> { public: + /** Create a new thread-safe priority queue. + * + * @param maxsize the upper limit on the size of the queue; or zero for no limit. + */ ThreadSafePriorityQueue(int maxsize = 0): ThreadSafeQueueBase<TYPE>(maxsize) {} + + /** Return the number of elements in the queue. + */ virtual int size() const { return m_queue.size(); } + protected: + /** Add an item to the bottom of the queue. + */ virtual void pushItem(TYPE &item) { m_queue.push(item); } + + /** Retrieve and remove an item from the top of the queue. + */ virtual TYPE popItem() { assert(size() > 0); TYPE item = m_queue.front(); m_queue.pop(); return item; } + private: - std::priority_queue<TYPE> m_queue; + std::priority_queue<TYPE, SEQUENCE, COMPARE> m_queue; }; |
From: <sv...@ww...> - 2004-06-27 07:56:42
|
Author: mkrose Date: 2004-06-27 00:56:34 -0700 (Sun, 27 Jun 2004) New Revision: 1074 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/LogStream.h trunk/CSP/SimData/Include/SimData/ThreadLog.h Log: Add doxygen comments to ThreadLog.h Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1074 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-27 07:35:54 UTC (rev 1073) +++ trunk/CSP/SimData/CHANGES.current 2004-06-27 07:56:34 UTC (rev 1074) @@ -24,6 +24,8 @@ * Improved the traceback generation under linux. Tracebacks can be decoded with the tools/trace program. + * Add doxygen comments to ThreadLog.h + 2004-06-22: onsight * Added a ScopedUnlock (trivial reversal of ScopedLock) Modified: trunk/CSP/SimData/Include/SimData/LogStream.h =================================================================== --- trunk/CSP/SimData/Include/SimData/LogStream.h 2004-06-27 07:35:54 UTC (rev 1073) +++ trunk/CSP/SimData/Include/SimData/LogStream.h 2004-06-27 07:56:34 UTC (rev 1074) @@ -76,10 +76,12 @@ { public: - /** Constructor */ + /** Constructor + */ LogBuffer(); - /** Destructor */ + /** Destructor + */ ~LogBuffer(); /** Test if logging is enabled. Modified: trunk/CSP/SimData/Include/SimData/ThreadLog.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadLog.h 2004-06-27 07:35:54 UTC (rev 1073) +++ trunk/CSP/SimData/Include/SimData/ThreadLog.h 2004-06-27 07:56:34 UTC (rev 1074) @@ -40,11 +40,10 @@ NAMESPACE_SIMDATA -/** An output-only, category-based log stream. +/** A steam buffer class for thread-safe logging. * - * logbuf is an output-only streambuf with the ability to disable sets of - * messages at runtime. Only messages with priority >= logbuf::logPriority - * and debugClass == logbuf::logClass are output. + * StringBufs are used internally by ThreadLog to provide serialized + * access to a LogStream. */ class SIMDATA_EXPORT StringBuf: public NonCopyable, public std::streambuf { @@ -60,22 +59,31 @@ protected: + // accessed directly by ThreadLog LogStream &m_log; typedef ScopedLock<LogStream> ScopedLogLock; + /** Default constructor, connects to the global simdata log. + */ StringBuf(): m_category(LOG_ALL), m_priority(LOG_INFO), m_file(0), m_line(0), m_log(::simdata::log()) { init(); } + /** Constructor, connects to the specified LogStream + */ StringBuf(LogStream &base): m_category(LOG_ALL), m_priority(LOG_INFO), m_log(base) { init(); } + /** Overflow (cache characters internally) + */ virtual int overflow(int c) { m_buffer.push_back(static_cast<char>(c)); return 1; } + /** Sync/flush the cached log entry to the underlying LogStream + */ virtual int sync() { ScopedLogLock lock(m_log); std::ostream &entry = m_log.entry(m_priority, m_category, m_file, m_line); @@ -85,6 +93,8 @@ return 1; } + /** Cache the log entry parameters. + */ inline void setPrefix(int priority, int category, const char *file, int line) { m_priority = priority; m_category = category; @@ -94,56 +104,95 @@ }; + +/** A thread-safe logging class that provides serialized access to an + * underlying LogStream instance. The public interface is the same as + * LogStream, and the logging macro as defined to use thread-specific + * ThreadLog instances instead of the global LogStream whenever threading + * is enabled. + */ class SIMDATA_EXPORT ThreadLog: private StringBuf, protected std::ostream { public: + /** Default constructor, connects to the global simdata log. + */ ThreadLog(): std::ostream(this) {} + /** Constructor, connects to the specified LogStream + */ ThreadLog(LogStream &base): StringBuf(base), std::ostream(this) {} + /** Close the underlying (shared) LogStream. + */ void _close() { ScopedLogLock lock(m_log); m_log._close(); } + /** Set the output stream used by the underlying (shared) LogStream. + */ void setOutput(std::ostream& out_) { ScopedLogLock lock(m_log); m_log.setOutput(out_); } + /** Set the output file used by the underlying (shared) LogStream. + */ void setOutput(std::string const &filename) { ScopedLogLock lock(m_log); m_log.setOutput(filename); } + /** Set the logging priority threshold of the underlying (shared) LogStream. + */ void setLogPriority(int p) { ScopedLogLock lock(m_log); m_log.setLogPriority(p); } + /** Set the logging category mask of the underlying (shared) LogStream. + */ void setLogCategory(int c) { ScopedLogLock lock(m_log); m_log.setLogCategory(c); } + /** Enable or disable point logging (source file and line number) by the + * underlying (shared) LogStream. + */ void setPointLogging(bool enabled) { ScopedLogLock lock(m_log); m_log.setPointLogging(enabled); } + /** Get the point logging state of the underlying (shared) LogStream. + */ bool getPointLogging() const { return m_log.getPointLogging(); } + /** Enable or disable time stamping of log entries written to the + * underlying (shared) LogStream. + */ void setTimeLogging(bool enabled) { ScopedLogLock lock(m_log); m_log.setTimeLogging(enabled); } + /** Get the time logging state of the underlying (shared) LogStream. + */ bool getTimeLogging() const { return m_log.getTimeLogging(); } + /** Method for logging a message to the underlying (shared) LogStream. + * + * @param priority priority of this message. + * @param category category of this message (default ALL). + * @param file source file that generated this message; typically __FILE__. + * @param line line number of the code that generated this message (typically __LINE__). + * @return an output stream to receive the message contents. + */ std::ostream & entry(int priority, int category=LOG_ALL, const char *file=0, int line=0) { setPrefix(priority, category, file, line); return *this; |
From: <sv...@ww...> - 2004-06-27 07:36:01
|
Author: mkrose Date: 2004-06-27 00:35:54 -0700 (Sun, 27 Jun 2004) New Revision: 1073 Added: trunk/CSP/SimData/Include/SimData/ThreadLog.h Modified: trunk/CSP/CSPSim/Bin/CSPSim.py trunk/CSP/CSPSim/CHANGES.current trunk/CSP/CSPSim/Include/Log.h trunk/CSP/CSPSim/Source/CSPSim.cpp trunk/CSP/CSPSim/Source/Exception.cpp trunk/CSP/CSPSim/Source/ServerNode.cpp trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/ExceptionBase.h trunk/CSP/SimData/Include/SimData/Log.h trunk/CSP/SimData/Include/SimData/Log.i trunk/CSP/SimData/Include/SimData/LogStream.h trunk/CSP/SimData/Include/SimData/Ref.h trunk/CSP/SimData/Include/SimData/Thread.h trunk/CSP/SimData/Include/SimData/ThreadBase.h trunk/CSP/SimData/Include/SimData/Trace.h trunk/CSP/SimData/Source/BaseType.cpp trunk/CSP/SimData/Source/ExceptionBase.cpp trunk/CSP/SimData/Source/InterfaceRegistry.cpp trunk/CSP/SimData/Source/LogStream.cpp trunk/CSP/SimData/Source/Makefile trunk/CSP/SimData/Source/SConscript trunk/CSP/SimData/setup.py Log: SimData: - Major overhaul of the logging system. Added threadsafe logging. Added (optional) timestamps and source file/line. Priority value now logged as first character. Environment variables SIMDATA_LOGFILE and SIMDATA_LOGPRIORITY override the default values of stderr and 0 (BULK). - Several bug fixes in the thread code, and much better handling of error codes. Split larger functions out of ThreadBase.h into ThreadBase.cpp. - Enhanced the exception classes to record stack traces (linux only for now). Additional convenience methods for logging and outputing to streams. - Improved the traceback generation under linux. Tracebacks can be decoded with the tools/trace program. CSPSim: - Fixes for changes in the SimData api (logging and exceptions). Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1073 Diff omitted (68630 bytes). |
From: <sv...@ww...> - 2004-06-27 07:17:01
|
Author: mkrose Date: 2004-06-27 00:16:54 -0700 (Sun, 27 Jun 2004) New Revision: 1072 Modified: trunk/CSP/SimData/Include/SimData/AtomicCounter.h trunk/CSP/SimData/Include/SimData/ThreadQueue.h Log: Add guards to disable thread-related code if SIMDATA_NOTHREADS is defined. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1072 Modified: trunk/CSP/SimData/Include/SimData/AtomicCounter.h =================================================================== --- trunk/CSP/SimData/Include/SimData/AtomicCounter.h 2004-06-27 06:48:44 UTC (rev 1071) +++ trunk/CSP/SimData/Include/SimData/AtomicCounter.h 2004-06-27 07:16:54 UTC (rev 1072) @@ -26,6 +26,8 @@ */ +#ifndef SIMDATA_NOTHREADS + #ifndef __SIMDATA_ATOMICCOUNTER_H__ #define __SIMDATA_ATOMICCOUNTER_H__ @@ -168,3 +170,4 @@ #endif // __SIMDATA_ATOMICCOUNTER_H__ +#endif // SIMDATA_NOTHREADS Modified: trunk/CSP/SimData/Include/SimData/ThreadQueue.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadQueue.h 2004-06-27 06:48:44 UTC (rev 1071) +++ trunk/CSP/SimData/Include/SimData/ThreadQueue.h 2004-06-27 07:16:54 UTC (rev 1072) @@ -26,6 +26,8 @@ */ +#ifndef SIMDATA_NOTHREADS + #ifndef __SIMDATA_THREADQUEUE_H__ #define __SIMDATA_THREADQUEUE_H__ @@ -152,3 +154,4 @@ #endif // __SIMDATA_THREADQUEUE_H__ +#endif // SIMDATA_NOTHREADS |
From: <sv...@ww...> - 2004-06-27 06:48:50
|
Author: mkrose Date: 2004-06-26 23:48:44 -0700 (Sat, 26 Jun 2004) New Revision: 1071 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Matrix3.h Log: Fix tabs in Matrix.h Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1071 Diff omitted (15856 bytes). |
From: <sv...@ww...> - 2004-06-27 06:47:13
|
Author: mkrose Date: 2004-06-26 23:47:07 -0700 (Sat, 26 Jun 2004) New Revision: 1070 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h trunk/CSP/SimData/Include/SimData/InterfaceRegistry.i Log: Remove superflous logging in interface registry, and suppress swig warnings. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1070 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-27 06:44:09 UTC (rev 1069) +++ trunk/CSP/SimData/CHANGES.current 2004-06-27 06:47:07 UTC (rev 1070) @@ -1,6 +1,10 @@ Version 0.4.0 (in progress) =========================== +2004-06-26: onsight + * Remove superflous logging in interface registry, and suppress + swig warnings. + 2004-06-22: onsight * Added a ScopedUnlock (trivial reversal of ScopedLock) Modified: trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h =================================================================== --- trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h 2004-06-27 06:44:09 UTC (rev 1069) +++ trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h 2004-06-27 06:47:07 UTC (rev 1070) @@ -599,7 +599,6 @@ std::string _classname = #classname; \ SIMDATA(hasht) _classhash = classname::_getClassHash(); \ if (!_interface) { \ - SIMDATA_LOG(SIMDATA(LOG_ALL), SIMDATA(LOG_ERROR), "constructing interfaceproxy for " << #classname); \ _interface = new SIMDATA(ObjectInterface)<classname>; \ (*_interface) Modified: trunk/CSP/SimData/Include/SimData/InterfaceRegistry.i =================================================================== --- trunk/CSP/SimData/Include/SimData/InterfaceRegistry.i 2004-06-27 06:44:09 UTC (rev 1069) +++ trunk/CSP/SimData/Include/SimData/InterfaceRegistry.i 2004-06-27 06:47:07 UTC (rev 1070) @@ -29,9 +29,18 @@ %include "SimData/vector.i" NAMESPACE_SIMDATA + %newobject InterfaceProxy::createObject; + +// silence swig warningns about unknown base class Singleton<InterfaceRegistry> +class InterfaceRegistry; +template <class T> class Singleton; +%template(SingletonInterfaceRegistry) Singleton<InterfaceRegistry>; +%warnfilter(402) InterfaceRegistry; + NAMESPACE_SIMDATA_END + %exception { try { $action |
From: <sv...@ww...> - 2004-06-27 06:44:15
|
Author: mkrose Date: 2004-06-26 23:44:09 -0700 (Sat, 26 Jun 2004) New Revision: 1069 Modified: trunk/CSP/CSPSim/CHANGES.current trunk/CSP/CSPSim/Source/ConsoleCommands.cpp trunk/CSP/CSPSim/Source/GameScreen.cpp Log: Fixed indentation. Rearrange headers to suppress a warning in py_config.h. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1069 Modified: trunk/CSP/CSPSim/CHANGES.current =================================================================== --- trunk/CSP/CSPSim/CHANGES.current 2004-06-27 02:57:47 UTC (rev 1068) +++ trunk/CSP/CSPSim/CHANGES.current 2004-06-27 06:44:09 UTC (rev 1069) @@ -1,6 +1,11 @@ Version 0.4.0 (in progress) =========================== +2004-06-26: onsight + * Fixed indentation. + + * Rearrange headers to suppress a warning in py_config.h. + 2004-06-20: onsight * Changed doxygen control file to recurse into the variou subdirectories (Systems, Theater, etc). Modified: trunk/CSP/CSPSim/Source/ConsoleCommands.cpp =================================================================== --- trunk/CSP/CSPSim/Source/ConsoleCommands.cpp 2004-06-27 02:57:47 UTC (rev 1068) +++ trunk/CSP/CSPSim/Source/ConsoleCommands.cpp 2004-06-27 06:44:09 UTC (rev 1069) @@ -23,6 +23,16 @@ **/ +// python ends up defining _POSIX_C_SOURCE, without testing if it has +// previously been defined. ConsoleCommands.h ultimately includes stl +// headers than bring in features.h, which also define this constant, +// but are more careful about overriding previous definitions. So +// although we generally put the header file associated with a cpp +// file first in the includes list, moving Python.h to the front of +// the list serves to suppress this warning (and the dozen or so lines +// of diagnostic output that g++ emits). +#include <Python.h> + #include "ConsoleCommands.h" #include "Console.h" #include "Shell.h" Modified: trunk/CSP/CSPSim/Source/GameScreen.cpp =================================================================== --- trunk/CSP/CSPSim/Source/GameScreen.cpp 2004-06-27 02:57:47 UTC (rev 1068) +++ trunk/CSP/CSPSim/Source/GameScreen.cpp 2004-06-27 06:44:09 UTC (rev 1069) @@ -206,10 +206,10 @@ m_ActiveObject(0), m_CameraAgent(ViewFactory()), m_CurrentCameraCommand(0) { - initInterface(); - createCameraCommand(); + initInterface(); + createCameraCommand(); } - + GameScreen::~GameScreen() { deleteCameraCommands(); } |
From: <sv...@ww...> - 2004-06-27 02:57:53
|
Author: mkrose Date: 2004-06-26 19:57:47 -0700 (Sat, 26 Jun 2004) New Revision: 1068 Added: trunk/CSP/tools/trace Log: Add stack trace decoding tool for linux. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1068 Added: trunk/CSP/tools/trace =================================================================== --- trunk/CSP/tools/trace 2004-06-27 01:04:57 UTC (rev 1067) +++ trunk/CSP/tools/trace 2004-06-27 02:57:47 UTC (rev 1068) @@ -0,0 +1,258 @@ +#!/usr/bin/python +# +# Copyright 2004 Mark Rose <mk...@us...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#!/usr/bin/python + +""" +Decode SimData stack traces under GNU/Linux. + +Reads a stack trace from stdin, and dumps a more readable form of +the stack trace to stdout. The easiest way to use this program is +to select the stack trace using the mouse, run %(prog)s, and then +paste the stack trace into the terminal window (you'll also need +to type <ctrl-d> to close stdin). + +Caveats: + +This program relies on GNU-specific tools, both to decode binary +addresses into source files and line numbers, and to demangle C++ +symbol names. When SimData supports stack trace generation under +Windows, a comparable mechanism for decoding them will be devised. + +Since the stack trace includes relative paths to shared libraries, +this program must be run from the same directory as the program +that generated the stack trace. Alternatively, you can specify the +'--dir' flag to set the base directory. Either way, the program +and all shared libaries must be available in order to properly +decode the stack trace. + +Usage: %(prog)s [options] +""" + +import sys +import os +import re +import os.path + +import bootstrap + +from CSP.base import app + + +re_trace1 = re.compile(r'\s+([^(]+)[(]([A-Z_0-9a-z]+)\+0x([0-9a-f]+)[)]\s+\[0x([0-9a-f]+)\]') +re_trace2 = re.compile(r'\s*(\S+)\s+\[0x([0-9a-f]+)\]') + + +def filt(mangled): + """Demangle a C++ symbol""" + return os.popen('c++filt %s' % mangled).readline().strip() + +def addr2line(bin, offset): + """ + Translate a object file offset into a source file name and line number. + + The object file must have been compiled with debugging symbols (and not + subsequently stripped). + """ + return os.popen('addr2line -e %s %x' % (bin, offset)).readline().strip() + +def fixpath(dir, path): + """ + Translate a path relative to the specified directory. Absolute paths are + unchanged. + """ + if not os.path.isabs(path): + path = os.path.join(dir, path) + path = os.path.normpath(path) + return path + + +class Symbols: + """ + Object file symbol table reader and cache. + """ + + class SymbolSet: + """ + An index for the symbol table of a single object file. + """ + + def __init__(self): + self._table = {} + self._index = [] + + def add(self, method, addr): + """Add a new symbol to the index.""" + self._table[method] = addr + self._index.append((addr, method)) + + def search(self, addr): + """Search for the symbol at, or immediately preceding, address.""" + index = self._index + if not index: return '' + A = 0 + B = len(index) + n = B / 2 + while B - A > 1: + at = index[n][0] + if at > addr: + B = n + else: + A = n + n = (A + B) / 2 + if n == len(index): return '' + return index[n][1] + + def get(self, symbol, default=0): + """Return the address of a symbol, or default.""" + return self._table.get(symbol, default) + + def __init__(self): + self._syms = {} + + def getsym(self, lib): + """ + Get the SymbolSet for the specified object file. SymbolSets are cached, + so subsequent calls for a given object file are cheap. + """ + syms = self._syms + sym = syms.get(lib, None) + if sym: return sym + symset = Symbols.SymbolSet() + cin, cout, cerr = os.popen3('nm -n %s' % lib) + for line in cout.readlines(): + parts = line.strip().split() + if len(parts) == 3: + addr, type, method = line.strip().split() + addr = int(addr, 16) + symset.add(method, addr) + syms[lib] = symset + return symset + + +class StackTrace: + + def __init__(self): + self._symbols = Symbols() + self._offsets = {} + + def _decode1(self, dir, line, parts): + """ + Decode stack trace lines that match re_trace1. + """ + lib = fixpath(dir, parts[0]) + if not os.path.exists(lib): + print >>sys.stderr, 'unable to find object file (%s); may need to specify --dir' % lib + sys.exit(1) + method = parts[1] + offset = int(parts[2], 16) + image = int(parts[3], 16) + real_name = filt(method) + symset = self._symbols.getsym(lib) + method_address = symset.get(method, default=0) + if method_address: + address = method_address + offset + self._offsets[lib] = address - image + point = addr2line(lib, address) + return '%s (%s)' % (real_name, point) + else: + symbol = symset.search(image) + if symbol: real_name = filt(symbol) + point = addr2line(lib, image) + if point.find('?') < 0: + return '%s (%s)' % (real_name, point) + return '%s (%s+0x%x) [0x%x]' % (os.path.basename(lib), real_name, offset, image) + + def _decode2(self, dir, line, parts): + """ + Decode stack trace lines that match re_trace2. + """ + lib, addr = parts + lib = fixpath(dir, lib) + if not os.path.exists(lib): + print >>sys.stderr, 'unable to find object file (%s); may need to specify --dir' % lib + sys.exit(1) + addr = int(addr, 16) + offset = self._offsets.get(lib, 0) + symset = self._symbols.getsym(lib) + symbol = symset.search(addr + offset) + if symbol: + point = addr2line(lib, addr) + if point.find('?') < 0: + return '%s (%s)' % (filt(symbol), point) + else: + return '%s (%s)' % (filt(symbol), os.path.basename(lib)) + return '%s [0x%x]' % (os.path.basename(lib), addr) + + def process(self, input, dir): + """ + Process input lines and print the decoded stack trace to stdout. + """ + start = 0 + trace = [] + output = [] + for line in input: + line = line.rstrip() + if not line: continue + + if line.find('CALL STACK BACKTRACE') >= 0: + start = 1 + continue + + m = re_trace1.match(line) + if m: + start = 1 + output.append(self._decode1(dir, line, m.groups())) + continue + + m = re_trace2.match(line) + if m: + start = 1 + output.append(self._decode2(dir, line, m.groups())) + continue + + if start and line.startswith(' '): + parts = line.split() + if len(parts): + parts[0] = os.path.basename(parts[0]) + output.append(' '.join(parts)) + + print '=============' + for idx, line in enumerate(output): + print '%2d. %s' % (idx+1, line) + + +def main(args): + if args: + app.usage() + return 1 + + try: + input = sys.stdin.readlines() + except KeyboardInterrupt: + return 0 + + dir = app.options.dir + stack_trace = StackTrace() + stack_trace.process(input, dir) + return 0 + + +app.addOption('-d', '--dir', default='.', help='specify the starting directory of the program that generated the stack trace') +app.start() + + Property changes on: trunk/CSP/tools/trace ___________________________________________________________________ Name: svn:executable + * |
From: <sv...@ww...> - 2004-06-27 01:05:03
|
Author: wolverine Date: 2004-06-26 18:04:57 -0700 (Sat, 26 Jun 2004) New Revision: 1067 Modified: trunk/CSP/CSPSim/Source/ClientNode.cpp trunk/CSP/CSPSim/Source/DynamicObject.cpp trunk/CSP/CSPSim/Source/Networking/DispatchMessageHandler.cpp trunk/CSP/CSPSim/Source/Networking/EchoMessageHandler.cpp trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp trunk/CSP/CSPSim/Source/Networking/PrintMessageHandler.cpp trunk/CSP/CSPSim/Source/ServerNode.cpp trunk/CSP/CSPSim/Source/cCSP.i Log: changes related receiving handling Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1067 Diff omitted (26588 bytes). |
From: <sv...@ww...> - 2004-06-27 00:46:45
|
Author: wolverine Date: 2004-06-26 17:46:39 -0700 (Sat, 26 Jun 2004) New Revision: 1066 Added: trunk/CSP/CSPSim/Include/Networking.i Modified: trunk/CSP/CSPSim/Include/ClientNode.h trunk/CSP/CSPSim/Include/Networking.h Log: changes related receiving handling Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1066 Modified: trunk/CSP/CSPSim/Include/ClientNode.h =================================================================== --- trunk/CSP/CSPSim/Include/ClientNode.h 2004-06-23 16:47:53 UTC (rev 1065) +++ trunk/CSP/CSPSim/Include/ClientNode.h 2004-06-27 00:46:39 UTC (rev 1066) @@ -5,9 +5,23 @@ { public: - ClientNode(); - int run(); - + ClientNode(); + int run(); + protected: + + void init(); + void dumpSizes(); + void initNetworking(); + + VirtualBattlefield * m_battlefield; + simdata::DataManager m_DataManager; + NetworkMessenger * m_networkMessenger; + NetworkNode * m_remoteNode; + NetworkNode * m_localNode; + Port m_localPort; + std::string m_localHost; + Port m_remotePort; + std::string m_remoteHost; }; Modified: trunk/CSP/CSPSim/Include/Networking.h =================================================================== --- trunk/CSP/CSPSim/Include/Networking.h 2004-06-23 16:47:53 UTC (rev 1065) +++ trunk/CSP/CSPSim/Include/Networking.h 2004-06-27 00:46:39 UTC (rev 1066) @@ -246,32 +246,7 @@ NetworkMessage * m_message; }; -class MessageSocketDuplex -{ - ost::UDPSocket * m_UDPReceiverSocket; - ost::UDPSocket * m_UDPSenderSocket; - - ost::InetAddress * m_receiverAddr; - Port m_receiverPort; - - public: - MessageSocketDuplex(); // set the listener port to unbound. - MessageSocketDuplex(ost::InetAddress & Address, Port port); // set the bound address and port. - MessageSocketDuplex(Port port); // set the bound port. - - int sendto(NetworkMessage * message, ost::InetHostAddress * remoteAddress, Port * remotePort); - int sendto(NetworkMessage * message, NetworkNode * node); - - int recvfrom(NetworkMessage ** message); - int sendto(std::vector<RoutedMessage> * sendArray, int count); - int recvfrom(std::vector<RoutedMessage> * receiveArray, int * count); - - ost::InetAddress * getReceiverAddress() { return m_receiverAddr; } - Port getReceiverPort() { return m_receiverPort; } - -}; - class DynamicObject; class RemoteObjectWrapper @@ -337,6 +312,8 @@ void queueMessage(NetworkNode * remoteNode, NetworkMessage * message); void sendQueuedMessages(); void receiveMessages(); + void receiveMessages(int max); + int getSendQueueCount() { return m_messageSendArrayCount; } NetworkNode * getOriginatorNode(); void setOriginatorNode(NetworkNode * orginatorNode); @@ -366,16 +343,23 @@ class NetworkMessageHandler { public: - virtual void process(NetworkMessage * message, NetworkMessenger * messenger) = 0; + virtual void process(NetworkMessage * message) = 0; }; class EchoMessageHandler : public NetworkMessageHandler { - + protected: + NetworkMessenger * m_messenger; public: EchoMessageHandler(); - virtual void process(NetworkMessage * message, NetworkMessenger * messenger); + virtual void process(NetworkMessage * message); virtual ~EchoMessageHandler(); + + + virtual void setMessenger(NetworkMessenger * messenger) + { m_messenger = messenger; } + virtual NetworkMessenger * getMessenger() + { return m_messenger; } }; @@ -386,7 +370,7 @@ int m_count; public: PrintMessageHandler(); - virtual void process(NetworkMessage * message, NetworkMessenger * messenger); + virtual void process(NetworkMessage * message); virtual ~PrintMessageHandler(); void setFrequency(int frequency) { m_frequency = frequency; } @@ -397,12 +381,21 @@ { public: DispatchMessageHandler(); - virtual void process(NetworkMessage * message, NetworkMessenger * messenger); + virtual void process(NetworkMessage * message); virtual ~DispatchMessageHandler(); + void setLocalAddress(unsigned int addr) { _addr = addr; } + unsigned int getLocalAddress() { return _addr; } + void setLocalPort(unsigned short port) { _port = port; } + unsigned short getLocalPort() { return _port; } + void setVirtualBattlefield(VirtualBattlefield * battlefield) { _virtualBattlefield = battlefield; } + VirtualBattlefield * getVirtualBattlefield() { return _virtualBattlefield; } + void setDataManager(simdata::DataManager & dataManager) { _dataManager = dataManager; } + simdata::DataManager getDataManager() { return _dataManager; } + protected: bool isLocal(unsigned int addr, unsigned short port); @@ -465,5 +458,30 @@ }; +class MessageSocketDuplex +{ + ost::UDPSocket * m_UDPReceiverSocket; + ost::UDPSocket * m_UDPSenderSocket; + + ost::InetAddress * m_receiverAddr; + Port m_receiverPort; + + public: + MessageSocketDuplex(); // set the listener port to unbound. + MessageSocketDuplex(ost::InetAddress & Address, Port port); // set the bound address and port. + MessageSocketDuplex(Port port); // set the bound port. + + int sendto(NetworkMessage * message, ost::InetHostAddress * remoteAddress, Port * remotePort); + int sendto(NetworkMessage * message, NetworkNode * node); + + int recvfrom(NetworkMessage ** message); + + int sendto(std::vector<RoutedMessage> * sendArray, int count); + int recvfrom(std::vector<RoutedMessage> * receiveArray, int * count); + + ost::InetAddress * getReceiverAddress() { return m_receiverAddr; } + Port getReceiverPort() { return m_receiverPort; } + +}; #endif Added: trunk/CSP/CSPSim/Include/Networking.i =================================================================== --- trunk/CSP/CSPSim/Include/Networking.i 2004-06-23 16:47:53 UTC (rev 1065) +++ trunk/CSP/CSPSim/Include/Networking.i 2004-06-27 00:46:39 UTC (rev 1066) @@ -0,0 +1,7 @@ +%module Networking +%{ +#include "Networking.h" +%} + +%include "Networking.h" + |
From: <sv...@ww...> - 2004-06-23 16:47:59
|
Author: mkrose Date: 2004-06-23 09:47:53 -0700 (Wed, 23 Jun 2004) New Revision: 1065 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Thread.h trunk/CSP/SimData/Include/SimData/ThreadBase.h trunk/CSP/SimData/Include/SimData/ThreadQueue.h Log: More thread cleanup: timed join, simple thread abort mechanism, accessor for the task associated with a thread, fix for a compile error and slightly improved interfaces in the queue classes. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1065 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-23 06:35:25 UTC (rev 1064) +++ trunk/CSP/SimData/CHANGES.current 2004-06-23 16:47:53 UTC (rev 1065) @@ -6,6 +6,10 @@ * Cleaned doxygen comments for some thread classes. + * More thread cleanup: timed join, simple thread abort mechanism, + accessor for the task associated with a thread, compile fixes + and improved interface in queue classes. + 2004-06-20: onsight * Doxygen and copyright notice updates. Modified: trunk/CSP/SimData/Include/SimData/Thread.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Thread.h 2004-06-23 06:35:25 UTC (rev 1064) +++ trunk/CSP/SimData/Include/SimData/Thread.h 2004-06-23 16:47:53 UTC (rev 1065) @@ -108,13 +108,13 @@ /** Suspend execution of the current thread the specified amount of time. * - * @param seconds seconds to pause - * @param nanosecondns nanoseconds to pause (in addition to seconds) + * @param seconds seconds to pause (fractional values ok, but limited by + * the granularity of the operating system's time slices). */ - static void sleep(int seconds, int nanoseconds=0) { + static void sleep(double seconds) { static ThreadCondition m_condition; m_condition.lock(); - m_condition.wait(seconds + 1e-9 * nanoseconds); + m_condition.wait(seconds); m_condition.unlock(); } @@ -145,6 +145,19 @@ */ virtual void run()=0; + /** Signal a task to abort. + * + * This is advisory only. Tasks can test for this signal by calling + * isAborted(), then ignore or honor the aborted condition in any manner. + */ + virtual void abort() { m_abort = true; } + + /** Test if a request to abort the task has been made. + * + * @return true if abort() has been called, false otherwise. + */ + bool isAborted() const { return m_abort; } + /** Returns true if this task is executing in a detached thread. Memory * resources associated with a detached thread are automatically reclaimed * when the thread exits, but other threads cannot join a detached thread. @@ -166,7 +179,7 @@ /** Initialize the task state. */ - Task(): m_running(false), m_detached(false), m_complete(false), m_thread_id(0) { + Task(): m_running(false), m_detached(false), m_complete(false), m_abort(false), m_thread_id(0) { } virtual ~Task() { } @@ -198,12 +211,12 @@ /** Begin execution of the task. */ void _execute() { - std::cout << getName() << " start\n"; m_running = true; m_thread_id = pthread_self(); run(); - std::cout << getName() << " exit\n"; m_complete = true; + // signal any threads waiting to join with us + m_exit.signalAll(); } /** Mark this task as running in a detached thread. @@ -214,11 +227,24 @@ */ void setName(std::string const &name) { m_name = name; } + /** Join this task's thread by for an internal condition variable that + * signals on exit. Used via ThreadBase. + * + * @param timeout the maximum time in seconds to wait for the task to finish. + * @return true if the task ended, false if the timeout expired. + */ + bool join(double timeout) { + ScopedLock<ThreadCondition> lock(m_exit); + return m_exit.wait(timeout); + } + std::string m_name; bool m_running; bool m_detached; bool m_complete; + bool m_abort; ThreadId m_thread_id; + ThreadCondition m_exit; }; @@ -229,22 +255,33 @@ */ class BaseThread: public NonCopyable { + // private and undefined, use BaseThread(Task*, std::string const &) BaseThread(); protected: - BaseThread(Task *task, std::string const &name): m_task(task), m_thread_id(0) { + /** Construct a new thread with a bound task. See Thread<> for details. + * + * @param task a non-null Task pointer to bind to this thread. + * @param name a unique string identifier for this thread. + */ + BaseThread(Task *task, std::string const &name): m_task(task), m_thread_id(0), m_cancelled(false) { assert(task); task->setName(name); } + /** Accessor used by Thread<> to provide type-specialized access to the + * associated task instance. + */ + Ref<Task> const &getTask() const { return m_task; } + public: + /** Destroy a thread instance and free internal resources. * * The thread will be cancelled if it is running and not detached. */ virtual ~BaseThread() { - std::cout << "~BaseThread " << m_task->getName() << "\n"; if (isActive() && !isDetached()) { cancel(); } @@ -259,19 +296,18 @@ ThreadException::check(result); } - /* - bool join(int sec, int ns) { - pthread_joinoption_np_t joinoption; - memset(&joinoption, 0, sizeof(pthread_joinoption_np_t)); - joinoption.deltatime.tv_sec = sec; - joinoption.deltatime.tv_ns = ns; - joinoption.leaveThreadAllocated = 1; - int result = pthread_extendedjoin_np(m_thread_id, 0, &joinoption); - if (result == 0) return true; - if (result == ETIMEDOUT) return false; - throw ThreadException(result); + /** Wait for at most a limited amount of time for this thread to finish. + * + * @param timeout the maximum time in seconds to wait for the task to finish. + * @return true if the task ended, false if the timeout expired. + */ + bool join(double timeout) { + assert(!isDetached()); + if (isActive()) { + return m_task->join(timeout); + } + return false; } - */ /** Detach the thread. Once detached, the resources of the thread will * be reclaimed automatically when the thread exits. Note that you @@ -294,11 +330,22 @@ * cancellation checkpoint (e.g. by calling testCancel). */ void cancel() { + if (m_cancelled) return; assert(isStarted()); const int result = pthread_cancel(m_thread_id); ThreadException::check(result); + m_cancelled = true; + //m_thread_id = 0; } + /** Signal the associated task to abort. This is an advisory request; + * the task is free to ignore or honor it in any manner. Provides a + * gentler alternative to cancel(). + */ + void abort() { + if (isStarted()) m_task->abort(); + } + /** Start the thread running. Calls run() in the new thread and returns * immediately. */ @@ -336,6 +383,7 @@ private: Task::ThreadId m_thread_id; Ref<Task> m_task; + bool m_cancelled; }; @@ -389,6 +437,13 @@ */ Thread(std::string const &name): BaseThread(new TASK(), name) { } + /** Get the associated task instance. + * + * Requires an internal downcast from Task to the template type, so + * store a local copy if this overhead is a concern. + */ + Ref<TASK> getTask() const { return BaseThread::getTask(); } + }; NAMESPACE_SIMDATA_END Modified: trunk/CSP/SimData/Include/SimData/ThreadBase.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 06:35:25 UTC (rev 1064) +++ trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 16:47:53 UTC (rev 1065) @@ -72,6 +72,9 @@ if (result != 0) throw ThreadException(result); } + int getError() const { return m_error; } + std::string getMessage() const { return m_message; } + private: void translate(const int error) { @@ -87,7 +90,7 @@ case EPERM: m_error = DENIED; default: - m_error = INTERNAL; + m_error = error + 1000; //INTERNAL; } } @@ -296,7 +299,7 @@ * signals the condition variable, one (or all) of the threads waiting * on that variable will be activated. */ -class ThreadCondition { +class ThreadCondition: public NonCopyable { public: /** Construct a condition variable, using an internal mutex. @@ -403,8 +406,6 @@ pthread_cond_t m_cond; pthread_mutex_t m_local_mutex; pthread_mutex_t &m_mutex; - ThreadCondition(const ThreadCondition &); - ThreadCondition &operator=(const ThreadCondition &); }; Modified: trunk/CSP/SimData/Include/SimData/ThreadQueue.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadQueue.h 2004-06-23 06:35:25 UTC (rev 1064) +++ trunk/CSP/SimData/Include/SimData/ThreadQueue.h 2004-06-23 16:47:53 UTC (rev 1065) @@ -63,20 +63,33 @@ m_notFull.unlock(); m_notEmpty.signal(); } - TYPE get(bool block = true) { + bool get(TYPE &item, bool block = true) { m_notEmpty.lock(); while (empty()) { if (!block) { m_notEmpty.unlock(); - throw Empty(); + return false; } m_notEmpty.wait(); } - TYPE item = popItem(); + item = popItem(); m_notEmpty.unlock(); m_notFull.signal(); - return item; + return true; } + bool get(TYPE &item, double timeout) { + m_notEmpty.lock(); + while (empty()) { + if (!m_notEmpty.wait(timeout)) { + m_notEmpty.unlock(); + return false; + } + } + item = popItem(); + m_notEmpty.unlock(); + m_notFull.signal(); + return true; + } protected: ThreadSafeQueueBase(int maxsize) : m_mutex(), m_notEmpty(m_mutex), m_notFull(m_mutex), m_maxsize(maxsize) {} @@ -103,7 +116,8 @@ m_queue.push(item); } virtual TYPE popItem() { - TYPE item = m_queue.top(); + assert(size() > 0); + TYPE item = m_queue.front(); m_queue.pop(); return item; } @@ -124,7 +138,8 @@ m_queue.push(item); } virtual TYPE popItem() { - TYPE item = m_queue.top(); + assert(size() > 0); + TYPE item = m_queue.front(); m_queue.pop(); return item; } |
From: <sv...@ww...> - 2004-06-23 06:35:32
|
Author: mkrose Date: 2004-06-22 23:35:25 -0700 (Tue, 22 Jun 2004) New Revision: 1064 Modified: trunk/CSP/SimData/Include/SimData/ThreadBase.h Log: Fix ScopedUnlock dtor name (again!) Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1064 Modified: trunk/CSP/SimData/Include/SimData/ThreadBase.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 06:26:05 UTC (rev 1063) +++ trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 06:35:25 UTC (rev 1064) @@ -463,7 +463,7 @@ /** Release the underlying lock. */ - ~ScopedUnLock() { + ~ScopedUnlock() { m_lock.lock(); } |
From: <sv...@ww...> - 2004-06-23 06:26:12
|
Author: mkrose Date: 2004-06-22 23:26:05 -0700 (Tue, 22 Jun 2004) New Revision: 1063 Modified: trunk/CSP/SimData/Include/SimData/ThreadBase.h Log: Fix ScopedUnlock dtor name. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1063 Modified: trunk/CSP/SimData/Include/SimData/ThreadBase.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 06:24:22 UTC (rev 1062) +++ trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 06:26:05 UTC (rev 1063) @@ -463,7 +463,7 @@ /** Release the underlying lock. */ - ~ScopedLock() { + ~ScopedUnLock() { m_lock.lock(); } |
From: <sv...@ww...> - 2004-06-23 06:24:31
|
Author: mkrose Date: 2004-06-22 23:24:22 -0700 (Tue, 22 Jun 2004) New Revision: 1062 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Thread.h trunk/CSP/SimData/Include/SimData/ThreadBase.h Log: Added a ScopedUnlock (trivial reversal of ScopedLock) Cleaned doxygen comments for some thread classes. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1062 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-21 07:23:32 UTC (rev 1061) +++ trunk/CSP/SimData/CHANGES.current 2004-06-23 06:24:22 UTC (rev 1062) @@ -1,6 +1,11 @@ Version 0.4.0 (in progress) =========================== +2004-06-22: onsight + * Added a ScopedUnlock (trivial reversal of ScopedLock) + + * Cleaned doxygen comments for some thread classes. + 2004-06-20: onsight * Doxygen and copyright notice updates. Modified: trunk/CSP/SimData/Include/SimData/Thread.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Thread.h 2004-06-21 07:23:32 UTC (rev 1061) +++ trunk/CSP/SimData/Include/SimData/Thread.h 2004-06-23 06:24:22 UTC (rev 1062) @@ -40,6 +40,11 @@ NAMESPACE_SIMDATA +/** + * @namespace thread + * + * @brief Global functions for manipulating threads. + */ namespace thread { @@ -78,7 +83,7 @@ } /** Terminate the current thread if there are any pending cancellation - * requests. @see cancel(). + * requests. @see Thread::cancel(). */ static void testCancel() { pthread_testcancel(); @@ -92,7 +97,7 @@ ThreadException::check(result); } - /* Set the cancellation type to be deferred. Cancellation requests will be + /** Set the cancellation type to be deferred. Cancellation requests will be * deferred until a cancellation checkpoint is reached (e.g a blocking wait * or an explicit call to testCancel()). */ @@ -217,10 +222,10 @@ }; -/** Object oriented wrapper for a Posix thread. +/** Base class for wrapping a Posix thread. * - * To create a thread, subclass Thread and implement the run() method. - * Then instantiate the class and call start(). + * This class is not used directly. To create a thread, subclass Task and + * implement the run() method. @see Thread for details. */ class BaseThread: public NonCopyable { @@ -334,6 +339,39 @@ }; +/** Class for starting and manipulating a posix thread. + * + * To create a new thread, subclass Task and implement the run() method. + * Then instantiate Thread<YourTaskSubclass>, and call the start() method. + * + * For example: + * @code + * // implement a task to run in a separate thread; this is just a + * // silly example. + * class MyTask: public simdata::Task { + * protected: + * // the task action; the thread running this task will terminate when + * // when run() returns. + * virtual void run() { + * for (int i = 0; i < 1000; i++) std::cout << "hello " << i << "\n"; + * } + * }; + * + * void start_a_couple_tasks() { + * // construct a couple threads to execute MyTask + * simdata::Thread<MyTask> task1("hello writer 1"); + * simdata::Thread<MyTask> task2("hello writer 2"); + * + * // start both tasks + * task1.start(); + * task2.start(); + * + * // wait for both tasks to finish + * task1.join() + * task2.join() + * } + * @endcode + */ template <class TASK> class Thread: public BaseThread { Modified: trunk/CSP/SimData/Include/SimData/ThreadBase.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-21 07:23:32 UTC (rev 1061) +++ trunk/CSP/SimData/Include/SimData/ThreadBase.h 2004-06-23 06:24:22 UTC (rev 1062) @@ -109,15 +109,17 @@ friend class ThreadCondition; public: /** Mutex types: - * DEFAULT : same as NORMAL - * NORMAL : non-reentrant; attempts to relock by a single thread, - * or to lock a mutex held by another thread that terminated - * will cause a deadlock. - * RECURSIVE : reentrant; can be relocked by a thread without causing - * a deadlock. The mutex will be held until it has been - * unlocked as many times as it was locked. - * ERRORCHECK : like NORMAL; but returns an error in situations that would - * normally result in a deadlock. + * <dl> + * <dt>DEFAULT <dd>same as NORMAL + * <dt>NORMAL <dd>non-reentrant; attempts to relock by a single thread, + * or to lock a mutex held by another thread that terminated + * will cause a deadlock. + * <dt>RECURSIVE <dd>reentrant; can be relocked by a thread without causing + * a deadlock. The mutex will be held until it has been + * unlocked as many times as it was locked. + * <dt>ERRORCHECK <dd>like NORMAL; but returns an error in situations that would + * normally result in a deadlock. + * </dl> */ typedef enum { DEFAULT, NORMAL, RECURSIVE, ERRORCHECK } MutexType; @@ -158,8 +160,8 @@ * * This method will block if another thread holds the mutex lock. * If the current thread has already locked the mutex, the behavior - * depends on the type of mutex specified during construction (@see - * MutexType). + * depends on the type of mutex specified during construction (see + * ThreadMutex::MutexType). */ void lock() { const int result = pthread_mutex_lock(&m_mutex); @@ -445,6 +447,31 @@ }; +/** Similar to ScopedLock, but unlocks the mutex for the duration of + * its existence, then relocks the mutex on destruction. + */ +template <class LOCK> +class ScopedUnlock { +public: + /** Construct a new scoped lock for a existing lockable instance. If constructed + * an the stack, this will immediately lock the instance for the duration of the + * current scope. + */ + ScopedUnlock(LOCK &lock): m_lock(lock) { + m_lock.unlock(); + } + + /** Release the underlying lock. + */ + ~ScopedLock() { + m_lock.lock(); + } + +private: + LOCK &m_lock; +}; + + /** Wrapper for allocating a global resource such that each thread receives * a separate, private instance. Thread specific instances do not require * any locking, since each thread has its own copy. |
From: <sv...@ww...> - 2004-06-21 07:23:38
|
Author: mkrose Date: 2004-06-21 00:23:32 -0700 (Mon, 21 Jun 2004) New Revision: 1061 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h trunk/CSP/SimData/Source/InterfaceRegistry.cpp Log: Slight refactoring and cleanup of InterfaceRegistry. Subclassed singleton<InterfaceRegistry>, converted some pointer fields to member variables, tweaked the init and cleanup. Hopefully this won't break the static initializers used to register interfaces. Works fine under linux but needs to be tested under windows. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1061 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-21 07:16:54 UTC (rev 1060) +++ trunk/CSP/SimData/CHANGES.current 2004-06-21 07:23:32 UTC (rev 1061) @@ -28,6 +28,12 @@ * Minor fixups to Trace.h (needs more work, and really needs a win32 implementation). + * Slight refactoring and cleanup of InterfaceRegistry. Subclassed + singleton<InterfaceRegistry>, converted some pointer fields to + member variables, tweaked the init and cleanup. Hopefully this + won't break the static initializers used to register interfaces. + Works fine under linux but needs to be tested under windows. + 2004-06-16: onsight * Doxygen cleanups. Modified: trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h =================================================================== --- trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h 2004-06-21 07:16:54 UTC (rev 1060) +++ trunk/CSP/SimData/Include/SimData/InterfaceRegistry.h 2004-06-21 07:23:32 UTC (rev 1061) @@ -347,8 +347,9 @@ * * @author Mark Rose <mr...@st...> */ -class InterfaceRegistry { +class InterfaceRegistry: public Singleton<InterfaceRegistry> { +friend class Singleton<InterfaceRegistry>; friend class InterfaceProxy; public: @@ -389,18 +390,12 @@ /** Get the interface registry singleton. */ static InterfaceRegistry &getInterfaceRegistry() { - return Singleton<InterfaceRegistry>::getInstance(); + return getInstance(); } -#if defined(_MSC_VER ) && (_MSC_VER <= 1200) - virtual ~InterfaceRegistry(); -#endif - private: -#if !defined(_MSC_VER ) || (_MSC_VER > 1200) virtual ~InterfaceRegistry(); -#endif /** Add an interface to the registry. * @@ -409,17 +404,15 @@ */ void addInterface(const char *name, hasht id, InterfaceProxy *proxy) throw(InterfaceError); - friend class Singleton<InterfaceRegistry>; + //friend class Singleton<InterfaceRegistry>; InterfaceRegistry(); - void __cleanup(); - typedef HASH_MAPS<const char*, InterfaceProxy*, HASH<const char*>, eqstr>::Type proxy_map; typedef HASHT_MAP<InterfaceProxy*>::Type proxy_id_map; - proxy_map *__map; - proxy_id_map *__id_map; - interface_list *__list; + proxy_map __map; + proxy_id_map __id_map; + interface_list __list; }; Modified: trunk/CSP/SimData/Source/InterfaceRegistry.cpp =================================================================== --- trunk/CSP/SimData/Source/InterfaceRegistry.cpp 2004-06-21 07:16:54 UTC (rev 1060) +++ trunk/CSP/SimData/Source/InterfaceRegistry.cpp 2004-06-21 07:23:32 UTC (rev 1061) @@ -127,75 +127,54 @@ // InterfaceRegistry -InterfaceRegistry::InterfaceRegistry(): __map(0), __id_map(0), __list(0) { +InterfaceRegistry::InterfaceRegistry() { + SIMDATA_LOG(LOG_REGISTRY, LOG_DEBUG, "Initializing interface registry."); } InterfaceRegistry::~InterfaceRegistry() { - __cleanup(); -} - -void InterfaceRegistry::__cleanup() { SIMDATA_LOG(LOG_REGISTRY, LOG_DEBUG, "Destroying the interface registry."); - if (__map) delete __map; __map = 0; - if (__id_map) delete __id_map; __id_map = 0; - if (__list) delete __list; __list = 0; } InterfaceProxy *InterfaceRegistry::getInterface(const char *name) { - if (!__map) return 0; - proxy_map::iterator i = __map->find(name); - if (i == __map->end()) return 0; + proxy_map::iterator i = __map.find(name); + if (i == __map.end()) return 0; return i->second; } InterfaceProxy *InterfaceRegistry::getInterface(hasht key) { - if (!__id_map) return 0; - proxy_id_map::iterator i = __id_map->find(key); - if (i == __id_map->end()) return 0; + proxy_id_map::iterator i = __id_map.find(key); + if (i == __id_map.end()) return 0; return i->second; } bool InterfaceRegistry::hasInterface(const char *name) { - if (!__map) return false; - return (__map->find(name) != __map->end()); + return (__map.find(name) != __map.end()); } bool InterfaceRegistry::hasInterface(hasht key) { - if (!__id_map) return false; - return (__id_map->find(key) != __id_map->end()); + return (__id_map.find(key) != __id_map.end()); } std::vector<std::string> InterfaceRegistry::getInterfaceNames() const { std::vector<std::string> names; - if (__list) { - interface_list::const_iterator i; - for (i = __list->begin(); i != __list->end(); i++) { - names.push_back((*i)->getClassName()); - } + interface_list::const_iterator i; + for (i = __list.begin(); i != __list.end(); i++) { + names.push_back((*i)->getClassName()); } return names; } std::vector<InterfaceProxy *> InterfaceRegistry::getInterfaces() const { - if (__list) return *__list; - return interface_list(); + return __list; } void InterfaceRegistry::addInterface(const char *name, hasht id, InterfaceProxy *proxy) throw(InterfaceError) { - if (__map == 0) { - //cout << "Initializing interface registry." << endl; - SIMDATA_LOG(LOG_REGISTRY, LOG_DEBUG, "Initializing interface registry."); - __map = new proxy_map; - __id_map = new proxy_id_map; - __list = new interface_list; - } if (hasInterface(name)) { throw InterfaceError("interface \"" + std::string(name) + "\" multiply defined"); } - (*__map)[name] = proxy; - (*__id_map)[id] = proxy; - __list->push_back(proxy); - //cout << "Registering interface<" << name << "> [" << id << "]" << endl; + __map[name] = proxy; + __id_map[id] = proxy; + __list.push_back(proxy); SIMDATA_LOG(LOG_REGISTRY, LOG_DEBUG, "Registering interface<" << name << "> [" << id << "]"); } |
From: <sv...@ww...> - 2004-06-21 07:17:00
|
Author: mkrose Date: 2004-06-21 00:16:54 -0700 (Mon, 21 Jun 2004) New Revision: 1060 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Trace.h Log: Minor fixups to Trace.h (needs more work, and really needs a win32 implementation). Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1060 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-21 07:11:10 UTC (rev 1059) +++ trunk/CSP/SimData/CHANGES.current 2004-06-21 07:16:54 UTC (rev 1060) @@ -25,6 +25,9 @@ * Updated docs in TaggedRecord.h. Added a global registry for tagged records. + * Minor fixups to Trace.h (needs more work, and really needs a + win32 implementation). + 2004-06-16: onsight * Doxygen cleanups. Modified: trunk/CSP/SimData/Include/SimData/Trace.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Trace.h 2004-06-21 07:11:10 UTC (rev 1059) +++ trunk/CSP/SimData/Include/SimData/Trace.h 2004-06-21 07:16:54 UTC (rev 1060) @@ -1,18 +1,18 @@ /* SimData: Data Infrastructure for Simulations - * Copyright (C) 2003 Mark Rose <tm...@st...> - * + * Copyright 2003, 2004 Mark Rose <mk...@us...> + * * This file is part of SimData. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -22,6 +22,11 @@ /** * @file Trace.h * @brief Automatic callstack traces reporting on error. + * + * TODO does not show the offending address (need siginfo_t). + * TODO difficult to decode addresses for libraries with lazy loading. + * TODO what's the point of TraceBase? + * TODO need a windows implementation */ @@ -35,27 +40,41 @@ #ifdef __GNUC__ # include <csignal> # include <execinfo.h> -# include <exception> +# include <exception> # include <cstdlib> +# include <dlfcn.h> #endif // __GNUC__ NAMESPACE_SIMDATA + +/** Base class for implementing signal handlers and stack trace dumps. + */ class TraceBase { +private: typedef void (*Callback)(); + Callback _precallback, _postcallback; logstream *_log; bool _traced; - Callback _precallback, _postcallback; + void *_reference; + protected: - TraceBase(): _precallback(0), _postcallback(0), _log(0), _traced(false) { } + TraceBase(): _precallback(0), _postcallback(0), _log(0), _traced(false), _reference(0) { } + void setCallbacks_impl(Callback precallback, Callback postcallback) { _precallback = precallback; _postcallback = postcallback; } + + void setReference(void *ref) { + _reference = ref; + } + void setLog_impl(logstream &log) { _log = &log; } + std::ostream &log() { if (_log) { return (*_log) << loglevel(LOG_ALL, LOG_ERROR); @@ -63,29 +82,34 @@ return simdata::log() << loglevel(LOG_ALL, LOG_ERROR); } } + void _preCallback() { if (_precallback != 0) _precallback(); } + void _postCallback() { if (_postcallback != 0) _postcallback(); } + void error(int skip, bool segv=false) { if (_traced) return; _traced = true; if (segv) { log() << "FATAL ERROR: segmentation fault." << std::endl; + if (_reference) { + log() << "reference = " << _reference << std::endl; + } } _preCallback(); _backtrace(skip, segv); _postCallback(); } + virtual void _backtrace(int skip, bool segv) {} }; - /** Singleton callstack trace error handler. - * */ class Trace: public TraceBase { @@ -128,17 +152,17 @@ } Trace(): TraceBase() {} - ~Trace() {} + virtual ~Trace() {} public: - /** Install a new backtrace error handler. * * @returns true if succesful. */ - static bool install() { + static bool install(void *reference) { #ifdef __GNUC__ + getTrace().setReference(reference); signal(SIGABRT, __sigabort); signal(SIGSEGV, __sigsegv); return true; |
From: <sv...@ww...> - 2004-06-21 07:11:16
|
Author: mkrose Date: 2004-06-21 00:11:10 -0700 (Mon, 21 Jun 2004) New Revision: 1059 Added: trunk/CSP/SimData/Include/SimData/TaggedRecordRegistry.h Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/TaggedRecord.h Log: Updated docs in TaggedRecord.h. Added a global registry for tagged records. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1059 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-21 07:02:44 UTC (rev 1058) +++ trunk/CSP/SimData/CHANGES.current 2004-06-21 07:11:10 UTC (rev 1059) @@ -22,6 +22,9 @@ generate the record class id. The single 64-bit id was being truncated when used to construct the simdata::hasht identifier. + * Updated docs in TaggedRecord.h. Added a global registry for + tagged records. + 2004-06-16: onsight * Doxygen cleanups. Modified: trunk/CSP/SimData/Include/SimData/TaggedRecord.h =================================================================== --- trunk/CSP/SimData/Include/SimData/TaggedRecord.h 2004-06-21 07:02:44 UTC (rev 1058) +++ trunk/CSP/SimData/Include/SimData/TaggedRecord.h 2004-06-21 07:11:10 UTC (rev 1059) @@ -24,7 +24,22 @@ * @brief Base classes for tagged records. */ +// TODO ============================================================= +// pack tags; group them at the start of the record: +// bit 7: packed (1) or offset (0) +// packed: +// bits 0-6 indicate which of the next 7 tags are present (1) or +// absent (0) +// offset: +// bits 0-6 are the offset to the next tag, relative to the last +// known tag. (1-127) +// special cases: +// 0: reserved +// 101-126: reserved +// 127: offset is greater than 100, is contained in the next +// two bytes + #ifndef __SIMDATA_TAGGED_RECORD_H__ #define __SIMDATA_TAGGED_RECORD_H__ @@ -47,8 +62,7 @@ typedef hasht int64; -/** - * Simple Writer class for serializing to a string buffer. +/** Simple Writer class for serializing to a string buffer. */ class StringWriter: public Writer { std::string _buffer; @@ -118,12 +132,11 @@ } }; -/** - * Simple Reader class for serializing from a string buffer. +/** Simple Reader class for serializing from a string buffer. */ class StringReader: public Reader { const unsigned char *_data; - int _bytes; + unsigned int _bytes; public: StringReader(std::string const &buffer) : _data(reinterpret_cast<const unsigned char *>(buffer.data())), @@ -199,7 +212,7 @@ return *this; } virtual Reader & operator>>(char * &x) { - assert(0); + assert(0); // avoid allocation issues for now -- no char*'s return *this; } virtual Reader & operator>>(BaseType &x) { @@ -207,7 +220,7 @@ return *this; } virtual Reader & operator>>(std::string &x) { - int length = readLength(); + unsigned int length = readLength(); assert(_bytes >= length); x.clear(); x.append(reinterpret_cast<const char*>(_data), length); @@ -218,9 +231,8 @@ }; -/** - * Base class for TagWriter and TagReader which manages a stack - * of nested records. +/** Base class for TagWriter and TagReader which manages a stack + * of nested records. */ class TagBase { protected: @@ -232,8 +244,7 @@ }; -/** - * Class for writing tagged records to wire format. +/** Class for writing tagged records to wire format. */ class TagWriter: public TagBase { public: @@ -270,8 +281,7 @@ }; -/** - * Class for reading tagged records from wire format. +/** Class for reading tagged records from wire format. */ class TagReader: public TagBase { public: @@ -311,10 +321,9 @@ }; -/** - * Base class for auto-generated record classes that can be serialized - * to a tagged binary format. Subclasses are generated by compiling - * record definitions with the TaggedRecordCompiler. +/** Base class for auto-generated record classes that can be serialized + * to a tagged binary format. Subclasses are generated by compiling + * record definitions with the TaggedRecordCompiler. */ class TaggedRecord: public Referenced { public: @@ -337,8 +346,7 @@ } -/** - * Small helper class for indenting TaggedRecord dumps. +/** Small helper class for indenting TaggedRecord dumps. */ class Indent { public: @@ -348,8 +356,8 @@ Indent & operator--() { --level; return *this; } }; -std::ostream & operator << (std::ostream &os, Indent const &indent) { - for (int i = 0; i < indent.level; ++i) os << " "; +inline std::ostream & operator << (std::ostream &os, Indent const &indent) { + for (int i = 0; i < indent.level; ++i) os << " "; return os; } Added: trunk/CSP/SimData/Include/SimData/TaggedRecordRegistry.h =================================================================== --- trunk/CSP/SimData/Include/SimData/TaggedRecordRegistry.h 2004-06-21 07:02:44 UTC (rev 1058) +++ trunk/CSP/SimData/Include/SimData/TaggedRecordRegistry.h 2004-06-21 07:11:10 UTC (rev 1059) @@ -0,0 +1,175 @@ +/* SimData: Data Infrastructure for Simulations + * Copyright (C) 2004 Mark Rose <mk...@us...> + * + * This file is part of SimData. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +/** + * @file TaggedRecordRegistry.h + * @brief Classes for storing and accessing tagged record factories. + */ + + +#ifndef __SIMDATA_TAGGEDRECORDREGISTRY_H__ +#define __SIMDATA_TAGGEDRECORDREGISTRY_H__ + +#include <string> +#include <vector> +#include <map> + +#include <SimData/Export.h> +#include <SimData/HashUtility.h> +#include <SimData/TaggedRecord.h> +#include <SimData/Singleton.h> +#include <SimData/Namespace.h> +#include <SimData/ExceptionBase.h> + + +NAMESPACE_SIMDATA + + +/** Abstract interface for TaggedRecord factories. + * + * Automatically registers with the TaggedRecordRegistry when instantiated. + */ +class SIMDATA_EXPORT TaggedRecordFactoryBase { +public: + TaggedRecordFactoryBase() { } + virtual Ref<TaggedRecord> create() const=0; + virtual std::string getName() const=0; + virtual int getVersion() const=0; + virtual int64 getId() const=0; + virtual ~TaggedRecordFactoryBase() { } +}; + + +/** Singleton class to store and access all TaggedRecords in the application. + * + * TaggedRecord classes automatically register themselves with the global instance + * of this class at startup. + * + * @author Mark Rose <mr...@st...> + */ +class SIMDATA_EXPORT TaggedRecordRegistry: public Singleton<TaggedRecordRegistry> { + +friend class Singleton<TaggedRecordRegistry>; + +template <class RECORD> friend class TaggedRecordFactory; + +public: + typedef std::vector<TaggedRecordFactoryBase *> FactoryList; + + /** Get an object interface by object class name. + * + * @returns 0 if the interface is not found. + */ + Ref<TaggedRecord> createRecord(std::string const &name) const { + FactoryMap::const_iterator it = _map.find(name); + if (it != _map.end()) return it->second->create(); + return 0; + } + + /** Get an object interface by object class hash. + * + * @returns 0 if the interface is not found. + */ + Ref<TaggedRecord> createRecord(hasht key) const { + FactoryIdMap::const_iterator it = _id_map.find(key); + if (it != _id_map.end()) return it->second->create(); + return 0; + } + + /** Test if an object interface is registered. + * + * @param name The object class name. + */ + bool hasFactory(std::string const &name) const { + FactoryMap::const_iterator it = _map.find(name); + return it != _map.end(); + } + + /** Test if an object interface is registered. + * + * @param key The object class hash. + */ + bool hasFactory(hasht key) const { + FactoryIdMap::const_iterator it = _id_map.find(key); + return it != _id_map.end(); + } + + /** Get a list of all interfaces in the registry. + */ + std::vector<TaggedRecordFactoryBase *> getFactories() const { + std::vector<TaggedRecordFactoryBase *> list; + FactoryIdMap::const_iterator it = _id_map.begin(); + for (; it != _id_map.end(); ++it) { + list.push_back(it->second); + } + return list; + } + + /** Get the interface registry singleton. + */ + static TaggedRecordRegistry &getTaggedRecordRegistry() { + return getInstance(); + } + +private: + + ~TaggedRecordRegistry() { } + + /** Register a factory with the registry. + */ + void registerFactory(TaggedRecordFactoryBase *factory) { + assert(factory != 0); + assert(!hasFactory(factory->getName())); + SIMDATA_LOG(LOG_ALL, LOG_INFO, "Registering TaggedRecordFactory<" << factory->getName() << "> [" << factory->getId() << "]"); + _map[factory->getName()] = factory; + _id_map[factory->getId()] = factory; + } + + TaggedRecordRegistry() { } + + typedef HASH_MAPS<std::string, TaggedRecordFactoryBase*, hashstring, eqstring>::Type FactoryMap; + typedef HASHT_MAP<TaggedRecordFactoryBase*>::Type FactoryIdMap; + + FactoryMap _map; + FactoryIdMap _id_map; + +}; + + +/** Factory template for creating TaggedRecord subclasses. + */ +template <class RECORD> +class SIMDATA_EXPORT TaggedRecordFactory: public TaggedRecordFactoryBase { +public: + TaggedRecordFactory(): TaggedRecordFactoryBase() { + TaggedRecordRegistry ®istry = TaggedRecordRegistry::getInstance(); + registry.registerFactory(this); + } + virtual Ref<TaggedRecord> create() const { return new RECORD(); } + virtual std::string getName() const { return RECORD::_getName(); } + virtual int getVersion() const { return RECORD::_getVersion(); } + virtual int64 getId() const { return RECORD::_getId(); }; +}; + + +NAMESPACE_SIMDATA_END + +#endif // __SIMDATA_TAGGEDRECORDREGISTRY_H__ |
From: <sv...@ww...> - 2004-06-21 07:02:50
|
Author: mkrose Date: 2004-06-21 00:02:44 -0700 (Mon, 21 Jun 2004) New Revision: 1058 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Tools/TaggedRecordCompiler/BaseTypes.py Log: Modify tagged record compiler to use two 32-bit hash ids to generate the record class id. The single 64-bit id was being truncated when used to construct the simdata::hasht identifier. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1058 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-21 06:58:58 UTC (rev 1057) +++ trunk/CSP/SimData/CHANGES.current 2004-06-21 07:02:44 UTC (rev 1058) @@ -18,6 +18,10 @@ as pthreads-win32 (http://sources.redhat.com/pthreads-win32/) to use these classes. + * Modify tagged record compiler to use two 32-bit hash ids to + generate the record class id. The single 64-bit id was being + truncated when used to construct the simdata::hasht identifier. + 2004-06-16: onsight * Doxygen cleanups. Modified: trunk/CSP/SimData/Tools/TaggedRecordCompiler/BaseTypes.py =================================================================== --- trunk/CSP/SimData/Tools/TaggedRecordCompiler/BaseTypes.py 2004-06-21 06:58:58 UTC (rev 1057) +++ trunk/CSP/SimData/Tools/TaggedRecordCompiler/BaseTypes.py 2004-06-21 07:02:44 UTC (rev 1058) @@ -26,11 +26,16 @@ import CodeFormat import md5 -def md5hash(s): +def md5hash64(s): """return a 64-bit (python long) hash of a string""" return long(md5.md5(s).hexdigest()[:16], 16) +def md5hash32(s): + """return a pair of 32-bit hashs of a string""" + digest = md5.md5(s).hexdigest() + return int(digest[:8], 16), int(digest[8:16], 16) + class Declaration: DEFAULT = 0 COMPOUND = 0 @@ -224,7 +229,7 @@ format.write('void dump(std::ostream &os, int level=0) const {') format.indent() format.write('simdata::Indent indent(level);') - format.write('os << indent << "%s <\\n";' % self.id) + format.write('os << "%s {\\n";' % self.id) format.write('++indent;') for element in self.elements: format.write('if (m_has_%s) {' % element.id) @@ -235,7 +240,7 @@ format.dedent() format.write('}') format.write('--indent;') - format.write('os << indent << ">";') + format.write('os << indent << "}";') format.dedent() format.write('}') @@ -422,8 +427,8 @@ except ValueError: print >>sys.stderr, 'ERROR: VERSION option on %s must be an integer' % name sys.exit(1) - id = md5hash('%s_%d' % (name, version)) - d = {'name': name, 'version': version, 'id': id} + id0, id1 = md5hash32('%s_%d' % (name, version)) + d = {'name': name, 'version': version, 'id0': id0, 'id1': id1} format.template(Message.TRF_GETID, d) format.template(Message.TRF_GETVERSION, d) format.template(Message.TRF_GETNAME, d) @@ -438,7 +443,7 @@ TRF_GETID = ''' virtual Id getId() const { return _getId(); } - static inline Id _getId() { return %(id)dll; } + static inline Id _getId() { return Id(%(id0)du, %(id1)du); } ''' TRF_GETVERSION = ''' |
From: <sv...@ww...> - 2004-06-21 06:59:05
|
Author: mkrose Date: 2004-06-20 23:58:58 -0700 (Sun, 20 Jun 2004) New Revision: 1057 Modified: trunk/CSP/CSPSim/CHANGES.current trunk/CSP/CSPSim/Include/CSPSim.h trunk/CSP/CSPSim/Include/DynamicObject.h Log: Changed some print statements to use logging instead. Added a mainpage comment for the doxygen docs. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1057 Modified: trunk/CSP/CSPSim/CHANGES.current =================================================================== --- trunk/CSP/CSPSim/CHANGES.current 2004-06-21 06:56:34 UTC (rev 1056) +++ trunk/CSP/CSPSim/CHANGES.current 2004-06-21 06:58:58 UTC (rev 1057) @@ -5,6 +5,10 @@ * Changed doxygen control file to recurse into the variou subdirectories (Systems, Theater, etc). + * Changed some print statements to use logging instead. + + * Added a mainpage comment for the doxygen docs. + 2004-06-14: onsight * Added doxygen directory, control file, and make targets. Modified: trunk/CSP/CSPSim/Include/CSPSim.h =================================================================== --- trunk/CSP/CSPSim/Include/CSPSim.h 2004-06-21 06:56:34 UTC (rev 1056) +++ trunk/CSP/CSPSim/Include/CSPSim.h 2004-06-21 06:58:58 UTC (rev 1057) @@ -24,6 +24,26 @@ * */ +/** + * @mainpage CSPSim - Combat Simulator Project + * + * @section overview Overview + * + * The Combat Simulator Project is an open-source community united by a + * common interest in combat simulator development. We are developing + * standards, technologies, code libraries, tools and artwork that can be + * used to build a wide variety of real-time combat simulators. Our + * ultimate goal is to realize concurrent and networked cross-platform + * simulation of large-scale multi-vehicle combat scenarios. + * + * CSPSim is a simulator testbed used to develop the infrastructure of + * CSP. It is currently a functional flight simulator, using OpenGL + * rendering under both Microsoft Windows and GNU/Linux environments. + * For more details about current development efforts, please visit + * the <a href='csp.sourceforge.net/forum'>CSP Forums</a>. + * + */ + #ifndef __CSPSIM_H__ #define __CSPSIM_H__ Modified: trunk/CSP/CSPSim/Include/DynamicObject.h =================================================================== --- trunk/CSP/CSPSim/Include/DynamicObject.h 2004-06-21 06:56:34 UTC (rev 1056) +++ trunk/CSP/CSPSim/Include/DynamicObject.h 2004-06-21 06:58:58 UTC (rev 1057) @@ -151,10 +151,12 @@ void updateGroundPosition(); void updateOrientation(); - virtual void aggregate() { std::cout << "aggregate " << int(this) << std::endl; } - virtual void deaggregate() { std::cout << "deaggregate " << int(this) << std::endl; } - virtual void setVisible(bool visible) { std::cout << int(this) << ": visible = " << visible << std::endl; } - + virtual void aggregate() { CSP_LOG(APP, INFO, "aggregate @ " << int(this)); } + virtual void deaggregate() { CSP_LOG(APP, INFO, "deaggregate @ " << int(this)); } + virtual void setVisible(bool visible) { + CSP_LOG(APP, INFO, "object @ " << int(this) << ": visible = " << visible); + } + bool isNearGround(); // The object name holds an identifier string for in-game display. It is not |
From: <sv...@ww...> - 2004-06-21 06:56:40
|
Author: mkrose Date: 2004-06-20 23:56:34 -0700 (Sun, 20 Jun 2004) New Revision: 1056 Modified: trunk/CSP/CSPSim/CHANGES.current trunk/CSP/CSPSim/Doc/Doxyfile Log: Changed doxygen control file to recurse into the variou subdirectories (Systems, Theater, etc). Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1056 Modified: trunk/CSP/CSPSim/CHANGES.current =================================================================== --- trunk/CSP/CSPSim/CHANGES.current 2004-06-21 06:54:28 UTC (rev 1055) +++ trunk/CSP/CSPSim/CHANGES.current 2004-06-21 06:56:34 UTC (rev 1056) @@ -1,6 +1,10 @@ Version 0.4.0 (in progress) =========================== +2004-06-20: onsight + * Changed doxygen control file to recurse into the variou subdirectories + (Systems, Theater, etc). + 2004-06-14: onsight * Added doxygen directory, control file, and make targets. Modified: trunk/CSP/CSPSim/Doc/Doxyfile =================================================================== --- trunk/CSP/CSPSim/Doc/Doxyfile 2004-06-21 06:54:28 UTC (rev 1055) +++ trunk/CSP/CSPSim/Doc/Doxyfile 2004-06-21 06:56:34 UTC (rev 1056) @@ -323,7 +323,7 @@ # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. -RECURSIVE = NO +RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a |
From: <sv...@ww...> - 2004-06-21 06:54:36
|
Author: mkrose Date: 2004-06-20 23:54:28 -0700 (Sun, 20 Jun 2004) New Revision: 1055 Added: trunk/CSP/SimData/Include/SimData/AtomicCounter.h trunk/CSP/SimData/Include/SimData/Thread.h trunk/CSP/SimData/Include/SimData/ThreadBase.h trunk/CSP/SimData/Include/SimData/ThreadQueue.h Modified: trunk/CSP/SimData/CHANGES.current Log: Added several classes for posix threading support. These are all headers so they should not affect the build. Under win32 you'll need a posix threads implementation, such as pthreads-win32 (http://sources.redhat.com/pthreads-win32/) to use these classes. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1055 Diff omitted (35515 bytes). |
From: <sv...@ww...> - 2004-06-21 06:49:22
|
Author: mkrose Date: 2004-06-20 23:49:13 -0700 (Sun, 20 Jun 2004) New Revision: 1054 Added: trunk/CSP/SimData/Include/SimData/Timing.h trunk/CSP/SimData/Source/Timing.cpp Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Date.h trunk/CSP/SimData/Source/Date.cpp trunk/CSP/SimData/Source/Makefile Log: Moved fast-timing code out of Date.h/cpp into Timing.h/cpp. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1054 Diff omitted (23826 bytes). |
From: <sv...@ww...> - 2004-06-21 06:41:49
|
Author: mkrose Date: 2004-06-20 23:41:43 -0700 (Sun, 20 Jun 2004) New Revision: 1053 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Ref.h Log: Refactored Referenced class to take a counter type as a template parameter; in anticipation of adding thread-safe reference counting. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1053 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-21 06:38:27 UTC (rev 1052) +++ trunk/CSP/SimData/CHANGES.current 2004-06-21 06:41:43 UTC (rev 1053) @@ -4,6 +4,10 @@ 2004-06-20: onsight * Doxygen and copyright notice updates. + * Refactored Referenced class to a templated base class, allowing + different counter types to be used in anticipation of adding + thread-safe reference counting. + 2004-06-16: onsight * Doxygen cleanups. Modified: trunk/CSP/SimData/Include/SimData/Ref.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Ref.h 2004-06-21 06:38:27 UTC (rev 1052) +++ trunk/CSP/SimData/Include/SimData/Ref.h 2004-06-21 06:41:43 UTC (rev 1053) @@ -47,7 +47,6 @@ NAMESPACE_SIMDATA -class Referenced; class ReferencePointer; class LinkBase; @@ -61,20 +60,21 @@ * * @author Mark Rose <mr...@st...> */ -class SIMDATA_EXPORT Referenced: public NonCopyable { +template <typename COUNTER> +class SIMDATA_EXPORT ReferencedBase: public NonCopyable { template <class T> friend class Ref; friend class ReferencePointer; protected: - Referenced(): __count(0) { - //SIMDATA_LOG(LOG_ALL, LOG_ERROR, "Referenced(" << this << ")"); + ReferencedBase(): __count(0) { + //SIMDATA_LOG(LOG_ALL, LOG_ERROR, "ReferencedBase(" << this << ")"); } - virtual ~Referenced() { - //SIMDATA_LOG(LOG_ALL, LOG_ERROR, "~Referenced(" << this << ", " << __count << ")"); + virtual ~ReferencedBase() { + //SIMDATA_LOG(LOG_ALL, LOG_ERROR, "~ReferencedBase(" << this << ", " << __count << ")"); if (__count != 0) { - SIMDATA_LOG(LOG_ALL, LOG_ERROR, "simdata::Referenced(" << std::hex << int(this) << ") deleted with non-zero reference count (" << __count << "): memory corruption possible."); + SIMDATA_LOG(LOG_ALL, LOG_ERROR, "simdata::ReferencedBase(" << std::hex << int(this) << ") deleted with non-zero reference count (" << __count << "): memory corruption possible."); } } @@ -86,13 +86,20 @@ inline void _decref() const { //SIMDATA_LOG(LOG_ALL, LOG_ERROR, "_decref(" << this << ", " << __count << ")"); assert(__count > 0); - if (0 == --__count) delete this; + if (!--__count) delete this; } - inline unsigned _count() const { return __count; } - mutable unsigned __count; + inline int _count() const { return static_cast<int>(__count); } + mutable COUNTER __count; }; +/** Base class for referenced counted objects that are used within a single + * thread. <b>Not thread-safe</b>, use ThreadSafeReferenced for references + * that are shared between threads. + */ +typedef ReferencedBase<int> Referenced; + + /** Reference counting smart-pointer. * * Reference counting smart-pointer for use with simdata::Referenced @@ -104,7 +111,7 @@ * @author Mark Rose <mr...@st...> */ template<class CLASS> -class Ref: protected HasBase<CLASS, Referenced> { +class Ref { public: typedef std::vector< Ref<CLASS> > vector; typedef std::list< Ref<CLASS> > list; @@ -117,24 +124,24 @@ /** Create a null reference. */ - Ref(): HasBase<CLASS, Referenced>(), _reference(0) { } + Ref(): _reference(0) { } /** Create a new reference. */ - Ref(CLASS* ptr): HasBase<CLASS, Referenced>(), _reference(ptr) { + Ref(CLASS* ptr): _reference(ptr) { if (_reference) _reference->_incref(); } /** Light-weight copy with reference counting. */ - Ref(LinkBase const & r): HasBase<CLASS, Referenced>(), _reference(0) { + Ref(LinkBase const & r): _reference(0) { _rebind(r._get()); } /** Light-weight copy with reference counting. */ template <typename Q> - Ref(Ref<Q> const & r): HasBase<CLASS, Referenced>(), _reference(0) { + Ref(Ref<Q> const & r): _reference(0) { Q *rp = r.get(); if (rp != 0) { //rp->_incref(); @@ -145,14 +152,14 @@ /** Light-weight copy with reference counting. */ - Ref(Ref const & r): HasBase<CLASS, Referenced>(), _reference(r._reference) { + Ref(Ref const & r): _reference(r._reference) { if (_reference) _reference->_incref(); } /** Decrement the reference count, and potentially destroy * the referenced object. */ - ~Ref() { + ~Ref() { _unbind(); } @@ -263,8 +270,10 @@ } /** Comparison with other simdata pointers. + * XXX the base class NonCopyable is used here instead of CLASS since + * swig generates bad code if CLASS is const (const const). */ - inline bool operator==(Referenced const * p) const { + inline bool operator==(NonCopyable const * p) const { return _reference == p; } @@ -276,8 +285,10 @@ } /** Comparison with other simdata pointers. + * XXX the base class NonCopyable is used here instead of CLASS since + * swig generates bad code if CLASS is const (const const). */ - inline bool operator!=(Referenced const * p) const { + inline bool operator!=(NonCopyable const * p) const { return _reference != p; } |
From: <sv...@ww...> - 2004-06-21 06:38:34
|
Author: mkrose Date: 2004-06-20 23:38:27 -0700 (Sun, 20 Jun 2004) New Revision: 1052 Modified: trunk/CSP/SimData/CHANGES.current trunk/CSP/SimData/Include/SimData/Archive.h trunk/CSP/SimData/Include/SimData/PTS.h Log: Minor doc and copyright notice fixes. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1052 Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-17 06:36:15 UTC (rev 1051) +++ trunk/CSP/SimData/CHANGES.current 2004-06-21 06:38:27 UTC (rev 1052) @@ -1,6 +1,9 @@ Version 0.4.0 (in progress) =========================== +2004-06-20: onsight + * Doxygen and copyright notice updates. + 2004-06-16: onsight * Doxygen cleanups. Modified: trunk/CSP/SimData/Include/SimData/Archive.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Archive.h 2004-06-17 06:36:15 UTC (rev 1051) +++ trunk/CSP/SimData/Include/SimData/Archive.h 2004-06-21 06:38:27 UTC (rev 1052) @@ -1,5 +1,5 @@ /* SimData: Data Infrastructure for Simulations - * Copyright (C) 2002 Mark Rose <tm...@st...> + * Copyright 2002, 2003, 2004 Mark Rose <mk...@us...> * * This file is part of SimData. * @@ -50,29 +50,50 @@ SIMDATA_EXCEPTION(SerializeError); +/** A trivial FILE * wrapper to provide a uniform file interface for both + * C++ and Python. + */ class SIMDATA_EXPORT PackFile { FILE *_f; bool _open; public: + #ifndef SWIG + /** Retrieve the underlying FILE pointer. + */ operator FILE*() { return _f; } - PackFile(FILE* f): _f(f), _open(false) {} + + /** Wrap an existing (open) FILE pointer. + */ + PackFile(FILE* f): _f(f), _open(false) { + _open = (_f != 0); + } #endif + + /** Open a new file (fopen interface) + */ PackFile(const char *fn, const char *mode) { _f = (FILE*) fopen(fn, mode); assert(_f); // XXX add error handling _open = (_f != 0); } + + /** Close the current file, if open. + */ void close() { if (_open) { - fclose(_f); + if (_f) fclose(_f); + _f = 0; _open = false; } } }; - +/** + * Abstract base class for serializing standard types and BaseTypes + * from a data source. + */ class SIMDATA_EXPORT Reader { public: virtual ~Reader() {} @@ -214,7 +235,8 @@ /** - * + * Abstract base class for serializing standard types and BaseTypes + * to a data source. */ class SIMDATA_EXPORT Writer { public: @@ -273,7 +295,7 @@ * and provides methods to write variables of various types to * the file in a standard format. * - * @author Mark Rose <tm...@st...> + * @author Mark Rose <mk...@us...> */ class SIMDATA_EXPORT ArchiveWriter: public Writer { FILE *_f; @@ -355,7 +377,7 @@ * needed to reconstruct the object, and provides access methods * for translating the raw bytes into variables of various types. * - * @author Mark Rose <tm...@st...> + * @author Mark Rose <mk...@us...> */ class SIMDATA_EXPORT ArchiveReader: public Reader { const char* _d; @@ -467,12 +489,15 @@ }; +/** Writer class for serializing data to a memory buffer. + * + * This class currently uses a fixed size memory buffer, that + * must be preallocated with sufficient space to store all + * data that is serialized. + */ class SIMDATA_EXPORT MemoryWriter: public Writer { uint8 * _ptr; int _n; - //void write(const void* x, int n) { - // fwrite(x, n, 1, _f); - //} public: MemoryWriter(uint8 * ptr): Writer(), _n(0) { _ptr = ptr; @@ -549,12 +574,14 @@ }; +/** Reader class for serializing data from a memory buffer. + * + * The current implementation does not check for serialization + * underflows or overflows. + */ class SIMDATA_EXPORT MemoryReader: public Reader { uint8 * _ptr; int _n; - //void write(const void* x, int n) { - // fwrite(x, n, 1, _f); - //} public: MemoryReader(uint8 * ptr): Reader(), _n(0) { _ptr = ptr; Modified: trunk/CSP/SimData/Include/SimData/PTS.h =================================================================== --- trunk/CSP/SimData/Include/SimData/PTS.h 2004-06-17 06:36:15 UTC (rev 1051) +++ trunk/CSP/SimData/Include/SimData/PTS.h 2004-06-21 06:38:27 UTC (rev 1052) @@ -1,18 +1,18 @@ /* SimData: Data Infrastructure for Simulations - * Copyright (C) 2002 Mark Rose <tm...@st...> - * + * Copyright (C) 2002 Mark Rose <mk...@us...> + * * This file is part of SimData. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
From: <sv...@ww...> - 2004-06-17 06:36:24
|
Author: mkrose Date: 2004-06-16 23:36:15 -0700 (Wed, 16 Jun 2004) New Revision: 1051 Added: trunk/CSP/SimData/Include/SimData/ScopedPointer.h Modified: trunk/CSP/SimData/Source/SConscript trunk/CSP/SimData/setup.py Log: Add a scoped pointer class. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1051 Added: trunk/CSP/SimData/Include/SimData/ScopedPointer.h =================================================================== --- trunk/CSP/SimData/Include/SimData/ScopedPointer.h 2004-06-17 06:31:57 UTC (rev 1050) +++ trunk/CSP/SimData/Include/SimData/ScopedPointer.h 2004-06-17 06:36:15 UTC (rev 1051) @@ -0,0 +1,99 @@ +/* SimData: Data Infrastructure for Simulations + * Copyright (C) 2004 Mark Rose <mk...@us...> + * + * This file is part of SimData. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +/** + * @file ScopedPointer.h + * @brief A pointer wrapper with scope-based auto deletion. + */ + + +#ifndef __SIMDATA_SCOPEDPOINTER_H__ +#define __SIMDATA_SCOPEDPOINTER_H__ + +#include <SimData/Namespace.h> +#include <SimData/Properties.h> + + +NAMESPACE_SIMDATA + + +/** A smart pointer class that automatically deletes the + * referenced object when leaving scope. + * + * This class is similar to std::auto_ptr, but does not + * allow ownership to be transferred. The interface + * was borrowed from Boost C++. + */ +template <class T> +class ScopedPointer: public NonCopyable { + T *_ptr; +public: + typedef T Type; + + /** Construct a new scoped pointer. + * + * The assigned pointer, if non-null, will be automatically + * deleted when this instance goes out of scope. + */ + explicit ScopedPointer(T * p = 0): _ptr(p) { } + + inline ~ScopedPointer() { if (_ptr) reset(); } + + /** Reassign this instance to a new pointer. + * + * If the current pointer is non-null it will be deleted. + */ + void reset(T * p = 0) { + assert(_ptr == 0 || _ptr != p); + if (_ptr) delete _ptr; + _ptr = p; + } + + /** Obtain a non-const referenc to the underlying object. + * + * Will abort if the pointer is null. + */ + inline T & operator*() const { assert(ptr); return *_ptr; } + + /** Dereference the pointer. + * + * Will abort if the pointer is null. + */ + inline T * operator->() const { assert(ptr); return _ptr; } + + /** Get the raw pointer. + */ + inline T * get() const { return _ptr; } + + /** Return true if the pointer is null. + */ + inline bool isNull() const { return 0 == _ptr; } + + /** Return true if the pointer is not null. + */ + inline bool valid() const { return 0 != _ptr; } + +}; + +NAMESPACE_SIMDATA_END + +#endif // __SIMDATA_SCOPEDPOINTER_H__ + Modified: trunk/CSP/SimData/Source/SConscript =================================================================== --- trunk/CSP/SimData/Source/SConscript 2004-06-17 06:31:57 UTC (rev 1050) +++ trunk/CSP/SimData/Source/SConscript 2004-06-17 06:36:15 UTC (rev 1051) @@ -66,6 +66,7 @@ Random.h Real.h Ref.h + ScopedPointer.h Singleton.h String.h Trace.h Modified: trunk/CSP/SimData/setup.py =================================================================== --- trunk/CSP/SimData/setup.py 2004-06-17 06:31:57 UTC (rev 1050) +++ trunk/CSP/SimData/setup.py 2004-06-17 06:36:15 UTC (rev 1051) @@ -318,6 +318,7 @@ "Random.h", "Real.h", "Ref.h", + "ScopedPointer.h", "Singleton.h", "String.h", "Trace.h", |