| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef _IGNITE_COMMON_CONCURRENT |
| #define _IGNITE_COMMON_CONCURRENT |
| |
| #include <cassert> |
| #include <utility> |
| |
| #include "ignite/common/concurrent_os.h" |
| |
| namespace ignite |
| { |
| namespace common |
| { |
| namespace concurrent |
| { |
| /** |
| * Type tag for static pointer cast. |
| */ |
| struct StaticTag {}; |
| |
| /** |
| * Default deleter implementation. |
| * |
| * @param obj Object to be deleted. |
| */ |
| template<typename T> |
| IGNITE_IMPORT_EXPORT void SharedPointerDefaultDeleter(T* obj) |
| { |
| delete obj; |
| } |
| |
| /** |
| * Empty deleter implementation. |
| * |
| * @param obj Object to be deleted. |
| */ |
| template<typename T> |
| IGNITE_IMPORT_EXPORT void SharedPointerEmptyDeleter(T*) |
| { |
| // No-op. |
| } |
| |
| /** |
| * Holder of shared pointer data. |
| */ |
| class IGNITE_IMPORT_EXPORT SharedPointerImpl |
| { |
| public: |
| typedef void(*DeleterType)(void*); |
| /** |
| * Constructor. |
| * |
| * @param ptr Raw pointer. |
| */ |
| SharedPointerImpl(void* ptr, DeleterType deleter); |
| |
| /** |
| * Get raw pointer. |
| * |
| * @return Raw pointer. |
| */ |
| void* Pointer(); |
| |
| /** |
| * Get raw pointer. |
| * |
| * @return Raw pointer. |
| */ |
| const void* Pointer() const; |
| |
| /** |
| * Get raw pointer. |
| * |
| * @return Raw pointer. |
| */ |
| DeleterType Deleter(); |
| |
| /** |
| * Increment usage counter. |
| */ |
| void Increment(); |
| |
| /** |
| * Decrement usage counter. |
| * |
| * @return True if counter reached zero. |
| */ |
| bool Decrement(); |
| private: |
| /** Raw pointer. */ |
| void* ptr; |
| |
| /** Deleter. */ |
| DeleterType deleter; |
| |
| /** Reference count. */ |
| int32_t refCnt; |
| |
| IGNITE_NO_COPY_ASSIGNMENT(SharedPointerImpl); |
| }; |
| |
| /* Forward declaration. */ |
| template<typename T> |
| class IGNITE_IMPORT_EXPORT EnableSharedFromThis; |
| |
| /* Forward declaration. */ |
| template<typename T> |
| inline void ImplEnableShared(EnableSharedFromThis<T>* some, SharedPointerImpl* impl); |
| |
| // Do nothing if the instance is not derived from EnableSharedFromThis. |
| inline void ImplEnableShared(const volatile void*, const volatile void*) |
| { |
| // No-op. |
| } |
| |
| /** |
| * Shared pointer. |
| */ |
| template<typename T> |
| class IGNITE_IMPORT_EXPORT SharedPointer |
| { |
| public: |
| friend class EnableSharedFromThis<T>; |
| |
| template<typename T2> |
| friend class SharedPointer; |
| |
| /** |
| * Constructor. |
| */ |
| SharedPointer() : |
| ptr(0), |
| impl(0) |
| { |
| // No-op. |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param ptr Raw pointer. |
| * @param deleter Delete function. |
| */ |
| SharedPointer(T* ptr, void(*deleter)(T*) = &SharedPointerDefaultDeleter<T>) : |
| ptr(ptr), |
| impl(0) |
| { |
| if (ptr) |
| { |
| impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(deleter)); |
| ImplEnableShared(ptr, impl); |
| } |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param ptr Raw pointer. |
| * @param deleter Delete function. |
| */ |
| template<typename T2> |
| SharedPointer(T2* ptr, void(*deleter)(T2*) = &SharedPointerDefaultDeleter<T2>) : |
| ptr(ptr), |
| impl(0) |
| { |
| if (ptr) |
| { |
| impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(deleter)); |
| ImplEnableShared(ptr, impl); |
| } |
| } |
| |
| /** |
| * Copy constructor. |
| * |
| * @param other Instance to copy. |
| */ |
| SharedPointer(const SharedPointer& other) : |
| ptr(other.ptr), |
| impl(other.impl) |
| { |
| if (impl) |
| impl->Increment(); |
| } |
| |
| /** |
| * Copy constructor. |
| * |
| * @param other Instance to copy. |
| */ |
| template<typename T2> |
| SharedPointer(const SharedPointer<T2>& other) : |
| ptr(other.ptr), |
| impl(other.impl) |
| { |
| if (impl) |
| impl->Increment(); |
| } |
| |
| /** |
| * Static-cast constructor. |
| * |
| * @param other Instance to copy. |
| */ |
| template<typename T2> |
| SharedPointer(const SharedPointer<T2>& other, StaticTag) : |
| ptr(static_cast<T*>(other.ptr)), |
| impl(other.impl) |
| { |
| if (impl) |
| impl->Increment(); |
| } |
| |
| /** |
| * Assignment operator. |
| * |
| * @param other Other instance. |
| */ |
| SharedPointer& operator=(const SharedPointer& other) |
| { |
| if (this != &other) |
| { |
| SharedPointer tmp(other); |
| |
| Swap(tmp); |
| } |
| |
| return *this; |
| } |
| |
| /** |
| * Assignment operator. |
| * |
| * @param other Other instance. |
| */ |
| template<typename T2> |
| SharedPointer& operator=(const SharedPointer<T2>& other) |
| { |
| SharedPointer<T> tmp(other); |
| |
| Swap(tmp); |
| |
| return *this; |
| } |
| |
| /** |
| * Destructor. |
| */ |
| IGNORE_FALSE_UNDEFINED |
| ~SharedPointer() |
| { |
| if (impl && impl->Decrement()) |
| { |
| void* ptr0 = impl->Pointer(); |
| |
| void(*deleter)(void*) = impl->Deleter(); |
| |
| deleter(ptr0); |
| |
| delete impl; |
| |
| ptr = 0; |
| } |
| } |
| |
| /** |
| * Get raw pointer. |
| * |
| * @return Raw pointer. |
| */ |
| T* Get() |
| { |
| return ptr; |
| } |
| |
| /** |
| * Get raw pointer. |
| * |
| * @return Raw pointer. |
| */ |
| T* Get() const |
| { |
| return ptr; |
| } |
| |
| /** |
| * Check whether underlying raw pointer is valid. |
| * |
| * Invalid instance can be returned if some of the previous |
| * operations have resulted in a failure. For example invalid |
| * instance can be returned by not-throwing version of method |
| * in case of error. Invalid instances also often can be |
| * created using default constructor. |
| * |
| * @return True if valid. |
| */ |
| bool IsValid() const |
| { |
| return impl != 0; |
| } |
| |
| /** |
| * Swap pointer content with another instance. |
| * |
| * @param other Other instance. |
| */ |
| void Swap(SharedPointer& other) |
| { |
| if (this != &other) |
| { |
| T* ptrTmp = ptr; |
| SharedPointerImpl* implTmp = impl; |
| |
| ptr = other.ptr; |
| impl = other.impl; |
| |
| other.ptr = ptrTmp; |
| other.impl = implTmp; |
| } |
| } |
| |
| private: |
| /* Pointer. */ |
| T* ptr; |
| |
| /** Implementation. */ |
| SharedPointerImpl* impl; |
| }; |
| |
| /** |
| * Enables static-cast semantics for SharedPointer. |
| * |
| * @param val Value to cast. |
| */ |
| template<class T1, class T2> |
| SharedPointer<T1> StaticPointerCast(const SharedPointer<T2>& val) |
| { |
| return SharedPointer<T1>(val, StaticTag()); |
| } |
| |
| /** |
| * The class provides functionality that allows objects of derived |
| * classes to create instances of shared_ptr pointing to themselves |
| * and sharing ownership with existing shared_ptr objects. |
| */ |
| template<typename T> |
| class IGNITE_IMPORT_EXPORT EnableSharedFromThis |
| { |
| public: |
| /** |
| * Default constructor. |
| */ |
| EnableSharedFromThis() : self(0) |
| { |
| // No-op. |
| } |
| |
| /** |
| * Copy constructor. |
| */ |
| EnableSharedFromThis(const EnableSharedFromThis&) : self(0) |
| { |
| // No-op. |
| } |
| |
| /** |
| * Assignment operator. |
| */ |
| EnableSharedFromThis& operator=(const EnableSharedFromThis&) |
| { |
| return *this; |
| } |
| |
| /** |
| * Destructor. |
| */ |
| virtual ~EnableSharedFromThis() |
| { |
| // No-op. |
| } |
| |
| /** |
| * Create shared pointer for this instance. |
| * |
| * Can only be called on already shared object. |
| * @return New shared pointer instance. |
| */ |
| SharedPointer<T> SharedFromThis() |
| { |
| assert(self != 0); |
| |
| SharedPointer<T> ptr; |
| |
| ptr.impl = self; |
| |
| self->Increment(); |
| |
| return ptr; |
| } |
| |
| private: |
| template<typename T0> |
| friend void ImplEnableShared(EnableSharedFromThis<T0>*, SharedPointerImpl*); |
| |
| /** Shared pointer base. */ |
| SharedPointerImpl* self; |
| }; |
| |
| // Implementation for instances derived from EnableSharedFromThis. |
| template<typename T> |
| inline void ImplEnableShared(EnableSharedFromThis<T>* some, SharedPointerImpl* impl) |
| { |
| if (some) |
| some->self = impl; |
| } |
| |
| /** |
| * Lock guard. |
| */ |
| template<typename T> |
| class LockGuard |
| { |
| public: |
| /** |
| * Constructor. |
| * |
| * @param lock Lockable object. |
| */ |
| LockGuard(T& lock) : |
| lock(&lock) |
| { |
| lock.Enter(); |
| } |
| |
| /** |
| * Destructor. |
| */ |
| ~LockGuard() |
| { |
| if (lock) |
| lock->Leave(); |
| } |
| |
| /** |
| * Releases control over lock without unlocking it. |
| */ |
| void Forget() |
| { |
| lock = 0; |
| } |
| |
| /** |
| * Releases control over lock and unlocks it as if it would |
| * go out of scope. |
| */ |
| void Reset() |
| { |
| if (lock) |
| { |
| lock->Leave(); |
| |
| Forget(); |
| } |
| } |
| |
| private: |
| T* lock; |
| }; |
| |
| typedef LockGuard<CriticalSection> CsLockGuard; |
| |
| /** |
| * Shared lock guard. |
| * Locks guard in shared mode. |
| */ |
| template<typename T> |
| class SharedLockGuard |
| { |
| public: |
| /** |
| * Constructor. |
| * |
| * @param lock Lockable object. |
| */ |
| SharedLockGuard(T& lock) : |
| lock(&lock) |
| { |
| lock.LockShared(); |
| } |
| |
| /** |
| * Destructor. |
| */ |
| ~SharedLockGuard() |
| { |
| if (lock) |
| lock->ReleaseShared(); |
| } |
| |
| /** |
| * Releases control over lock without unlocking it. |
| */ |
| void Forget() |
| { |
| lock = 0; |
| } |
| |
| /** |
| * Releases control over lock and unlocks it as if it would |
| * go out of scope. |
| */ |
| void Reset() |
| { |
| if (lock) |
| { |
| lock->ReleaseShared(); |
| |
| Forget(); |
| } |
| } |
| |
| private: |
| T* lock; |
| }; |
| |
| typedef SharedLockGuard<ReadWriteLock> RwSharedLockGuard; |
| |
| /** |
| * Exclusive lock guard. |
| * Locks guard in exclusive mode. |
| */ |
| template<typename T> |
| class ExclusiveLockGuard |
| { |
| public: |
| /** |
| * Constructor. |
| * |
| * @param lock Lockable object. |
| */ |
| ExclusiveLockGuard(T& lock) : |
| lock(&lock) |
| { |
| lock.LockExclusive(); |
| } |
| |
| /** |
| * Destructor. |
| */ |
| ~ExclusiveLockGuard() |
| { |
| if (lock) |
| lock->ReleaseExclusive(); |
| } |
| |
| /** |
| * Releases control over lock without unlocking it. |
| */ |
| void Forget() |
| { |
| lock = 0; |
| } |
| |
| /** |
| * Releases control over lock and unlocks it as if it would |
| * go out of scope. |
| */ |
| void Reset() |
| { |
| if (lock) |
| { |
| lock->ReleaseExclusive(); |
| |
| Forget(); |
| } |
| } |
| |
| private: |
| T* lock; |
| }; |
| |
| typedef ExclusiveLockGuard<ReadWriteLock> RwExclusiveLockGuard; |
| } |
| } |
| } |
| |
| #endif //_IGNITE_COMMON_CONCURRENT |