From: Paul Wisbey Date: Mon, 17 Feb 2020 16:28:52 +0000 (+0000) Subject: Moved SingletonService into dali-core X-Git-Tag: dali_1.9.1~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-core.git;a=commitdiff_plain;h=8c46e3360d6c14675bc001806e1acf32affd17c1 Moved SingletonService into dali-core Change-Id: I72649695560fa6acafbdeb5f48df61c7d4c75509 --- diff --git a/automated-tests/src/dali/CMakeLists.txt b/automated-tests/src/dali/CMakeLists.txt index 169f2d1..6db6c25 100644 --- a/automated-tests/src/dali/CMakeLists.txt +++ b/automated-tests/src/dali/CMakeLists.txt @@ -89,6 +89,7 @@ SET(TC_SOURCES utc-Dali-SignalDelegate.cpp utc-Dali-SignalTemplatesFunctors.cpp utc-Dali-SignalTemplates.cpp + utc-Dali-SingletonService.cpp utc-Dali-Stage.cpp utc-Dali-TapGesture.cpp utc-Dali-TapGestureDetector.cpp diff --git a/automated-tests/src/dali/utc-Dali-SingletonService.cpp b/automated-tests/src/dali/utc-Dali-SingletonService.cpp new file mode 100644 index 0000000..21087cd --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-SingletonService.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 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. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ + +class TestHandle : public BaseHandle +{ +public: + TestHandle() {} + TestHandle( BaseObject* object ) : BaseHandle( object ) {} +}; + +class TestObject : public BaseObject +{ +}; + +} // unnamed namespace + +void utc_dali_singleton_service_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_singleton_service_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliSingletonServiceGet(void) +{ + // Attempt to retrieve SingletonService before creating application + SingletonService singletonService; + singletonService = SingletonService::Get(); + DALI_TEST_CHECK( !singletonService ); + + // Create Application class, should be able to retrieve SingletonService now + TestApplication application; + singletonService = SingletonService::Get(); + DALI_TEST_CHECK( singletonService ); + + END_TEST; +} + +int UtcDaliSingletonServiceRegisterAndGetSingleton(void) +{ + TestApplication application; + SingletonService singletonService( SingletonService::Get() ); + + // Attempt to register an empty handle + TestHandle handle; + singletonService.Register( typeid( handle ), handle ); + DALI_TEST_CHECK( !singletonService.GetSingleton( typeid( handle ) ) ); + + // Create an actor instance and retrieve, should be valid this time + handle = TestHandle( new TestObject ); + singletonService.Register( typeid( handle ), handle ); + DALI_TEST_CHECK( singletonService.GetSingleton( typeid( handle ) ) ); + + END_TEST; +} diff --git a/dali/devel-api/common/singleton-service.cpp b/dali/devel-api/common/singleton-service.cpp new file mode 100644 index 0000000..715e3ed --- /dev/null +++ b/dali/devel-api/common/singleton-service.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 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 +{ + +SingletonService::SingletonService() +{ +} + +SingletonService SingletonService::Get() +{ + return Internal::ThreadLocalStorage::GetSingletonService(); +} + +SingletonService::~SingletonService() +{ +} + +void SingletonService::Register( const std::type_info& info, BaseHandle singleton ) +{ + GetImplementation( *this ).Register( info, singleton ); +} + +void SingletonService::UnregisterAll() +{ + GetImplementation( *this ).UnregisterAll(); +} + +BaseHandle SingletonService::GetSingleton( const std::type_info& info ) const +{ + return GetImplementation( *this ).GetSingleton( info ); +} + +SingletonService::SingletonService( Internal::ThreadLocalStorage* tls ) +: BaseHandle( tls ) +{ +} + +} // namespace Dali diff --git a/dali/devel-api/common/singleton-service.h b/dali/devel-api/common/singleton-service.h new file mode 100755 index 0000000..7677487 --- /dev/null +++ b/dali/devel-api/common/singleton-service.h @@ -0,0 +1,104 @@ +#ifndef DALI_SINGELTON_SERVICE_H +#define DALI_SINGELTON_SERVICE_H + +/* + * Copyright (c) 2020 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. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class ThreadLocalStorage; +} + +/** + * @brief Allows the registration of a class as a singleton + * + * @note This class is created by the Application class and is destroyed when the Application class is destroyed. + * + * @see Application + */ +class DALI_CORE_API SingletonService : public BaseHandle +{ +public: + + /** + * @brief Create an uninitialized handle. + * + * This can be initialized by calling SingletonService::Get(). + */ + SingletonService(); + + /** + * @brief Retrieves a handle to the SingletonService. + * + * @return A handle to the SingletonService if it is available. This will be an empty handle if + * the service is not available. + */ + static SingletonService Get(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~SingletonService(); + + /** + * @brief Registers the singleton of Dali handle with its type info. + * + * The singleton will be kept alive for the lifetime of the service. + * + * @note This is not intended for application developers. + * @param[in] info The type info of the Dali handle generated by the compiler. + * @param[in] singleton The Dali handle to be registered + */ + void Register( const std::type_info& info, BaseHandle singleton ); + + /** + * @brief Unregisters all singletons. + * + * @note This is not intended for application developers. + */ + void UnregisterAll(); + + /** + * @brief Gets the singleton for the given type. + * + * @note This is not intended for application developers. + * @param[in] info The type info of the given type. + * @return the Dali handle if it is registered as a singleton or an uninitialized handle. + */ + BaseHandle GetSingleton( const std::type_info& info ) const; + +public: // Not intended for application developers + + /** + * @brief This constructor is used by SingletonService::Get(). + * @param[in] singletonService A pointer to the internal singleton-service object. + */ + explicit DALI_INTERNAL SingletonService( Internal::ThreadLocalStorage* singletonService ); +}; + +} // namespace Dali + +#endif // DALI_SINGELTON_SERVICE_H diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list index 78f1aab..5ac372f 100644 --- a/dali/devel-api/file.list +++ b/dali/devel-api/file.list @@ -9,6 +9,7 @@ SET( devel_api_src_files ${devel_api_src_dir}/animation/animation-devel.cpp ${devel_api_src_dir}/animation/path-constrainer.cpp ${devel_api_src_dir}/common/hash.cpp + ${devel_api_src_dir}/common/singleton-service.cpp ${devel_api_src_dir}/common/stage-devel.cpp ${devel_api_src_dir}/events/hit-test-algorithm.cpp ${devel_api_src_dir}/events/long-press-gesture-detector-devel.cpp @@ -52,6 +53,7 @@ SET( devel_api_core_common_header_files ${devel_api_src_dir}/common/bitwise-enum.h ${devel_api_src_dir}/common/circular-queue.h ${devel_api_src_dir}/common/hash.h + ${devel_api_src_dir}/common/singleton-service.h ${devel_api_src_dir}/common/map-wrapper.h ${devel_api_src_dir}/common/owner-container.h ${devel_api_src_dir}/common/ref-counted-dali-vector.h diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index ac0c500..43f2a2a 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -153,7 +153,7 @@ Core::~Core() if( tls ) { tls->Remove(); - delete tls; + tls->Unreference(); } mObjectRegistry.Reset(); @@ -432,7 +432,8 @@ void Core::CreateThreadLocalStorage() { // a pointer to the ThreadLocalStorage object will be stored in TLS // The ThreadLocalStorage object should be deleted by the Core destructor - new ThreadLocalStorage(this); + ThreadLocalStorage* tls = new ThreadLocalStorage(this); + tls->Reference(); } void Core::RegisterObject( Dali::BaseObject* object ) diff --git a/dali/internal/event/common/thread-local-storage.cpp b/dali/internal/event/common/thread-local-storage.cpp index 8ce6c11..2424d41 100644 --- a/dali/internal/event/common/thread-local-storage.cpp +++ b/dali/internal/event/common/thread-local-storage.cpp @@ -22,6 +22,23 @@ #include #include #include +#include + +#if defined(DEBUG_ENABLED) +#include +Debug::Filter* gSingletonServiceLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_SINGLETON_SERVICE" ); + +// Need to define own macro as the log function is not installed when this object is created so no logging is shown with DALI_LOG_INFO at construction and destruction +#define DALI_LOG_SINGLETON_SERVICE_DIRECT(level, message) \ + if(gSingletonServiceLogFilter && gSingletonServiceLogFilter->IsEnabledFor(level)) { std::string string(message); Dali::TizenPlatform::LogMessage( Debug::DebugInfo, string ); } + +#define DALI_LOG_SINGLETON_SERVICE(level, format, ...) DALI_LOG_INFO(gSingletonServiceLogFilter, level, format, ## __VA_ARGS__ ) +#else + +#define DALI_LOG_SINGLETON_SERVICE_DIRECT(level, message) +#define DALI_LOG_SINGLETON_SERVICE(level, format, ...) + +#endif namespace Dali { @@ -58,6 +75,16 @@ ThreadLocalStorage& ThreadLocalStorage::Get() return *threadLocal; } +Dali::SingletonService ThreadLocalStorage::GetSingletonService() +{ + Dali::SingletonService singletonService; + if ( threadLocal ) + { + singletonService = Dali::SingletonService( threadLocal ); + } + return singletonService; +} + bool ThreadLocalStorage::Created() { // see if the TLS has been set yet @@ -134,6 +161,43 @@ void ThreadLocalStorage::RemoveScene( Scene* scene ) mCore->RemoveScene( scene ); } +void ThreadLocalStorage::Register( const std::type_info& info, BaseHandle singleton ) +{ + if( singleton ) + { + DALI_LOG_SINGLETON_SERVICE( Debug::General, "Singleton Added: %s\n", info.name() ); + mSingletonContainer.push_back( SingletonPair( info.name(), singleton ) ); + + Integration::Processor* processor = dynamic_cast( &singleton.GetBaseObject() ); + if( processor ) + { + mCore->RegisterProcessor( *processor ); + } + } +} + +void ThreadLocalStorage::UnregisterAll( ) +{ + mSingletonContainer.clear(); +} + +BaseHandle ThreadLocalStorage::GetSingleton( const std::type_info& info ) const +{ + BaseHandle object; + + const SingletonContainer::const_iterator end = mSingletonContainer.end(); + for( SingletonContainer::const_iterator iter = mSingletonContainer.begin(); iter != end; ++iter ) + { + // comparing the addresses as these are allocated statically per library + if( ( *iter ).first == info.name() ) + { + object = ( *iter ).second; + } + } + + return object; +} + } // namespace Internal } // namespace Dali diff --git a/dali/internal/event/common/thread-local-storage.h b/dali/internal/event/common/thread-local-storage.h index 448a61f..0335955 100644 --- a/dali/internal/event/common/thread-local-storage.h +++ b/dali/internal/event/common/thread-local-storage.h @@ -18,7 +18,11 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES +#include #include #include @@ -52,7 +56,7 @@ class UpdateManager; * Class to store a pointer to core in thread local storage. * */ -class ThreadLocalStorage +class ThreadLocalStorage : public Dali::BaseObject { public: @@ -64,11 +68,6 @@ public: ThreadLocalStorage(Core* core); /** - * Destructor. - */ - ~ThreadLocalStorage(); - - /** * Remove core pointer. * Prevents the core pointer being automatically deleted when the thread exits. */ @@ -81,6 +80,11 @@ public: static ThreadLocalStorage& Get(); /** + * @copydoc Dali::SingletonService::Get() + */ + static Dali::SingletonService GetSingletonService(); + + /** * Checks if the TLS has been created * @return if the TLS has been created */ @@ -172,14 +176,68 @@ public: */ void RemoveScene( Scene* scene ); + /** + * @copydoc Dali::SingletonService::Register() + */ + void Register( const std::type_info& info, BaseHandle singleton ); + + /** + * @copydoc Dali::SingletonService::UnregisterAll() + */ + void UnregisterAll(); + + /** + * @copydoc Dali::SingletonService::GetSingleton() + */ + BaseHandle GetSingleton( const std::type_info& info ) const; + +private: + + /** + * Virtual Destructor + */ + virtual ~ThreadLocalStorage(); + + // Undefined + ThreadLocalStorage( const ThreadLocalStorage& ); + ThreadLocalStorage& operator=( ThreadLocalStorage& ); + private: Core* mCore; ///< reference to core + // using the address of the type name string as compiler will allocate these once per library + // and we don't support un/re-loading of dali libraries while singleton service is alive + typedef std::pair< const char*, BaseHandle> SingletonPair; + typedef std::vector< SingletonPair > SingletonContainer; + typedef SingletonContainer::const_iterator SingletonConstIter; + + SingletonContainer mSingletonContainer; ///< The container to look up singleton by its type name + }; } // namespace Internal +// Helpers for public-api forwarding methods + +inline Internal::ThreadLocalStorage& GetImplementation(Dali::SingletonService& service) +{ + DALI_ASSERT_ALWAYS( service && "SingletonService handle is empty" ); + + BaseObject& handle = service.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::ThreadLocalStorage& GetImplementation(const Dali::SingletonService& service) +{ + DALI_ASSERT_ALWAYS( service && "SingletonService handle is empty" ); + + const BaseObject& handle = service.GetBaseObject(); + + return static_cast(handle); +} + } // namespace Dali #endif // DALI_INTERNAL_THREAD_LOCAL_STORAGE_H