#ifndef RC_PTR_H #define RC_PTR_H /**************************************************************************** ** COPYRIGHT (C): 1997 Cay S. Horstmann. All Rights Reserved. ** PROJECT: Practical OO Development with C++ and Java ** FILE: rc_ptr.h ** PURPOSE: smart pointers with reference counting ** VERSION 1.0 ** PROGRAMMERS: Cay Horstmann (CSH) ** RELEASE DATE: 3-15-97 (CSH) ** UPDATE HISTORY: ****************************************************************************/ #line 27 "rc_ptr.cpp" class rc_base { public: void init() { _rc = 1; } bool is_unique() const { return _rc == 1; } void incref() { ++_rc; } int decref() { return --_rc; } private: int _rc; }; #line 38 "rc_ptr.cpp" template class rc_wrapper : public rc_base, public X {}; #line 42 "rc_ptr.cpp" template class rc_ptr { public: rc_ptr() : _pwrap(NULL) {} rc_ptr(const rc_ptr& b) { copy(b); } const rc_ptr& operator=(const rc_ptr& b) { if (this != &b) { free(); copy(b); } return *this; } ~rc_ptr() { free(); } X* operator->() { assert(_pwrap != NULL); return (X*)_pwrap; } const X* operator->() const { assert(_pwrap != NULL); return (const X*)_pwrap; } X& operator*() { assert(_pwrap != NULL); return *(X*)_pwrap; } const X& operator*() const { assert(_pwrap != NULL); return *(const X*)_pwrap; } bool operator!() const { return _pwrap == NULL; } bool operator==(int n) const { return n == 0 && _pwrap == NULL; } bool operator!=(int n) const { return n != 0 || _pwrap != NULL; } bool operator==(const rc_ptr& b) const { return _pwrap == b._pwrap; } bool operator!=(const rc_ptr& b) const { return _pwrap != b._pwrap; } rc_ptr(X* p) { _pwrap = (rc_wrapper*)p; if (_pwrap) _pwrap->incref(); } operator const X*() const { return (const X*)_pwrap; } const rc_ptr& operator=(const X* p) { free(); _pwrap = (rc_wrapper*)p; if (_pwrap) _pwrap->incref(); return *this; } void free() // call to break cycles { if (_pwrap != NULL && _pwrap->decref() == 0) { ((X*)_pwrap)->~X(); delete[] (char*)_pwrap; } _pwrap = NULL; } void unique() const { if (_pwrap != NULL && !_pwrap->is_unique()) { X* px = (X*)_pwrap; new(*const_cast*>(this)) X(*px); } } rc_ptr clone() const { rc_ptr r; if (_pwrap != NULL) new(r) X(*(X*)_pwrap); return r; } private: void copy(const rc_ptr& b) { _pwrap = b._pwrap; if (_pwrap) _pwrap->incref(); } rc_wrapper* _pwrap; friend void* operator new(size_t n, rc_ptr& p); }; #line 142 "rc_ptr.cpp" template void* operator new(size_t, rc_ptr& p) { p.free(); char* cp = new char[sizeof(rc_wrapper)]; p._pwrap = (rc_wrapper*)cp; p._pwrap->init(); return (X*)p._pwrap; } #endif