// ndppd - NDP Proxy Daemon // Copyright (C) 2011 Daniel Adolfsson // // 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 3 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, see . #pragma once #include #include "ndppd.h" #include "logger.h" NDPPD_NS_BEGIN class invalid_pointer : public std::exception { public: invalid_pointer() throw() {}; }; template class weak_ptr; // This template class simplifies the usage of pointers. It's basically // a reference-counting smart pointer that supports both weak and // strong references. template class ptr { template friend class ptr; struct ptr_ref { T* ptr; int wc, sc; }; protected: bool _weak; ptr_ref* _ref; void acquire(ptr_ref* ref) { if (_ref) { release(); } if (ref && !ref->sc) { throw new invalid_pointer; } if (_ref = ref) { if (_weak) { _ref->wc++; } else { _ref->sc++; } } } void acquire(void* ptr) { _ref = new ptr_ref(); _ref->ptr = (T*)ptr; _ref->wc = !!_weak; _ref->sc = !_weak; } void release() { if (!_ref) { return; } //logger::debug() // << "ptr::release() _ref=" << logger::format("%x", _ref) // << ", _ref->wc=" << _ref->wc << ", _ref->sc=" << _ref->sc // << ", _weak=" << (_weak ? "yes" : "no"); if (_weak) { assert(_ref->wc > 0); _ref->wc--; } else { assert(_ref->sc > 0); if (!--_ref->sc && _ref->ptr) { T* ptr = _ref->ptr; _ref->ptr = 0; _ref->wc++; delete ptr; _ref->wc--; } } /*if (!_weak && !_ref->sc && _ref->ptr) { T* ptr = (T*)(_ref->ptr); _ref->ptr = 0; delete ptr; }*/ if (!_ref->sc && !_ref->wc) { delete _ref; } _ref = 0; } template void acquire(const ptr& ptr) { acquire(ptr._ref); } public: ptr(bool weak = false) : _weak(weak), _ref(0) { } ptr(T* p, bool weak = false) : _weak(weak), _ref(0) { acquire(p); } ptr(const ptr& p, bool weak = false) : _weak(weak), _ref(0) { acquire(p._ref); } ptr(const weak_ptr& p, bool weak = false) : _weak(weak), _ref(0) { acquire(p._ref); } template ptr(const ptr& p, bool weak = false) : _weak(weak), _ref(0) { T* x = (U*)0; acquire(p._ref); } template ptr(const weak_ptr& p, bool weak = false) : _weak(weak), _ref(0) { T* x = (U*)0; acquire(p._ref); } ~ptr() { release(); } void operator=(T* p) { acquire(p); } ptr& operator=(const ptr& p) { acquire(p); return* this; } bool operator==(const ptr& other) const { return other._ref == _ref; } bool operator!=(const ptr& other) const { return other._ref != _ref; } bool is_null() const { return !_ref || !_ref->ptr; } T& operator*() const { return* get_pointer(); } T* operator->() const { return get_pointer(); } operator T*() const { return get_pointer(); } operator bool() const { return !is_null(); } void reset(T* p = 0) { acquire(p); } T* get_pointer() const { if (!_ref || !_ref->ptr) { throw new invalid_pointer; } return static_cast(_ref->ptr); } }; template class weak_ptr : public ptr { public: weak_ptr() : ptr(true) { } weak_ptr(T* p) : ptr(p, true) { } weak_ptr(const ptr& p) : ptr(p, true) { } weak_ptr(const weak_ptr& p) : ptr(p, true) { } template weak_ptr(const ptr& p) : ptr(p, true) { } template weak_ptr(const weak_ptr& p) : ptr(p, true) { } }; NDPPD_NS_END