=== added file 'dcpp/Atomic.h' --- dcpp/Atomic.h 1970-01-01 00:00:00 +0000 +++ dcpp/Atomic.h 2010-08-14 20:35:14 +0000 @@ -0,0 +1,70 @@ +#if !defined(DCPP_ATOMIC_H) +#define DCPP_ATOMIC_H + +#include +#include + + +/* + * Atomic + * + * Suitable only for thread-safe accounting of some statistics. + * Not suitable for any synchronization between threads, + * since does not garantees necessary memory barriers. + * + */ + +template +class Atomic; + +// uint32_t +template <> +class Atomic { + typedef boost::uint32_t value_type; +public: + Atomic(value_type val) { assign(val); } + Atomic(const Atomic& other) { assign(static_cast(other)); } + + // operator= + // return void to be safe + void operator=(value_type val) { assign(val); } + void operator=(const Atomic& other) { + return operator=(static_cast(other)); + } + + // type cast + operator value_type() const { + return boost::interprocess::detail::atomic_read32(&m_value); + } + + // increment + void inc() { boost::interprocess::detail::atomic_inc32(&m_value); } + + // decrement + void dec() { boost::interprocess::detail::atomic_dec32(&m_value); } + +private: + mutable value_type m_value; + void assign(value_type val) { boost::interprocess::detail::atomic_write32(&m_value, val); } +}; + +// int32_t +// just forward all operations to underlying uint32_t variable +template <> +class Atomic { + typedef boost::int32_t value_type; +public: + Atomic(value_type val) : m_value(val) {} + Atomic(const Atomic& other) : m_value(other) {} + + void operator=(value_type val) { m_value=val; } + void operator=(const Atomic& other) { m_value=other; } + operator value_type() const { return static_cast(m_value); } + + void inc() { m_value.inc(); } + void dec() { m_value.dec(); } +private: + Atomic m_value; +}; + +#endif // !defined(DCPP_ATOMIC_H) === modified file 'dcpp/Client.cpp' --- dcpp/Client.cpp 2009-08-15 04:40:26 +0000 +++ dcpp/Client.cpp 2010-08-14 20:20:27 +0000 @@ -158,24 +158,24 @@ void Client::updateCounts(bool aRemove) { // We always remove the count and then add the correct one if requested... if(countType == COUNT_NORMAL) { - Thread::safeDec(counts.normal); + counts.normal.dec(); } else if(countType == COUNT_REGISTERED) { - Thread::safeDec(counts.registered); + counts.registered.dec(); } else if(countType == COUNT_OP) { - Thread::safeDec(counts.op); + counts.op.dec(); } countType = COUNT_UNCOUNTED; if(!aRemove) { if(getMyIdentity().isOp()) { - Thread::safeInc(counts.op); + counts.op.inc(); countType = COUNT_OP; } else if(getMyIdentity().isRegistered()) { - Thread::safeInc(counts.registered); + counts.registered.inc(); countType = COUNT_REGISTERED; } else { - Thread::safeInc(counts.normal); + counts.normal.inc(); countType = COUNT_NORMAL; } } === modified file 'dcpp/Client.h' --- dcpp/Client.h 2009-08-15 04:40:26 +0000 +++ dcpp/Client.h 2010-08-14 20:18:16 +0000 @@ -26,6 +26,7 @@ #include "BufferedSocketListener.h" #include "TimerManager.h" #include "ClientListener.h" +#include "Atomic.h" namespace dcpp { @@ -72,7 +73,10 @@ static string getCounts() { char buf[128]; - return string(buf, snprintf(buf, sizeof(buf), "%ld/%ld/%ld", counts.normal, counts.registered, counts.op)); + return string(buf, snprintf(buf, sizeof(buf), "%ld/%ld/%ld", + static_cast(counts.normal), + static_cast(counts.registered), + static_cast(counts.op))); } StringMap& escapeParams(StringMap& sm) { @@ -112,12 +116,16 @@ friend class ClientManager; Client(const string& hubURL, char separator, bool secure_); virtual ~Client() throw(); + struct Counts { - Counts(long n = 0, long r = 0, long o = 0) : normal(n), registered(r), op(o) { } - volatile long normal; - volatile long registered; - volatile long op; - bool operator !=(const Counts& rhs) { return normal != rhs.normal || registered != rhs.registered || op != rhs.op; } + private: + typedef Atomic atomic_counter_t; + public: + typedef boost::int32_t value_type; + Counts(value_type n = 0, value_type r = 0, value_type o = 0) : normal(n), registered(r), op(o) { } + atomic_counter_t normal; + atomic_counter_t registered; + atomic_counter_t op; }; enum States {