Moved SingletonService into dali-core 47/225147/6
authorPaul Wisbey <p.wisbey@samsung.com>
Mon, 17 Feb 2020 16:28:52 +0000 (16:28 +0000)
committerPaul Wisbey <p.wisbey@samsung.com>
Mon, 24 Feb 2020 13:41:00 +0000 (13:41 +0000)
Change-Id: I72649695560fa6acafbdeb5f48df61c7d4c75509

automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/utc-Dali-SingletonService.cpp [new file with mode: 0644]
dali/devel-api/common/singleton-service.cpp [new file with mode: 0644]
dali/devel-api/common/singleton-service.h [new file with mode: 0755]
dali/devel-api/file.list
dali/internal/common/core-impl.cpp
dali/internal/event/common/thread-local-storage.cpp
dali/internal/event/common/thread-local-storage.h

index 169f2d1237f9e3265d82efdc2ef6be3b90bcd683..6db6c2589008868cc2f8f5a2a12f45dafc6ed3cc 100644 (file)
@@ -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 (file)
index 0000000..21087cd
--- /dev/null
@@ -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 <stdlib.h>
+#include <iostream>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/common/singleton-service.h>
+
+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 (file)
index 0000000..715e3ed
--- /dev/null
@@ -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 <dali/devel-api/common/singleton-service.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/thread-local-storage.h>
+
+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 (executable)
index 0000000..7677487
--- /dev/null
@@ -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 <typeinfo>
+#include <dali/public-api/object/base-handle.h>
+
+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
index 78f1aabf2d8e21bf1b7222e08c7a4d8df8861e81..5ac372fae5de5a79cc06bd4f910ebae9a03ebf1b 100644 (file)
@@ -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
index ac0c500ec1ea9adf4eb93edca165d594e6773e87..43f2a2afd27c73649a60858f6afb18b4dc722e13 100644 (file)
@@ -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 )
index 8ce6c1113c73f68eefc1182e5711427dcec49a09..2424d41712e32754c85572cd8ac8f357052ffc75 100644 (file)
 #include <dali/internal/common/core-impl.h>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/internal/event/common/event-thread-services.h>
+#include <dali/integration-api/processor-interface.h>
+
+#if defined(DEBUG_ENABLED)
+#include <dali/integration-api/debug.h>
+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<Integration::Processor*>( &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
index 448a61f2bf74eed82892679f7721e866af7181df..0335955527e310b159369c0ac07797a6f576bf83 100644 (file)
  *
  */
 
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
 // INTERNAL INCLUDES
+#include <dali/devel-api/common/singleton-service.h>
 #include <dali/internal/event/common/stage-def.h>
 #include <dali/internal/event/common/scene-impl.h>
 
@@ -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:
 
@@ -63,11 +67,6 @@ public:
    */
   ThreadLocalStorage(Core* core);
 
-  /**
-   * Destructor.
-   */
-  ~ThreadLocalStorage();
-
   /**
    * Remove core pointer.
    * Prevents the core pointer being automatically deleted when the thread exits.
@@ -80,6 +79,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<Internal::ThreadLocalStorage&>(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<const Internal::ThreadLocalStorage&>(handle);
+}
+
 } // namespace Dali
 
 #endif // DALI_INTERNAL_THREAD_LOCAL_STORAGE_H