/* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * . * */ static const char* const Sptr_cxx_Version = "$Id: Sptr.cxx,v 1.12 2002/06/25 17:01:24 bko Exp $"; #include "global.h" #include "Sptr.hxx" #ifdef __linux__ #include #endif #include #define SPTR_TRACEBACK_RUNNING 0 /// this C file is only used for debugging, so it is totally ifdef'ed #define SPTR_DEBUG_ACTIVE 0 #if SPTR_DEBUG // static item SptrDebugger* SptrDebugger::impl_ = 0; SptrDebugger::SptrDebugger() : ptrsInUse(), mutex() {} SptrDebugger* SptrDebugger::getInstance() { if (!impl_) { impl_ = new SptrDebugger; } assert(impl_); return impl_; } void SptrDebugger::newPtr(void* ptr) { #if SPTR_DEBUG_ACTIVE if (ptr == 0) { // do nothing for the null ptr. return ; } PtrMap::iterator i; getInstance()->mutex.lock(); i = getInstance()->ptrsInUse.find(ptr); if (i != getInstance()->ptrsInUse.end()) { // check to see if it's set to inUse if (i->second) { cerr << "pointer " << ptr << " already in a different Sptr" << endl; assert(0); } } getInstance()->ptrsInUse[ptr] = true; getInstance()->mutex.unlock(); #endif } void SptrDebugger::deletePtr(void* ptr) { #if SPTR_DEBUG_ACTIVE PtrMap::iterator i; getInstance()->mutex.lock(); i = getInstance()->ptrsInUse.find(ptr); if (i == getInstance()->ptrsInUse.end()) { cerr << "pointer " << ptr << " is not in any Sptr" << endl; assert(0); } else { if (i->second == false) { cerr << "pointer " << ptr << " was already deleted by another Sptr" << endl; assert(0); } else { getInstance()->ptrsInUse[ptr] = false; } } getInstance()->mutex.unlock(); #endif } #endif #if SPTR_TRACEBACK #if SPTR_TRACEBACK_RUNNING #ifdef __linux__ class SptrTraceback { public: SptrTraceback(); SptrTraceback(const SptrTraceback& x); SptrTraceback(void* sptr); bool operator==(const SptrTraceback& x) const; SptrTraceback& operator=(const SptrTraceback& x); void dump(FILE* f); private: void* sptr; void *my_backtrace[50]; int backtrace_size; }; SptrTraceback::SptrTraceback() : sptr(0), backtrace_size(0) { } SptrTraceback::SptrTraceback(const SptrTraceback& x) : sptr(x.sptr), backtrace_size(x.backtrace_size) { for (int i = 0; i < backtrace_size; i++) { my_backtrace[i] = x.my_backtrace[i]; } } SptrTraceback::SptrTraceback(void* sptr) : sptr(sptr), backtrace_size(0) { backtrace_size = backtrace(my_backtrace, 50); } bool SptrTraceback::operator==(const SptrTraceback& x) const { return sptr == x.sptr; } SptrTraceback& SptrTraceback::operator=(const SptrTraceback& x) { sptr = x.sptr; backtrace_size = x.backtrace_size; for (int i = 0; i < backtrace_size; i++) { my_backtrace[i] = x.my_backtrace[i]; } return *this; } void SptrTraceback::dump(FILE* f) { fprintf(f, " %p:", sptr); for (int i = 0; i < backtrace_size; i++) { fprintf(f, " %p", my_backtrace[i]); } fprintf(f, "\n"); } struct ptr_less : public binary_function < void*, void*, bool > { bool operator()(void* const & x, void* const & y) const { return ((unsigned int) x) < ((unsigned int) y); } }; ////////////////////////////////////////////////////////////////////// class SptrTracebackPack { public: SptrTracebackPack(); SptrTracebackPack(const SptrTracebackPack& x); SptrTracebackPack(void* myPtr, void* sptr); void insert(void* sptr); void clear(void* sptr); void dump(FILE* f); private: void* ptr; map < void*, SptrTraceback, ptr_less > tracebacks; }; SptrTracebackPack::SptrTracebackPack(void* myPtr, void* sptr) : ptr(myPtr), tracebacks() { insert(sptr); } SptrTracebackPack::SptrTracebackPack() : ptr(0), tracebacks() { } SptrTracebackPack::SptrTracebackPack(const SptrTracebackPack& x) : ptr(x.ptr), tracebacks(x.tracebacks) { } void SptrTracebackPack::insert(void* sptr) { SptrTraceback t(sptr); tracebacks[sptr] = t; } void SptrTracebackPack::clear(void* sptr) { tracebacks.erase(tracebacks.find(sptr)); } void SptrTracebackPack::dump(FILE* f) { map < void*, SptrTraceback, ptr_less > ::iterator i = tracebacks.begin(); fprintf(f, "%p>\n", ptr); while (i != tracebacks.end()) { i->second.dump(f); ++i; } } typedef map < void*, SptrTracebackPack > TraceMap; static TraceMap tracemap; void sptrDebugMarkTraceback(void* sptr, void* ptr) { TraceMap::iterator i; if(ptr) { i = tracemap.find(ptr); if (i != tracemap.end()) { i->second.insert(sptr); } else { tracemap[ptr] = SptrTracebackPack(ptr, sptr); } } } void sptrDebugClearTraceback(void* sptr, void* ptr) { TraceMap::iterator i; if(ptr) { i = tracemap.find(ptr); if (i != tracemap.end()) { i->second.clear(sptr); } else { assert(0); } } } void sptrDebugDumpTraceback(char* filename) { // open file, and dump FILE* f; f = fopen(filename, "w"); if (!f) { return ; } TraceMap::iterator i = tracemap.begin(); while (i != tracemap.end()) { // dump the record i->second.dump(f); ++i; } fclose(f); } #else // no linux -- these functions do nothing void sptrDebugMarkTraceback(void* sptr, void* ptr) { } void sptrDebugClearTraceback(void* sptr, void* ptr) { } void sptrDebugDumpTraceback(char* filename) { } // #if __linux__ #endif // #if __linux__ // #if SPTR_TRACEBACK_RUNNING #else // #if SPTR_TRACEBACK_RUNNING void sptrDebugMarkTraceback(void* sptr, void* ptr) { } void sptrDebugClearTraceback(void* sptr, void* ptr) { } void sptrDebugDumpTraceback(char* filename) { } // #if SPTR_TRACEBACK_RUNNING #endif // #if SPTR_TRACEBACK_RUNNING // #if SPTR_TRACEBACK #endif // #if SPTR_TRACEBACK