From 91e873130916a6936b11e6a304c62a19ff50acfb Mon Sep 17 00:00:00 2001 From: Richard Huang Date: Thu, 13 Aug 2015 11:10:25 +0100 Subject: [PATCH] Implemented WeakHandle in dali-core WeakHandle stores a weak pointer to an internal Dali object. The handle to the object can be accessed if the object exists, and such access is not reference counted. When the object is deleted, the weak pointer will be set to NULL, and any further attmpt to access to a deleted object will return an empty handle. Change-Id: I56c8b0ea398f22c1d735270e6287124bdcea740b --- automated-tests/src/dali-devel/CMakeLists.txt | 1 + .../src/dali-devel/utc-Dali-WeakHandle.cpp | 378 +++++++++++++++++++++ dali/devel-api/file.list | 4 +- dali/devel-api/object/weak-handle.cpp | 135 ++++++++ dali/devel-api/object/weak-handle.h | 220 ++++++++++++ 5 files changed, 737 insertions(+), 1 deletion(-) create mode 100644 automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp create mode 100644 dali/devel-api/object/weak-handle.cpp create mode 100644 dali/devel-api/object/weak-handle.h diff --git a/automated-tests/src/dali-devel/CMakeLists.txt b/automated-tests/src/dali-devel/CMakeLists.txt index a63f773..dbd5168 100644 --- a/automated-tests/src/dali-devel/CMakeLists.txt +++ b/automated-tests/src/dali-devel/CMakeLists.txt @@ -23,6 +23,7 @@ SET(TC_SOURCES utc-Dali-SignalDelegate.cpp utc-Dali-Scripting.cpp utc-Dali-Shader.cpp + utc-Dali-WeakHandle.cpp ) LIST(APPEND TC_SOURCES diff --git a/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp b/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp new file mode 100644 index 0000000..fedb2e1 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed 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. + * + */ + +#include +#include +#include + +using namespace Dali; + +namespace +{ + +/******************************************************************************* + * + * Custom Actor + * + ******************************************************************************/ +namespace Impl +{ +struct MyTestCustomActor : public CustomActorImpl +{ + typedef Signal< void ()> SignalType; + typedef Signal< void (float)> SignalTypeFloat; + + MyTestCustomActor() : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS ) ) + { } + + virtual ~MyTestCustomActor() + { } + + void ResetCallStack() + { + } + + // From CustomActorImpl + virtual void OnStageConnection( int depth ) + { + } + virtual void OnStageDisconnection() + { + } + virtual void OnChildAdd(Actor& child) + { + } + virtual void OnChildRemove(Actor& child) + { + } + virtual void OnSizeSet(const Vector3& targetSize) + { + } + virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize) + { + } + virtual bool OnTouchEvent(const TouchEvent& event) + { + return true; + } + virtual bool OnHoverEvent(const HoverEvent& event) + { + return true; + } + virtual bool OnWheelEvent(const WheelEvent& event) + { + return true; + } + virtual bool OnKeyEvent(const KeyEvent& event) + { + return true; + } + virtual void OnKeyInputFocusGained() + { + } + virtual void OnKeyInputFocusLost() + { + } + virtual Vector3 GetNaturalSize() + { + return Vector3( 0.0f, 0.0f, 0.0f ); + } + + virtual float GetHeightForWidth( float width ) + { + return 0.0f; + } + + virtual float GetWidthForHeight( float height ) + { + return 0.0f; + } + + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) + { + } + + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) + { + } + + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) + { + } + + virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) + { + return 0.0f; + } + + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) + { + } + + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) + { + return false; + } + +public: + + SignalType mSignal; +}; + +}; // namespace Impl + +class MyTestCustomActor : public CustomActor +{ +public: + + typedef Signal< void ()> SignalType; + typedef Signal< void (float)> SignalTypeFloat; + + MyTestCustomActor() + { + } + + static MyTestCustomActor New() + { + Impl::MyTestCustomActor* p = new Impl::MyTestCustomActor; + return MyTestCustomActor( *p ); // takes ownership + } + + virtual ~MyTestCustomActor() + { + } + + static MyTestCustomActor DownCast( BaseHandle handle ) + { + MyTestCustomActor result; + + CustomActor custom = Dali::CustomActor::DownCast( handle ); + if ( custom ) + { + CustomActorImpl& customImpl = custom.GetImplementation(); + + Impl::MyTestCustomActor* impl = dynamic_cast(&customImpl); + + if (impl) + { + result = MyTestCustomActor(customImpl.GetOwner()); + } + } + + return result; + } + + SignalType& GetCustomSignal() + { + Dali::RefObject& obj = GetImplementation(); + return static_cast( obj ).mSignal; + } + + MyTestCustomActor(Internal::CustomActor* internal) + : CustomActor(internal) + { + } + + MyTestCustomActor( Impl::MyTestCustomActor& impl ) + : CustomActor( impl ) + { + } +}; + +} + +int UtcDaliWeakHandleBaseConstructorVoid(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase()"); + + WeakHandleBase object; + + DALI_TEST_CHECK(!object.GetBaseHandle()); + + END_TEST; +} + +int UtcDaliWeakHandleBaseConstructorWithHandle(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase(Handle)"); + + Handle emptyHandle; + WeakHandleBase emptyObject(emptyHandle); + DALI_TEST_CHECK(!emptyObject.GetBaseHandle()); + + Actor actor = Actor::New(); + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + END_TEST; +} + +int UtcDaliWeakHandleBaseCopyConstructor(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase(const WeakHandleBase&)"); + + Actor actor = Actor::New(); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase copy(object); + DALI_TEST_CHECK(copy.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + END_TEST; +} + +int UtcDaliWeakHandleBaseAssignmentOperator(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::operator="); + + Actor actor = Actor::New(); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase copy = object; + DALI_TEST_CHECK(copy.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + END_TEST; +} + +int UtcDaliWeakHandleBaseEqualityOperatorP(void) +{ + TestApplication application; + tet_infoline("Positive Test Dali::WeakHandleBase::operator=="); + + WeakHandleBase object; + WeakHandleBase theSameObject; + DALI_TEST_CHECK(object == theSameObject); + + Actor actor = Actor::New(); + + object = WeakHandleBase(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + theSameObject = object; + DALI_TEST_CHECK(theSameObject.GetBaseHandle() == actor); + DALI_TEST_CHECK(object == theSameObject); + + END_TEST; +} + +int UtcDaliWeakHandleBaseEqualityOperatorN(void) +{ + TestApplication application; + tet_infoline("Negative Test Dali::WeakHandleBase::operator=="); + + Actor actor = Actor::New(); + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + Actor differentActor = Actor::New(); + WeakHandleBase aDifferentWeakHandleBase(differentActor); + + DALI_TEST_CHECK(!(object == aDifferentWeakHandleBase)); + + END_TEST; +} + +int UtcDaliWeakHandleBaseInequalityOperatorP(void) +{ + TestApplication application; + tet_infoline("Positive Test Dali::WeakHandleBase::operator!="); + + Actor actor = Actor::New(); + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + Actor differentActor = Actor::New(); + WeakHandleBase aDifferentWeakHandleBase(differentActor); + + DALI_TEST_CHECK(object != aDifferentWeakHandleBase); + END_TEST; +} + +int UtcDaliWeakHandleBaseInequalityOperatorN(void) +{ + TestApplication application; + tet_infoline("Negative Test Dali::WeakHandleBase::operator!="); + + Actor actor = Actor::New(); + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + WeakHandleBase theSameWeakHandleBase = object; + + DALI_TEST_CHECK(!(object != theSameWeakHandleBase)); + END_TEST; +} + +int UtcDaliWeakHandleBaseGetBaseHandle(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::GetBaseHandle()"); + + Handle emptyHandle; + WeakHandleBase emptyObject(emptyHandle); + DALI_TEST_CHECK(!emptyObject.GetBaseHandle()); + + Actor actor = Actor::New(); + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + WeakHandleBase theSameObject = WeakHandleBase(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == theSameObject.GetBaseHandle()); + + Actor differentActor = Actor::New(); + WeakHandleBase aDifferentWeakHandleBase(differentActor); + DALI_TEST_CHECK(object.GetBaseHandle() != aDifferentWeakHandleBase.GetBaseHandle()); + + END_TEST; +} + +int UtcDaliWeakHandleGetHandle(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandle::GetHandle()"); + + Actor actor = Actor::New(); + WeakHandle object(actor); + DALI_TEST_CHECK(object.GetHandle() == actor); + + MyTestCustomActor customActor = MyTestCustomActor::New(); + WeakHandle customObject(customActor); + DALI_TEST_CHECK(customObject.GetHandle() == customActor); + + DALI_TEST_CHECK(object.GetHandle() != customObject.GetHandle()); + + END_TEST; +} + + + diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list index 967fc28..5186f52 100644 --- a/dali/devel-api/file.list +++ b/dali/devel-api/file.list @@ -9,6 +9,7 @@ devel_api_src_files = \ $(devel_api_src_dir)/images/atlas.cpp \ $(devel_api_src_dir)/images/distance-field.cpp \ $(devel_api_src_dir)/object/property-buffer.cpp \ + $(devel_api_src_dir)/object/weak-handle.cpp \ $(devel_api_src_dir)/rendering/cull-face.cpp \ $(devel_api_src_dir)/rendering/geometry.cpp \ $(devel_api_src_dir)/rendering/material.cpp \ @@ -40,7 +41,8 @@ devel_api_core_images_header_files = \ devel_api_core_object_header_files = \ $(devel_api_src_dir)/object/property-buffer.h \ - $(devel_api_src_dir)/object/type-registry-helper.h + $(devel_api_src_dir)/object/type-registry-helper.h \ + $(devel_api_src_dir)/object/weak-handle.h devel_api_core_rendering_header_files = \ $(devel_api_src_dir)/rendering/cull-face.h \ diff --git a/dali/devel-api/object/weak-handle.cpp b/dali/devel-api/object/weak-handle.cpp new file mode 100644 index 0000000..94bb88f --- /dev/null +++ b/dali/devel-api/object/weak-handle.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +struct WeakHandleBase::Impl : public Internal::Object::Observer +{ + // Construction + Impl() + : mObject( NULL ) + { + } + + // Construction + Impl( Handle& handle ) + : mObject( NULL ) + { + if(handle) + { + mObject = static_cast( handle.GetObjectPtr() ); + if(mObject) + { + mObject->AddObserver( *this ); + } + } + } + + // Destruction + ~Impl() + { + if( mObject ) + { + mObject->RemoveObserver( *this ); + } + } + + /** + * From Object::Observer + */ + virtual void SceneObjectAdded( Internal::Object& object ) + { + } + + /** + * From Object::Observer + */ + virtual void SceneObjectRemoved( Internal::Object& object ) + { + } + + /** + * From Object::Observer + */ + virtual void ObjectDestroyed( Internal::Object& object ) + { + mObject = NULL; + } + + // Data + Internal::Object* mObject; +}; + +WeakHandleBase::WeakHandleBase() +: mImpl( new Impl() ) +{ +} + +WeakHandleBase::WeakHandleBase( Handle& handle ) +: mImpl( new Impl( handle ) ) +{ +} + +WeakHandleBase::~WeakHandleBase() +{ + delete mImpl; + mImpl = NULL; +} + +WeakHandleBase::WeakHandleBase(const WeakHandleBase& handle) +: mImpl( NULL ) +{ + Handle object = handle.GetBaseHandle(); + mImpl = new Impl(object); +} + +WeakHandleBase& WeakHandleBase::operator=( const WeakHandleBase& rhs ) +{ + if( this != &rhs ) + { + delete mImpl; + + Handle handle = rhs.GetBaseHandle(); + mImpl = new Impl(handle); + } + + return *this; +} + +bool WeakHandleBase::operator==( const WeakHandleBase& rhs ) const +{ + return this->mImpl->mObject == rhs.mImpl->mObject; +} + +bool WeakHandleBase::operator!=( const WeakHandleBase& rhs ) const +{ + return !( *this == rhs ); +} + +Handle WeakHandleBase::GetBaseHandle() const +{ + return Handle( mImpl->mObject ); +} + +} // Dali diff --git a/dali/devel-api/object/weak-handle.h b/dali/devel-api/object/weak-handle.h new file mode 100644 index 0000000..2e24758 --- /dev/null +++ b/dali/devel-api/object/weak-handle.h @@ -0,0 +1,220 @@ +#ifndef __DALI_WEAK_HANDLE_H__ +#define __DALI_WEAK_HANDLE_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed 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. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +/** + * @brief Base class to store a weak pointer to an internal Dali object. The handle to the object + * can be accessed if the object exists, and such access is not reference counted. When the object + * is deleted, the weak pointer will be set to NULL, and any further attmpt to access to a deleted + * object will return an empty handle. + * + */ +class DALI_IMPORT_API WeakHandleBase +{ + +public: + + /** + * @brief Default constructor which provides an uninitialized Dali::WeakHandleBase. + */ + WeakHandleBase(); + + /** + * @brief This constructor creates a weak handle of the Dali object. + * + * @param [in] handle A reference to the handle of the Dali object. + */ + WeakHandleBase( Handle& handle ); + + /** + * @brief Destructor to free resources. + */ + ~WeakHandleBase(); + + /** + * @brief Copy constructor. + * + * @param [in] handle A reference to the copied WeakHandleBase + */ + WeakHandleBase(const WeakHandleBase& handle); + + /** + * @brief Assignment operator. + * + * It makes this WeakHandleBase point to the same internal Dali object as the copied WeakHandleBase + * @param [in] rhs A reference to the copied WeakHandleBase + * @return A reference to this WeakHandleBase + */ + WeakHandleBase& operator=( const WeakHandleBase& rhs ); + + /** + * @brief Equality operator overload. + * + * @param [in] rhs A reference to the compared WeakHandleBase. + * @return true if the handle points to the same Dali resource, or if both are uninitialized. + */ + bool operator==(const WeakHandleBase& rhs) const; + + /** + * @brief Inequality operator overload. + * + * @param [in] rhs A reference to the compared WeakHandleBase. + * @return true if the handle points to the different Dali resources. + */ + bool operator!=(const WeakHandleBase& rhs) const; + + /** + * @brief Gets the handle to the Dali object. + * + * @return The handle of the Dali object pointed by this WeakHandleBase or an empty handle if the Dali object doesn't exist. + */ + Handle GetBaseHandle() const; + +protected: + + struct Impl; + Impl* mImpl; +}; + +/** + * @brief Type CustomActors support + */ +template +struct CustomActors +{ + /** + * This flag tells Dali if a class is derived from CustomActor. + */ + enum { IS_CUSTOM_ACTOR = __is_base_of(Dali::CustomActor, Type) }; +}; + +template +struct TypeCustomActors : public CustomActors< Type > +{ +}; + +template < bool CustomActorType > +class InternalTypeName +{ +public: // Typedefs + + typedef Dali::Internal::CustomActor InternalObjectType; +}; + +template <> +class InternalTypeName< false > +{ +public: // Typedefs + + typedef Dali::Internal::Actor InternalObjectType; +}; + +/** + * @brief Weak handle for the given type of Dali object. + */ +template < class T > +class WeakHandle : public WeakHandleBase +{ +public: // Typedefs + + typedef typename InternalTypeName< TypeCustomActors::IS_CUSTOM_ACTOR >::InternalObjectType InternalObjectType; + +public: + + /** + * @copydoc Dali::WeakHandleBase::WeakHandleBase() + */ + WeakHandle() + : WeakHandleBase() + { + } + + /** + * @copydoc Dali::WeakHandleBase::WeakHandleBase(Handle&) + */ + WeakHandle( T& handle ) + : WeakHandleBase( handle ) + { + } + + /** + * @copydoc Dali::WeakHandleBase::~WeakHandleBase() + */ + ~WeakHandle() {} + + /** + * @copydoc Dali::WeakHandleBase::WeakHandleBase(const WeakHandleBase&) + */ + WeakHandle(const WeakHandle& handle) + : WeakHandleBase( handle ) + { + } + + /** + * @copydoc Dali::WeakHandleBase::operator=() + */ + WeakHandle& operator=( const WeakHandle& rhs ) + { + WeakHandleBase::operator=(rhs); + return *this; + } + + /** + * @copydoc Dali::WeakHandleBase::operator==() + */ + bool operator==(const WeakHandle& rhs) const + { + return WeakHandleBase::operator==(rhs); + } + + /** + * @copydoc Dali::WeakHandleBase::operator!=() + */ + bool operator!=(const WeakHandle& rhs) const + { + return WeakHandleBase::operator!=(rhs); + } + + /** + * @copydoc Dali::WeakHandleBase::GetHandle() + */ + T GetHandle() + { + Handle handle( GetBaseHandle() ); + if( handle ) + { + return T( reinterpret_cast< InternalObjectType* >( handle.GetObjectPtr() ) ); + } + else + { + return T(); + } + } +}; + +} // namespace Dali + +#endif // __DALI_WEAK_HANDLE_H__ -- 2.7.4