📄 ref.cc
字号:
//// ref.cc --- implementation of the reference counting classes//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@limitpt.com>// Maintainer: LPS//// This file is part of the SC Toolkit.//// The SC Toolkit is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// The SC Toolkit 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 Library General Public License for more details.//// You should have received a copy of the GNU Library General Public License// along with the SC Toolkit; see the file COPYING.LIB. If not, write to// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.//// The U.S. Government is granted a limited license as per AL 91-7.//#ifdef __GNUC__#pragma implementation#endif#include <typeinfo>#include <util/ref/ref.h>#include <util/misc/exenv.h>using namespace std;#if REF_USE_LOCKS#if HAVE_STHREAD#include <synch.h>#include <thread.h>typedef mutex_t sc_lock_t;static unsigned int __base_nlock__;static int __base_locker__;static int__init_lock__(sc_lock_t* inLock, int inCount){ for (int i=0; i < inCount; i++) mutex_init(&inLock[i], USYNC_THREAD, 0); return 1;}#define __LOCK(l) mutex_lock(&l)#define __UNLOCK(l) mutex_unlock(&l)#elif HAVE_PTHREAD#include <pthread.h>typedef pthread_mutex_t sc_lock_t;static int__init_lock__(sc_lock_t* inLock, int inCount){ for (int i=0; i < inCount; i++) pthread_mutex_init(&inLock[i], 0); return 1;}#define __LOCK(l) pthread_mutex_lock(&l)#define __UNLOCK(l) pthread_mutex_unlock(&l)#elif HAVE_CREATETHREAD#include <windows.h>typedef HANDLE sc_lock_t;HANDLE __base_lock__ = 0;static int__init_lock__(sc_lock_t* inLock, int inCount){ for (int i=0; i < inCount; i++) inLock[i] = CreateMutex(0, FALSE, 0); return 1;}// windows threads are recursive, so no fanciness is required#define __LOCK(l) WaitForSingleObject(l, INFINITE)#define __UNLOCK(l) ReleaseMutex(l)#else /* !PTHREAD && !STHREAD && !CREATETHREAD */#define __LOCK(l) 0#define __UNLOCK(l) 0#endif /* HAVE_STHREAD *//* * this is the number of locks to use in the round-robin. * since an unsigned char is used for the lock handle, * this cannot be greater than 255. */#define NLOCKS 128static sc_lock_t sRefLocks[NLOCKS];static int sRefLocksInit = __init_lock__(sRefLocks, NLOCKS);static unsigned char sRefLock = 0;#else /* !REF_USE_LOCKS */#define __LOCK(l) 0#define __UNLOCK(l) 0#endif /* !REF_USE_LOCKS */using namespace sc;intRefCount::lock_ptr() const{#if REF_USE_LOCKS if (ref_lock_ == 0xff) return 1; return __LOCK(sRefLocks[ref_lock_]);#else return 1;#endif }intRefCount::unlock_ptr() const{#if REF_USE_LOCKS if (ref_lock_ == 0xff) return 1; return __UNLOCK(sRefLocks[ref_lock_]);#else return 1;#endif }voidRefCount::use_locks(bool inVal){#if REF_USE_LOCKS if (inVal) { ref_lock_ = sRefLock; unsigned char tmp_sRefLock = sRefLock+1; if (tmp_sRefLock >= NLOCKS) tmp_sRefLock = 0; sRefLock = tmp_sRefLock; } else ref_lock_ = 0xff;#endif}voidRefCount::error(const char * w) const{ ExEnv::errn() << "RefCount: ERROR: " << w << endl; ExEnv::errn() << "The type name is " << typeid(*this).name() << std::endl; abort();}voidRefCount::too_many_refs() const{ error("Too many refs.");}voidRefCount::not_enough_refs() const{ error("Ref count dropped below zero.");}RefCount::~RefCount(){#if REF_MANAGE if (managed() && nreference()) { error("Deleting a referenced object."); }#endif}///////////////////////////////////////////////////////////////////////voidRefBase::warn ( const char * msg) const{ ExEnv::errn() << "WARNING: " << msg << endl;}voidRefBase::warn_ref_to_stack() const{ warn("Ref: creating a reference to stack data");}voidRefBase::warn_skip_stack_delete() const{ warn("Ref: skipping delete of object on the stack");}voidRefBase::warn_bad_ref_count() const{ warn("Ref: bad reference count in referenced object\n");}voidRefBase::ref_info(RefCount*p, ostream& os) const{ if (p) os << "nreference() = " << p->nreference() << endl; else os << "reference is null" << endl;}voidRefBase::require_nonnull() const{ if (parentpointer() == 0) { ExEnv::errn() << "RefBase: needed a nonnull pointer but got null" << endl; abort(); }}RefBase::~RefBase(){}voidRefBase::check_pointer() const{ if (parentpointer() && parentpointer()->nreference() <= 0) { warn_bad_ref_count(); }}voidRefBase::ref_info(ostream& os) const{ RefBase::ref_info(parentpointer(),os);}voidRefBase::reference(RefCount *p){ if (p) {#if REF_CHECK_STACK if (DO_REF_CHECK_STACK(p)) { DO_REF_UNMANAGE(p); warn_ref_to_stack(); }#endif p->reference(); }}intRefBase::dereference(RefCount *p){ if (p) return p->dereference(); else return -1;}/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "CLJ"// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -