mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-05-21 09:48:07 +00:00
Implement "weak pointer" behavior on Topology Path canonicalization hash table.
This commit is contained in:
parent
d1101441b3
commit
4931e44998
@ -20,11 +20,9 @@
|
|||||||
#define ZT_ATOMICCOUNTER_HPP
|
#define ZT_ATOMICCOUNTER_HPP
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Mutex.hpp"
|
|
||||||
#include "NonCopyable.hpp"
|
#include "NonCopyable.hpp"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifndef __GNUC__
|
||||||
// <atomic> will replace this whole class eventually once it's ubiquitous
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -36,75 +34,34 @@ namespace ZeroTier {
|
|||||||
class AtomicCounter : NonCopyable
|
class AtomicCounter : NonCopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Initialize counter at zero
|
|
||||||
*/
|
|
||||||
AtomicCounter()
|
AtomicCounter()
|
||||||
throw()
|
|
||||||
{
|
{
|
||||||
_v = 0;
|
_v = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator int() const
|
|
||||||
throw()
|
|
||||||
{
|
|
||||||
#ifdef __GNUC__
|
|
||||||
return __sync_or_and_fetch(const_cast <volatile int *>(&_v),0);
|
|
||||||
#else
|
|
||||||
#ifdef __WINDOWS__
|
|
||||||
return (int)_v;
|
|
||||||
#else
|
|
||||||
_l.lock();
|
|
||||||
int v = _v;
|
|
||||||
_l.unlock();
|
|
||||||
return v;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int operator++()
|
inline int operator++()
|
||||||
throw()
|
|
||||||
{
|
{
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
return __sync_add_and_fetch(&_v,1);
|
return __sync_add_and_fetch(&_v,1);
|
||||||
#else
|
#else
|
||||||
#ifdef __WINDOWS__
|
|
||||||
return ++_v;
|
return ++_v;
|
||||||
#else
|
|
||||||
_l.lock();
|
|
||||||
int v = ++_v;
|
|
||||||
_l.unlock();
|
|
||||||
return v;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int operator--()
|
inline int operator--()
|
||||||
throw()
|
|
||||||
{
|
{
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
return __sync_sub_and_fetch(&_v,1);
|
return __sync_sub_and_fetch(&_v,1);
|
||||||
#else
|
#else
|
||||||
#ifdef __WINDOWS__
|
|
||||||
return --_v;
|
return --_v;
|
||||||
#else
|
|
||||||
_l.lock();
|
|
||||||
int v = --_v;
|
|
||||||
_l.unlock();
|
|
||||||
return v;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef __WINDOWS__
|
#ifdef __GNUC__
|
||||||
std::atomic_int _v;
|
|
||||||
#else
|
|
||||||
int _v;
|
int _v;
|
||||||
#ifndef __GNUC__
|
#else
|
||||||
#warning Neither __WINDOWS__ nor __GNUC__ so AtomicCounter using Mutex
|
std::atomic_int _v;
|
||||||
Mutex _l;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,16 +119,40 @@ public:
|
|||||||
inline T *ptr() const throw() { return _ptr; }
|
inline T *ptr() const throw() { return _ptr; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this pointer to null
|
* Set this pointer to NULL
|
||||||
*/
|
*/
|
||||||
inline void zero()
|
inline void zero()
|
||||||
{
|
{
|
||||||
if (_ptr) {
|
if (_ptr) {
|
||||||
if (--_ptr->__refCount <= 0)
|
if (--_ptr->__refCount <= 0)
|
||||||
delete _ptr;
|
delete _ptr;
|
||||||
}
|
|
||||||
_ptr = (T *)0;
|
_ptr = (T *)0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this pointer to NULL if this is the only pointer holding the object
|
||||||
|
*
|
||||||
|
* @return True if object was deleted and SharedPtr is now NULL (or was already NULL)
|
||||||
|
*/
|
||||||
|
inline bool reclaimIfWeak()
|
||||||
|
{
|
||||||
|
if (_ptr) {
|
||||||
|
if (++_ptr->__refCount <= 2) {
|
||||||
|
if (--_ptr->__refCount <= 1) {
|
||||||
|
delete _ptr;
|
||||||
|
_ptr = (T *)0;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline bool operator==(const SharedPtr &sp) const throw() { return (_ptr == sp._ptr); }
|
inline bool operator==(const SharedPtr &sp) const throw() { return (_ptr == sp._ptr); }
|
||||||
inline bool operator!=(const SharedPtr &sp) const throw() { return (_ptr != sp._ptr); }
|
inline bool operator!=(const SharedPtr &sp) const throw() { return (_ptr != sp._ptr); }
|
||||||
|
@ -251,6 +251,7 @@ bool Topology::worldUpdateIfValid(const World &newWorld)
|
|||||||
void Topology::clean(uint64_t now)
|
void Topology::clean(uint64_t now)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_lock);
|
Mutex::Lock _l(_lock);
|
||||||
|
{
|
||||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||||
Address *a = (Address *)0;
|
Address *a = (Address *)0;
|
||||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||||
@ -262,6 +263,16 @@ void Topology::clean(uint64_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths);
|
||||||
|
Path::HashKey *k = (Path::HashKey *)0;
|
||||||
|
SharedPtr<Path> *p = (SharedPtr<Path> *)0;
|
||||||
|
while (i.next(k,p)) {
|
||||||
|
if (p->reclaimIfWeak())
|
||||||
|
_paths.erase(*k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Identity Topology::_getIdentity(const Address &zta)
|
Identity Topology::_getIdentity(const Address &zta)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user