You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/04/28 13:28:12 UTC
[11/22] ignite git commit: IGNITE-2981: CPP: Added
"EnableSharedFromThis" entity. This closes #636.
IGNITE-2981: CPP: Added "EnableSharedFromThis" entity. This closes #636.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f5f90ecc
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f5f90ecc
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f5f90ecc
Branch: refs/heads/ignite-2523-1
Commit: f5f90ecc88f0f467442506089116a6a153c77b50
Parents: 0460a35
Author: Igor Sapego <is...@gridgain.com>
Authored: Wed Apr 27 11:34:44 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Apr 27 11:34:44 2016 +0300
----------------------------------------------------------------------
.../common/include/ignite/common/concurrent.h | 176 ++++++++++++++++---
modules/platforms/cpp/common/src/concurrent.cpp | 13 +-
.../cpp/core-test/src/concurrent_test.cpp | 93 ++++++++++
3 files changed, 253 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/f5f90ecc/modules/platforms/cpp/common/include/ignite/common/concurrent.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/common/concurrent.h b/modules/platforms/cpp/common/include/ignite/common/concurrent.h
index a4cc3f7..1c84cf5 100644
--- a/modules/platforms/cpp/common/include/ignite/common/concurrent.h
+++ b/modules/platforms/cpp/common/include/ignite/common/concurrent.h
@@ -18,6 +18,8 @@
#ifndef _IGNITE_COMMON_CONCURRENT
#define _IGNITE_COMMON_CONCURRENT
+#include <cassert>
+
#include "ignite/common/concurrent_os.h"
namespace ignite
@@ -43,12 +45,13 @@ namespace ignite
class IGNITE_IMPORT_EXPORT SharedPointerImpl
{
public:
+ typedef void(*DeleterType)(void*);
/**
* Constructor.
*
* @param ptr Raw pointer.
*/
- SharedPointerImpl(void* ptr);
+ SharedPointerImpl(void* ptr, DeleterType deleter);
/**
* Get raw pointer.
@@ -65,6 +68,13 @@ namespace ignite
const void* Pointer() const;
/**
+ * Get raw pointer.
+ *
+ * @return Raw pointer.
+ */
+ DeleterType Deleter();
+
+ /**
* Increment usage counter.
*/
void Increment();
@@ -79,12 +89,29 @@ namespace ignite
/** 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.
*/
@@ -92,10 +119,12 @@ namespace ignite
class IGNITE_IMPORT_EXPORT SharedPointer
{
public:
+ friend class EnableSharedFromThis<T>;
+
/**
* Constructor.
*/
- SharedPointer() : impl(NULL), deleter(NULL)
+ SharedPointer() : impl(0)
{
// No-op.
}
@@ -109,14 +138,11 @@ namespace ignite
{
if (ptr)
{
- impl = new SharedPointerImpl(ptr);
- deleter = SharedPointerDefaultDeleter;
+ impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(&SharedPointerDefaultDeleter<T>));
+ ImplEnableShared(ptr, impl);
}
else
- {
- impl = NULL;
- deleter = NULL;
- }
+ impl = 0;
}
/**
@@ -129,14 +155,11 @@ namespace ignite
{
if (ptr)
{
- this->impl = new SharedPointerImpl(ptr);
- this->deleter = deleter;
+ impl = new SharedPointerImpl(ptr, reinterpret_cast<SharedPointerImpl::DeleterType>(deleter));
+ ImplEnableShared(ptr, impl);
}
else
- {
- this->impl = NULL;
- this->deleter = NULL;
- }
+ impl = 0;
}
/**
@@ -147,7 +170,6 @@ namespace ignite
SharedPointer(const SharedPointer& other)
{
impl = other.impl;
- deleter = other.deleter;
if (impl)
impl->Increment();
@@ -162,18 +184,9 @@ namespace ignite
{
if (this != &other)
{
- // 1. Create new instance.
SharedPointer tmp(other);
- // 2. Swap with temp.
- SharedPointerImpl* impl0 = impl;
- void(*deleter0)(T*) = deleter;
-
- impl = tmp.impl;
- deleter = tmp.deleter;
-
- tmp.impl = impl0;
- tmp.deleter = deleter0;
+ std::swap(impl, tmp.impl);
}
return *this;
@@ -188,9 +201,11 @@ namespace ignite
{
T* ptr = Get();
- delete impl;
+ void(*deleter)(T*) = reinterpret_cast<void(*)(T*)>(impl->Deleter());
deleter(ptr);
+
+ delete impl;
}
}
@@ -226,10 +241,115 @@ namespace ignite
private:
/** Implementation. */
SharedPointerImpl* impl;
+ };
+
+ /**
+ * 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;
+ };
- /** Delete function. */
- void(*deleter)(T*);
+ // 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()
+ {
+ lock.Leave();
+ }
+
+ private:
+ T& lock;
};
+
+ typedef LockGuard<CriticalSection> CsLockGuard;
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/f5f90ecc/modules/platforms/cpp/common/src/concurrent.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/src/concurrent.cpp b/modules/platforms/cpp/common/src/concurrent.cpp
index 3f85b65..5b62387 100644
--- a/modules/platforms/cpp/common/src/concurrent.cpp
+++ b/modules/platforms/cpp/common/src/concurrent.cpp
@@ -70,7 +70,8 @@ namespace ignite
}
}
- SharedPointerImpl::SharedPointerImpl(void* ptr) : ptr(ptr), refCnt(1)
+ SharedPointerImpl::SharedPointerImpl(void* ptr, DeleterType deleter) :
+ ptr(ptr), deleter(deleter), refCnt(1)
{
Memory::Fence();
}
@@ -80,6 +81,16 @@ namespace ignite
return ptr;
}
+ const void* SharedPointerImpl::Pointer() const
+ {
+ return ptr;
+ }
+
+ SharedPointerImpl::DeleterType SharedPointerImpl::Deleter()
+ {
+ return deleter;
+ }
+
void SharedPointerImpl::Increment()
{
Atomics::IncrementAndGet32(&refCnt);
http://git-wip-us.apache.org/repos/asf/ignite/blob/f5f90ecc/modules/platforms/cpp/core-test/src/concurrent_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/concurrent_test.cpp b/modules/platforms/cpp/core-test/src/concurrent_test.cpp
index 2d89b7a..173973d 100644
--- a/modules/platforms/cpp/core-test/src/concurrent_test.cpp
+++ b/modules/platforms/cpp/core-test/src/concurrent_test.cpp
@@ -183,4 +183,97 @@ BOOST_AUTO_TEST_CASE(TestSharedPointer)
delete target;
}
+struct SharedPointerTargetFromThis : public EnableSharedFromThis<SharedPointerTargetFromThis>
+{
+ bool& deleted;
+
+ SharedPointerTargetFromThis(bool& deleted) : deleted(deleted)
+ {
+ deleted = false;
+ }
+};
+
+void DeleteSharedPointerTarget(SharedPointerTargetFromThis* ptr)
+{
+ ptr->deleted = true;
+ delete ptr;
+}
+
+BOOST_AUTO_TEST_CASE(TestEnableSharedFromThis)
+{
+ typedef SharedPointerTargetFromThis TestT;
+
+ bool deleted;
+
+ // 1. Test the simple scenario.
+ TestT* target = new TestT(deleted);
+ BOOST_CHECK(!deleted);
+
+ SharedPointer<TestT>* ptr1 = new SharedPointer<TestT>(target, DeleteSharedPointerTarget);
+ BOOST_CHECK(!deleted);
+
+ delete ptr1;
+ BOOST_CHECK(deleted);
+
+ // 2. Test copy ctor.
+ target = new TestT(deleted);
+ BOOST_CHECK(!deleted);
+
+ ptr1 = new SharedPointer<TestT>(target, DeleteSharedPointerTarget);
+ BOOST_CHECK(!deleted);
+
+ SharedPointer<TestT>* ptr2 = new SharedPointer<TestT>(*ptr1);
+ BOOST_CHECK(!deleted);
+
+ delete ptr1;
+ BOOST_CHECK(!deleted);
+
+ delete ptr2;
+ BOOST_CHECK(deleted);
+
+ // 3. Test assignment logic.
+ target = new TestT(deleted);
+ BOOST_CHECK(!deleted);
+
+ ptr1 = new SharedPointer<TestT>(target, DeleteSharedPointerTarget);
+ BOOST_CHECK(!deleted);
+
+ SharedPointer<TestT> ptr3 = *ptr1;
+ BOOST_CHECK(!deleted);
+
+ delete ptr1;
+ BOOST_CHECK(!deleted);
+
+ ptr3 = SharedPointer<TestT>();
+ BOOST_CHECK(deleted);
+
+ // 4. Test self-assignment.
+ target = new TestT(deleted);
+ BOOST_CHECK(!deleted);
+
+ ptr1 = new SharedPointer<TestT>(target, DeleteSharedPointerTarget);
+
+ *ptr1 = *ptr1;
+
+ delete ptr1;
+
+ BOOST_CHECK(deleted);
+
+ // 5. Test shared from this
+ target = new TestT(deleted);
+ BOOST_CHECK(!deleted);
+
+ ptr1 = new SharedPointer<TestT>(target, DeleteSharedPointerTarget);
+ BOOST_CHECK(!deleted);
+
+ ptr3 = target->SharedFromThis();
+ BOOST_CHECK(!deleted);
+
+ delete ptr1;
+ BOOST_CHECK(!deleted);
+
+ ptr3 = SharedPointer<TestT>();
+ BOOST_CHECK(deleted);
+}
+
BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file