Add BaseObjectObserver 31/317331/4
authorYoungsun Suh <youngsun.suh@samsung.com>
Wed, 4 Sep 2024 01:59:32 +0000 (10:59 +0900)
committerYoungsun Suh <youngsun.suh@samsung.com>
Mon, 9 Sep 2024 06:58:02 +0000 (15:58 +0900)
Change-Id: I414126bece5aeb685835c1efa7c6ab8fba9ee67e

automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/utc-Dali-BaseObjectObserver.cpp [new file with mode: 0644]
dali/devel-api/file.list
dali/devel-api/object/base-object-observer.cpp [new file with mode: 0644]
dali/devel-api/object/base-object-observer.h [new file with mode: 0644]

index f7cdf6ea9550793e6ea2a72115767884824e999d..aa77e33177dbecc04072c930463b38684b97c635 100644 (file)
@@ -13,6 +13,7 @@ SET(TC_SOURCES
         utc-Dali-Animation.cpp
         utc-Dali-Any.cpp
         utc-Dali-BaseHandle.cpp
+        utc-Dali-BaseObjectObserver.cpp
         utc-Dali-CameraActor.cpp
         utc-Dali-CircularQueue.cpp
         utc-Dali-Common.cpp
diff --git a/automated-tests/src/dali/utc-Dali-BaseObjectObserver.cpp b/automated-tests/src/dali/utc-Dali-BaseObjectObserver.cpp
new file mode 100644 (file)
index 0000000..71fca12
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2024 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 <dali-test-suite-utils.h>
+#include <dali/devel-api/object/base-object-observer.h>
+#include <functional>
+
+using namespace Dali;
+
+namespace
+{
+
+class TestBaseObjectObserver : public BaseObjectObserver
+{
+public:
+  TestBaseObjectObserver(Actor actor)
+  : BaseObjectObserver(actor) {}
+
+  void ObjectDestroyed() override
+  {
+    objectDestroyed = true;
+    if(mCallback)
+    {
+      mCallback();
+      callbackCalled = true;
+    }
+  }
+
+  void SetCallback(std::function<void()> callback)
+  {
+    mCallback = std::move(callback);
+  }
+
+  bool objectDestroyed{false};
+  bool callbackCalled{false};
+
+private:
+  std::function<void()> mCallback;
+};
+
+} // anonymous namespace
+
+
+int UtcDaliBaseObjectObserverObjectDestroyedCalledOnObjectDestruction(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  TestBaseObjectObserver observer(actor);
+  DALI_TEST_CHECK(!observer.objectDestroyed);
+
+  observer.StartObservingDestruction();
+  observer.StartObservingDestruction(); // Test app does not crash when calling Start twice
+  DALI_TEST_CHECK(!observer.objectDestroyed);
+
+  actor.Reset();
+  DALI_TEST_CHECK(observer.objectDestroyed);
+  DALI_TEST_CHECK(!observer.callbackCalled);
+
+  END_TEST;
+}
+
+int UtcDaliBaseObjectObserverObjectDestroyedIsNotCalledIfObserverStopped(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  TestBaseObjectObserver observer(actor);
+  DALI_TEST_CHECK(!observer.objectDestroyed);
+
+  observer.StartObservingDestruction();
+  DALI_TEST_CHECK(!observer.objectDestroyed);
+  observer.StopObservingDestruction();
+  observer.StopObservingDestruction(); // Test app does not crash when calling Stop twice
+
+  actor.Reset();
+  DALI_TEST_CHECK(!observer.objectDestroyed);
+  DALI_TEST_CHECK(!observer.callbackCalled);
+
+  END_TEST;
+}
+
+int UtcDaliBaseObjectObserverObjectDestroyedIsNotCalledIfObserverNotStarted(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  TestBaseObjectObserver observer(actor);
+  DALI_TEST_CHECK(!observer.objectDestroyed);
+
+  actor.Reset();
+  DALI_TEST_CHECK(!observer.objectDestroyed);
+  DALI_TEST_CHECK(!observer.callbackCalled);
+
+  END_TEST;
+}
+
+int UtcDaliBaseObjectObserverRecursiveStart(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  TestBaseObjectObserver observer(actor);
+  observer.SetCallback([&observer] {
+    observer.StartObservingDestruction();
+  });
+
+  observer.StartObservingDestruction();
+
+  actor.Reset();
+  DALI_TEST_CHECK(observer.objectDestroyed);
+  DALI_TEST_CHECK(observer.callbackCalled);
+
+  END_TEST;
+}
+
+int UtcDaliBaseObjectObserverRecursiveStop(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  TestBaseObjectObserver observer(actor);
+  observer.SetCallback([&observer] {
+    observer.StopObservingDestruction();
+  });
+
+  observer.StartObservingDestruction();
+
+  actor.Reset();
+  DALI_TEST_CHECK(observer.objectDestroyed);
+  DALI_TEST_CHECK(observer.callbackCalled);
+
+  END_TEST;
+}
index aeed9793c574f865acd74ac571028b9bd7b8f5b3..fe6ebda83b675557e1e90c4eaa0750aa011f0c89 100644 (file)
@@ -31,6 +31,7 @@ SET( devel_api_src_files
   ${devel_api_src_dir}/images/distance-field.cpp
   ${devel_api_src_dir}/object/handle-devel.cpp
   ${devel_api_src_dir}/object/csharp-type-registry.cpp
+  ${devel_api_src_dir}/object/base-object-observer.cpp
   ${devel_api_src_dir}/rendering/frame-buffer-devel.cpp
   ${devel_api_src_dir}/rendering/renderer-devel.cpp
   ${devel_api_src_dir}/rendering/texture-devel.cpp
@@ -104,6 +105,7 @@ SET( devel_api_core_images_header_files
 
 
 SET( devel_api_core_object_header_files
+  ${devel_api_src_dir}/object/base-object-observer.h
   ${devel_api_src_dir}/object/csharp-type-info.h
   ${devel_api_src_dir}/object/csharp-type-registry.h
   ${devel_api_src_dir}/object/handle-devel.h
diff --git a/dali/devel-api/object/base-object-observer.cpp b/dali/devel-api/object/base-object-observer.cpp
new file mode 100644 (file)
index 0000000..494d1fa
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 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/object/base-object-observer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/base-object-impl.h>
+
+namespace Dali
+{
+class BaseObjectObserver::Impl : public BaseObject::Impl::Observer
+{
+public:
+explicit Impl(const BaseHandle& handle)
+  {
+    if(handle)
+    {
+      mObject = static_cast<Dali::BaseObject*>(handle.GetObjectPtr());
+    }
+  }
+
+  ~Impl() override
+  {
+    Stop();
+  }
+
+  void Start(BaseObjectObserver *observerBase)
+  {
+    if (mObject && !mObserverBase && observerBase)
+    {
+      mObserverBase = observerBase;
+      BaseObject::Impl::Get(*mObject).AddObserver(*this);
+    }
+  }
+
+  void Stop()
+  {
+    if(mObject && mObserverBase)
+    {
+      BaseObject::Impl::Get(*mObject).RemoveObserver(*this);
+      mObserverBase = nullptr;
+    }
+  }
+
+  /**
+   * From BaseObject::Impl::Observer
+   */
+  void ObjectDestroyed(BaseObject&) override
+  {
+    mObject = nullptr;
+    mObserverBase->ObjectDestroyed();
+  }
+
+private:
+  Dali::BaseObject* mObject{nullptr};
+  BaseObjectObserver* mObserverBase{nullptr};
+};
+
+BaseObjectObserver::BaseObjectObserver(const BaseHandle& handle)
+: mImpl{std::make_unique<BaseObjectObserver::Impl>(handle)}
+{
+}
+
+BaseObjectObserver::~BaseObjectObserver() = default;
+
+void BaseObjectObserver::StartObservingDestruction()
+{
+  mImpl->Start(this);
+}
+
+void BaseObjectObserver::StopObservingDestruction()
+{
+  mImpl->Stop();
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/object/base-object-observer.h b/dali/devel-api/object/base-object-observer.h
new file mode 100644 (file)
index 0000000..30b110b
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef DALI_BASE_OBJECT_OBSERVER_H
+#define DALI_BASE_OBJECT_OBSERVER_H
+
+/*
+ * Copyright (c) 2024 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 <dali/public-api/object/base-handle.h>
+#include <memory>
+
+namespace Dali
+{
+/**
+ * @brief Base class to provide observer interface for BaseOject destruction  store a weak pointer to an internal DALi object.
+ */
+class DALI_CORE_API BaseObjectObserver
+{
+public:
+  /**
+   * @brief The constructor initializes observer for given DALi object.
+   * @param [in] handle A reference to the handle of the DALi object
+   */
+  explicit BaseObjectObserver(const BaseHandle& handle);
+  virtual ~BaseObjectObserver();
+
+  /**
+   * @brief Starts observing destruction of the registered object.
+   */
+  void StartObservingDestruction();
+
+  /**
+   * @brief Stops observing destruction of the registered object.
+   */
+  void StopObservingDestruction();
+
+  /**
+   * @brief Called shortly before the object itself is destroyed.
+   */
+  virtual void ObjectDestroyed() = 0;
+
+  // deleted constructors and operators
+  BaseObjectObserver(const BaseObjectObserver& handle) = delete;
+  BaseObjectObserver& operator=(const BaseObjectObserver& rhs) = delete;
+  BaseObjectObserver(BaseObjectObserver&& rhs) = delete;
+  BaseObjectObserver& operator=(BaseObjectObserver&& rhs) = delete;
+
+private:
+  /// @cond internal
+  struct Impl;
+  std::unique_ptr<Impl> mImpl;
+  /// @endcond
+};
+
+} // namespace Dali
+
+#endif // DALI_BASE_OBJECT_OBSERVER_H