Implement "weak pointer" behavior on Topology Path canonicalization hash table.

This commit is contained in:
Adam Ierymenko 2016-09-02 12:34:02 -07:00
parent d1101441b3
commit 4931e44998
3 changed files with 49 additions and 57 deletions

View File

@ -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
}; };

View File

@ -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); }

View File

@ -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)
{ {