mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-18 10:46:33 +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
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "NonCopyable.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// <atomic> will replace this whole class eventually once it's ubiquitous
|
||||
#ifndef __GNUC__
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
@ -36,75 +34,34 @@ namespace ZeroTier {
|
||||
class AtomicCounter : NonCopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initialize counter at zero
|
||||
*/
|
||||
AtomicCounter()
|
||||
throw()
|
||||
{
|
||||
_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++()
|
||||
throw()
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_add_and_fetch(&_v,1);
|
||||
#else
|
||||
#ifdef __WINDOWS__
|
||||
return ++_v;
|
||||
#else
|
||||
_l.lock();
|
||||
int v = ++_v;
|
||||
_l.unlock();
|
||||
return v;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int operator--()
|
||||
throw()
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_sub_and_fetch(&_v,1);
|
||||
#else
|
||||
#ifdef __WINDOWS__
|
||||
return --_v;
|
||||
#else
|
||||
_l.lock();
|
||||
int v = --_v;
|
||||
_l.unlock();
|
||||
return v;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef __WINDOWS__
|
||||
std::atomic_int _v;
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
int _v;
|
||||
#ifndef __GNUC__
|
||||
#warning Neither __WINDOWS__ nor __GNUC__ so AtomicCounter using Mutex
|
||||
Mutex _l;
|
||||
#endif
|
||||
#else
|
||||
std::atomic_int _v;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -119,15 +119,39 @@ public:
|
||||
inline T *ptr() const throw() { return _ptr; }
|
||||
|
||||
/**
|
||||
* Set this pointer to null
|
||||
* Set this pointer to NULL
|
||||
*/
|
||||
inline void zero()
|
||||
{
|
||||
if (_ptr) {
|
||||
if (--_ptr->__refCount <= 0)
|
||||
delete _ptr;
|
||||
_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;
|
||||
}
|
||||
_ptr = (T *)0;
|
||||
}
|
||||
|
||||
inline bool operator==(const SharedPtr &sp) const throw() { return (_ptr == sp._ptr); }
|
||||
|
@ -251,14 +251,25 @@ bool Topology::worldUpdateIfValid(const World &newWorld)
|
||||
void Topology::clean(uint64_t now)
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = (Address *)0;
|
||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||
while (i.next(a,p)) {
|
||||
if (((now - (*p)->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootAddresses.begin(),_rootAddresses.end(),*a) == _rootAddresses.end())) {
|
||||
_peers.erase(*a);
|
||||
} else {
|
||||
(*p)->clean(now);
|
||||
{
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = (Address *)0;
|
||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||
while (i.next(a,p)) {
|
||||
if (((now - (*p)->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(std::find(_rootAddresses.begin(),_rootAddresses.end(),*a) == _rootAddresses.end())) {
|
||||
_peers.erase(*a);
|
||||
} else {
|
||||
(*p)->clean(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user