// 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" 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: ptr_ref* _ref; bool _weak; void acquire(ptr_ref* ref) { if (_ref) release(); 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; if (_weak) _ref->wc--; else _ref->sc--; if (!_ref->sc && _ref->ptr) { T* ptr = static_cast(_ref->ptr); _ref->ptr = 0; delete ptr; } if (!_ref->sc && !_ref->wc) delete _ref; _ref = 0; } template void acquire(const ptr& ptr) { T* t = static_cast(0); 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