245 lines
4.3 KiB
C
245 lines
4.3 KiB
C
|
// ndppd - NDP Proxy Daemon
|
||
|
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
|
||
|
//
|
||
|
// 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 <http://www.gnu.org/licenses/>.
|
||
|
#pragma once
|
||
|
|
||
|
#include <exception>
|
||
|
|
||
|
#include "ndppd.h"
|
||
|
|
||
|
NDPPD_NS_BEGIN
|
||
|
|
||
|
class invalid_pointer : public std::exception {
|
||
|
public:
|
||
|
invalid_pointer() throw() {};
|
||
|
};
|
||
|
|
||
|
template <class T>
|
||
|
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 <typename T>
|
||
|
class ptr {
|
||
|
template <typename U>
|
||
|
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<T* >(_ref->ptr);
|
||
|
_ref->ptr = 0;
|
||
|
delete ptr;
|
||
|
}
|
||
|
|
||
|
if (!_ref->sc && !_ref->wc)
|
||
|
delete _ref;
|
||
|
|
||
|
_ref = 0;
|
||
|
}
|
||
|
|
||
|
template <class U>
|
||
|
void acquire(const ptr<U>& ptr)
|
||
|
{
|
||
|
T* t = static_cast<U* >(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<T>& p, bool weak = false) :
|
||
|
_weak(weak), _ref(0)
|
||
|
{
|
||
|
acquire(p._ref);
|
||
|
}
|
||
|
|
||
|
ptr(const weak_ptr<T>& p, bool weak = false) :
|
||
|
_weak(weak), _ref(0)
|
||
|
{
|
||
|
acquire(p._ref);
|
||
|
}
|
||
|
|
||
|
template <class U>
|
||
|
ptr(const ptr<U>& p, bool weak = false) :
|
||
|
_weak(weak), _ref(0)
|
||
|
{
|
||
|
T* x = (U*)0;
|
||
|
acquire(p._ref);
|
||
|
}
|
||
|
|
||
|
template <class U>
|
||
|
ptr(const weak_ptr<U>& p, bool weak = false) :
|
||
|
_weak(weak), _ref(0)
|
||
|
{
|
||
|
T* x = (U*)0;
|
||
|
acquire(p._ref);
|
||
|
}
|
||
|
|
||
|
~ptr()
|
||
|
{
|
||
|
release();
|
||
|
}
|
||
|
|
||
|
void operator=(T* p)
|
||
|
{
|
||
|
acquire(p);
|
||
|
}
|
||
|
|
||
|
ptr<T>& operator=(const ptr<T>& p)
|
||
|
{
|
||
|
acquire(p);
|
||
|
return* this;
|
||
|
}
|
||
|
|
||
|
bool operator==(const ptr<T>& other) const
|
||
|
{
|
||
|
return other._ref == _ref;
|
||
|
}
|
||
|
|
||
|
bool operator!=(const ptr<T>& 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<T* >(_ref->ptr);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
class weak_ptr : public ptr<T> {
|
||
|
public:
|
||
|
weak_ptr() :
|
||
|
ptr<T>(true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
weak_ptr(T* p) :
|
||
|
ptr<T>(p, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
weak_ptr(const ptr<T>& p) :
|
||
|
ptr<T>(p, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
weak_ptr(const weak_ptr<T>& p) :
|
||
|
ptr<T>(p, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template <class U>
|
||
|
weak_ptr(const ptr<U>& p) :
|
||
|
ptr<T>(p, true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template <class U>
|
||
|
weak_ptr(const weak_ptr<U>& p) :
|
||
|
ptr<T>(p, true)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
NDPPD_NS_END
|
||
|
|
||
|
|