blob: 490e005730dbae8c92b14491a530bbf7afb758f9 [file] [log] [blame]
/*
* 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