diff options
Diffstat (limited to 'shared/zbase.h')
-rw-r--r-- | shared/zbase.h | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/shared/zbase.h b/shared/zbase.h index 6d9ac578..55bc0d96 100644 --- a/shared/zbase.h +++ b/shared/zbase.h @@ -3,7 +3,7 @@ // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * // * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** -// + #ifndef Z_BASE_H_INCLUDED #define Z_BASE_H_INCLUDED @@ -12,6 +12,7 @@ #include <sstream> #include <algorithm> #include <string_tools.h> +#include <boost/detail/atomic_count.hpp> /* Allocator Policy: @@ -101,24 +102,17 @@ private: size_t capacity; //allocated size without null-termination }; - static Descriptor* descr(T* ptr) - { - return reinterpret_cast<Descriptor*>(ptr) - 1; - } - - static const Descriptor* descr(const T* ptr) - { - return reinterpret_cast<const Descriptor*>(ptr) - 1; - } + static Descriptor* descr( T* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; } + static const Descriptor* descr(const T* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; } }; template <typename T, //Character Type class AP> //Allocator Policy -class StorageRefCount : public AP +class StorageRefCountThreadSafe : public AP { protected: - ~StorageRefCount() {} + ~StorageRefCountThreadSafe() {} static T* create(size_t size) { @@ -132,10 +126,7 @@ protected: assert(minCapacity >= size); Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(T))); - - newDescr->refCount = 1; - newDescr->length = size; - newDescr->capacity = newCapacity; + new (newDescr) Descriptor(1, size, newCapacity); return reinterpret_cast<T*>(newDescr + 1); } @@ -150,7 +141,10 @@ protected: static void destroy(T* ptr) { if (--descr(ptr)->refCount == 0) + { + descr(ptr)->~Descriptor(); AP::deallocate(descr(ptr)); + } } static bool canWrite(const T* ptr, size_t minCapacity) //needs to be checked before writing to "ptr" @@ -173,26 +167,23 @@ protected: private: struct Descriptor { - size_t refCount; + Descriptor(long rc, size_t len, size_t cap) : refCount(rc), length(len), capacity(cap) {} + + boost::detail::atomic_count refCount; //practically no perf loss: ~0.2%! (FFS comparison) size_t length; size_t capacity; //allocated size without null-termination }; - static Descriptor* descr(T* ptr) - { - return reinterpret_cast<Descriptor*>(ptr) - 1; - } - - static const Descriptor* descr(const T* ptr) - { - return reinterpret_cast<const Descriptor*>(ptr) - 1; - } + static Descriptor* descr( T* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; } + static const Descriptor* descr(const T* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; } }; -template <class T, //Character Type - template <class, class> class SP = StorageRefCount, //Storage Policy - class AP = AllocatorOptimalSpeed> //Allocator Policy +//perf note: interstingly StorageDeepCopy and StorageRefCountThreadSafe show same performance in FFS comparison + +template <class T, //Character Type + template <class, class> class SP = StorageRefCountThreadSafe, //Storage Policy + class AP = AllocatorOptimalSpeed> //Allocator Policy class Zbase : public SP<T, AP> { public: @@ -200,6 +191,7 @@ public: Zbase(const T* source); //implicit conversion from a C-string Zbase(const T* source, size_t length); Zbase(const Zbase& source); + Zbase(Zbase&& tmp); explicit Zbase(T source); //dangerous if implicit: T buffer[]; Zbase name = buffer; ups... //allow explicit construction from different string type, prevent ambiguity via SFINAE template <class S> explicit Zbase(const S& other, typename S::value_type = 0); @@ -261,6 +253,7 @@ public: void push_back(T val); //STL access Zbase& operator=(const Zbase& source); + Zbase& operator=(Zbase&& tmp); Zbase& operator=(const T* source); Zbase& operator=(T source); Zbase& operator+=(const Zbase& other); @@ -380,6 +373,14 @@ Zbase<T, SP, AP>::Zbase(const Zbase<T, SP, AP>& source) template <class T, template <class, class> class SP, class AP> +inline +Zbase<T, SP, AP>::Zbase(Zbase<T, SP, AP>&& tmp) +{ + rawStr = this->clone(tmp.rawStr); //for a ref-counting string there probably isn't a faster way, even with r-value references +} + + +template <class T, template <class, class> class SP, class AP> template <class S> inline Zbase<T, SP, AP>::Zbase(const S& other, typename S::value_type) @@ -827,6 +828,15 @@ Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(const Zbase<T, SP, AP>& source) template <class T, template <class, class> class SP, class AP> inline +Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(Zbase<T, SP, AP>&& tmp) +{ + swap(tmp); + return *this; +} + + +template <class T, template <class, class> class SP, class AP> +inline Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(const T* source) { return assign(source, zen::cStringLength(source)); |