Assert to add / remove observer during notifying 26/310026/7
authorEunki, Hong <eunkiki.hong@samsung.com>
Fri, 19 Apr 2024 09:25:16 +0000 (18:25 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 9 May 2024 00:31:34 +0000 (09:31 +0900)
Let we assert the cases when observer list try to be changed during notifying.

But, allow to remove observer during notifying, only for Object cases.

Until now, we just change the observer list directly, so if notifying, then
memory corruption occured.

To avoid this case, follow as ProcessorInterface did, copy the observer lists
and check whether it is valid or not, only if somebody touch original list.

Note : For BaseObject::Impl case, it is not opened
and it didn't send notify when scene on/off.
The only observer for BaseObject::Impl is WeakHandle. and OnDestroy() didnt'
send callback that timing.

Note2 : PropertyOwner case, it is also only for update-render thread for DALi.
We can control that non of callback change the observers for this thing.

So let we assume BaseObject::Impl::RemoveObserver and
PropertyOwner::RemoveObserver will not be called
during desturct object.

TODO : Should we also control Object::RemoveObserver case?
TODO : Should we remove observer copy?

Change-Id: Ia373243bdaae83613b1b91680a77b86409977028
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
16 files changed:
dali/internal/event/common/base-object-impl.cpp
dali/internal/event/common/base-object-impl.h
dali/internal/event/common/object-impl.cpp
dali/internal/event/common/object-impl.h
dali/internal/event/events/hover-event-processor.cpp
dali/internal/update/animation/scene-graph-animator.h
dali/internal/update/animation/scene-graph-constraint-base.h
dali/internal/update/common/node-resetter.h
dali/internal/update/common/property-owner.cpp
dali/internal/update/common/property-owner.h
dali/internal/update/common/property-resetter.h
dali/internal/update/common/renderer-resetter.h
dali/internal/update/manager/scene-graph-frame-callback.h
dali/internal/update/manager/scene-graph-traveler.h
dali/internal/update/render-tasks/scene-graph-render-task.cpp
dali/internal/update/render-tasks/scene-graph-render-task.h

index 0beeb26b7806139a821f05b9322ff1f7a74ffa2e..4d9e9eb5295de957879fcd936ecc97d7f5c6cd8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
 namespace Dali
 {
 BaseObject::Impl::Impl(BaseObject& baseObject)
-: mBaseObject(baseObject)
+: mBaseObject(baseObject),
+  mObservers(),
+  mObserverNotifying(false)
 {
 }
 
 BaseObject::Impl::~Impl()
 {
+  // Guard Add/Remove observer during observer notifying.
+  mObserverNotifying = true;
+
   // Notification for observers
   for(auto&& item : mObservers)
   {
     item->ObjectDestroyed(mBaseObject);
   }
+
+  // Note : We don't need to restore mObserverNotifying to false as we are in delete the object.
+  // If someone call AddObserver / RemoveObserver after this, assert.
+
+  // Remove all observers
+  mObservers.Clear();
 }
 
 BaseObject::Impl& BaseObject::Impl::Get(BaseObject& baseObject)
@@ -46,6 +57,8 @@ const BaseObject::Impl& BaseObject::Impl::Get(const BaseObject& baseObject)
 
 void BaseObject::Impl::AddObserver(Observer& observer)
 {
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Cannot add observer while notifying BaseObject::Impl::Observers");
+
   // make sure an observer doesn't observe the same object twice
   // otherwise it will get multiple calls to ObjectDestroyed()
   DALI_ASSERT_DEBUG(mObservers.End() == std::find(mObservers.Begin(), mObservers.End(), &observer));
@@ -55,6 +68,8 @@ void BaseObject::Impl::AddObserver(Observer& observer)
 
 void BaseObject::Impl::RemoveObserver(Observer& observer)
 {
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Cannot remove observer while notifying BaseObject::Impl::Observers");
+
   // Find the observer...
   const auto endIter = mObservers.End();
   for(auto iter = mObservers.Begin(); iter != endIter; ++iter)
index 7b95b8757646e6cd6d62f222382770a3e9ae0760..8099059e1b8850bd7e0df036e2426488ad3f1de4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_BASE_OBJECT_IMPL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
@@ -84,6 +84,8 @@ public:
 private:
   BaseObject&             mBaseObject;
   Dali::Vector<Observer*> mObservers;
+
+  bool mObserverNotifying : 1; ///< Whether we are currently notifying observers.
 };
 
 } // namespace Dali
index 5200ac042f330d578d00d9c7324d025910391711..74a788e6a1557c5a1d7ea8ee23383ebd7d31ec93 100644 (file)
@@ -55,6 +55,41 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJ
 
 constexpr Property::Index MAX_PER_CLASS_PROPERTY_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX;
 
+/// Helper to notify observers
+using ObserverNotifyMethod = void (Object::Observer::*)(Object&);
+
+void NotifyObservers(Object& object, Object::ObserverContainer& observers, ObserverNotifyMethod memberFunction)
+{
+  // Guard Add/Remove observer during observer notifying.
+  object.mObserverNotifying = true;
+
+  // Copy observers to prevent changes to vector affecting loop iterator.
+  auto copiedObservers(observers);
+
+  object.mObserverRemoved = false;
+
+  // Notification for observers
+  for(auto&& item : copiedObservers)
+  {
+    if(!object.mObserverRemoved)
+    {
+      (item->*memberFunction)(object);
+    }
+    else
+    {
+      // Notify only if the observer is still in the list.
+      // It may be removed during the loop.
+      auto iter = std::find(observers.Begin(), observers.End(), item);
+      if(iter != observers.End())
+      {
+        (item->*memberFunction)(object);
+      }
+    }
+  }
+
+  object.mObserverNotifying = false;
+}
+
 } // unnamed namespace
 
 IntrusivePtr<Object> Object::New()
@@ -64,6 +99,8 @@ IntrusivePtr<Object> Object::New()
 
 void Object::AddObserver(Observer& observer)
 {
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Cannot add observer while notifying Object::Observers");
+
   // make sure an observer doesn't observe the same object twice
   // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ObjectDestroyed()
   DALI_ASSERT_DEBUG(mObservers.End() == std::find(mObservers.Begin(), mObservers.End(), &observer));
@@ -73,12 +110,16 @@ void Object::AddObserver(Observer& observer)
 
 void Object::RemoveObserver(Observer& observer)
 {
+  // Note : We allow to remove observer during notifying.
+  // TODO : Could we assert during notifying in future?
+
   // Find the observer...
   const auto endIter = mObservers.End();
   for(auto iter = mObservers.Begin(); iter != endIter; ++iter)
   {
     if((*iter) == &observer)
     {
+      mObserverRemoved = true;
       mObservers.Erase(iter);
       break;
     }
@@ -971,17 +1012,23 @@ Object::Object(const SceneGraph::PropertyOwner* sceneObject)
   mUpdateObject(sceneObject),
   mTypeInfo(nullptr),
   mConstraints(nullptr),
-  mPropertyNotifications(nullptr)
+  mPropertyNotifications(nullptr),
+  mObserverNotifying(false),
+  mObserverRemoved(false)
 {
 }
 
 Object::~Object()
 {
-  // Notification for observers
-  for(auto&& item : mObservers)
-  {
-    item->ObjectDestroyed(*this);
-  }
+  NotifyObservers(*this, mObservers, &Object::Observer::ObjectDestroyed);
+
+  // Note : We don't need to restore mObserverNotifying to false as we are in delete the object.
+  // If someone call AddObserver after this, assert.
+  mObserverNotifying = true;
+
+  // Remove all observers
+  mObserverRemoved = true;
+  mObservers.Clear();
 
   // Disable property notifications in scene graph
   DisablePropertyNotifications();
@@ -1001,11 +1048,9 @@ Object::~Object()
 
 void Object::OnSceneObjectAdd()
 {
-  // Notification for observers
-  for(auto&& item : mObservers)
-  {
-    item->SceneObjectAdded(*this);
-  }
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Should not be call OnSceneObjectAdd while notifying observers");
+
+  NotifyObservers(*this, mObservers, &Object::Observer::SceneObjectAdded);
 
   // enable property notifications in scene graph
   EnablePropertyNotifications();
@@ -1013,11 +1058,9 @@ void Object::OnSceneObjectAdd()
 
 void Object::OnSceneObjectRemove()
 {
-  // Notification for observers
-  for(auto&& item : mObservers)
-  {
-    item->SceneObjectRemoved(*this);
-  }
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Should not be call OnSceneObjectRemove while notifying observers");
+
+  NotifyObservers(*this, mObservers, &Object::Observer::SceneObjectRemoved);
 
   // disable property notifications in scene graph
   DisablePropertyNotifications();
index 91143c1cd689a260f51153bd9ea51a5e912826a8..e29089811a1c934ee42f0dbef206e49a6fd8c73c 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_OBJECT_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
@@ -111,6 +111,9 @@ class Object : public Dali::BaseObject
 public:
   using Capability = Dali::Handle::Capability;
 
+  class Observer;
+  using ObserverContainer = Dali::Vector<Observer*>;
+
   class Observer
   {
   public:
@@ -594,7 +597,7 @@ protected:
   mutable const SceneGraph::PropertyOwner* mUpdateObject; ///< Reference to object to hold the scene graph properties
 
 private:
-  Dali::Vector<Observer*>                   mObservers;
+  ObserverContainer                         mObservers;
   mutable OwnerContainer<PropertyMetadata*> mCustomProperties;     ///< Used for accessing custom Node properties
   mutable OwnerContainer<PropertyMetadata*> mAnimatableProperties; ///< Used for accessing animatable Node properties
   mutable const TypeInfo*                   mTypeInfo;             ///< The type-info for this object, mutable so it can be lazy initialized from const method if it is required
@@ -605,6 +608,10 @@ private:
   PropertyNotificationContainer* mPropertyNotifications; ///< Container of owned property notifications.
 
   Handle::PropertySetSignalType mPropertySetSignal;
+
+public:                        /// To be used at observer container changes only.
+  bool mObserverNotifying : 1; ///< Whether we are currently notifying observers.
+  bool mObserverRemoved : 1;   ///< Whether we have removed an observer during notify.
 };
 
 } // namespace Internal
index afe0fa15c59f64e398c907ca64cc867459a166de..18a046917baeadf4ac29f4f519701610b05f64a0 100644 (file)
@@ -405,17 +405,17 @@ struct HoverEventProcessor::Impl
         if(hitActor && processor.mLastPrimaryHitActor.GetActor() != hitActor &&
            localVars.primaryPointState == PointState::MOTION && GetImplementation(hitActor).GetLeaveRequired())
         {
-            // A leave event is sent to the previous actor first.
-            localVars.lastPrimaryHitActor = processor.mLastPrimaryHitActor.GetActor();
-            localVars.lastConsumedActor   = processor.mLastConsumedActor.GetActor();
-            Impl::DeliverLeaveEvent(processor, localVars);
+          // A leave event is sent to the previous actor first.
+          localVars.lastPrimaryHitActor = processor.mLastPrimaryHitActor.GetActor();
+          localVars.lastConsumedActor   = processor.mLastConsumedActor.GetActor();
+          Impl::DeliverLeaveEvent(processor, localVars);
 
-            localVars.hoverEvent->GetPoint(0).SetState(PointState::STARTED);
-            localVars.primaryPointState = PointState::STARTED;
+          localVars.hoverEvent->GetPoint(0).SetState(PointState::STARTED);
+          localVars.primaryPointState = PointState::STARTED;
 
-            // It sends a started event and updates information.
-            localVars.consumedActor = EmitHoverSignals(hitActor, localVars.hoverEventHandle);
-            UpdateMembersWithCurrentHitInformation(processor, localVars);
+          // It sends a started event and updates information.
+          localVars.consumedActor = EmitHoverSignals(hitActor, localVars.hoverEventHandle);
+          UpdateMembersWithCurrentHitInformation(processor, localVars);
         }
         else
         {
index 108446c9dd852dcb7fcca4ad356dff620461e92d..c6d14473d2d5e8e4ac9e6fb7f5852604fd179c56 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -130,7 +130,7 @@ private: // From PropertyOwner::Observer
   /**
    * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
    */
-  void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) final
+  NotifyReturnType PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) final
   {
     // If we are active, then bake the value if required
     if(mAnimationPlaying && mDisconnectAction != Dali::Animation::DISCARD)
@@ -140,6 +140,8 @@ private: // From PropertyOwner::Observer
     }
 
     mEnabled = false;
+
+    return NotifyReturnType::KEEP_OBSERVING;
   }
 
   /**
index 5bab5055924c0d8d3c60cad7e5fe8a2afb643006..6439ec814ac99eb846098044820c48b219c25c44 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -182,18 +182,18 @@ private:
   /**
    * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected()
    */
-  void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
+  NotifyReturnType PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
   {
     if(!mDisconnected)
     {
-      // Stop observing property owners
-      StopObservation();
-
-      // Notification for derived class
-      OnDisconnect();
+      // Call PropertyOwnerDestroyed(), for reduce duplicated code.
+      ConstraintBase::PropertyOwnerDestroyed(owner);
 
-      mDisconnected = true;
+      // Let we make owner Stop observing this.
+      return NotifyReturnType::STOP_OBSERVING;
     }
+
+    return NotifyReturnType::KEEP_OBSERVING;
   }
 
   /**
index f3a41422ea938e51f2b81f5e966435e39c3afb5f..f0e155ef8983ed12f2a896dc6eba6812e0128937 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENEGRAPH_NODE_RESETTER_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -109,9 +109,10 @@ public:
    * @param[in] bufferIndex the current buffer index
    * @param[in] owner The property owner
    */
-  void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
+  NotifyReturnType PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
   {
     mDisconnected = true;
+    return NotifyReturnType::KEEP_OBSERVING;
   }
 
   /**
index 314e335f30e0daf50d2055f93ba018cc12e842a1..b60e57254ff813cc783bda4a51f578b964e6cb3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -44,6 +44,8 @@ PropertyOwner::~PropertyOwner()
 
 void PropertyOwner::AddObserver(Observer& observer)
 {
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Cannot add observer while notifying PropertyOwner::Observers");
+
   //Check for duplicates in debug builds
   DALI_ASSERT_DEBUG(mObservers.End() == std::find(mObservers.Begin(), mObservers.End(), &observer));
 
@@ -52,13 +54,14 @@ void PropertyOwner::AddObserver(Observer& observer)
 
 void PropertyOwner::RemoveObserver(Observer& observer)
 {
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Cannot remove observer while notifying PropertyOwner::Observers");
+
   // Find the observer...
   const ConstObserverIter endIter = mObservers.End();
   for(ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
   {
     if((*iter) == &observer)
     {
-      // erase it
       mObservers.Erase(iter);
       break;
     }
@@ -72,13 +75,19 @@ bool PropertyOwner::IsObserved()
 
 void PropertyOwner::Destroy()
 {
+  // Guard Add/Remove observer during observer notifying.
+  mObserverNotifying = true;
+
   // Notification for observers
-  const ConstObserverIter endIter = mObservers.End();
-  for(ConstObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  for(auto&& item : mObservers)
   {
-    (*iter)->PropertyOwnerDestroyed(*this);
+    item->PropertyOwnerDestroyed(*this);
   }
 
+  // Note : We don't need to restore mObserverNotifying to false as we are in delete the object.
+  // If someone call AddObserver / RemoveObserver after this, assert.
+
+  // Remove all observers
   mObservers.Clear();
 
   // Remove all constraints when disconnected from scene-graph
@@ -88,28 +97,48 @@ void PropertyOwner::Destroy()
 
 void PropertyOwner::ConnectToSceneGraph()
 {
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Should not be call ConnectToSceneGraph while notifying PropertyOwner::Observers");
+
   mIsConnectedToSceneGraph = true;
   SetUpdated(true);
 
+  // Guard Add/Remove observer during observer notifying.
+  mObserverNotifying = true;
+
   // Notification for observers
-  const ConstObserverIter endIter = mObservers.End();
-  for(ConstObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  for(auto&& item : mObservers)
   {
-    (*iter)->PropertyOwnerConnected(*this);
+    item->PropertyOwnerConnected(*this);
   }
+
+  mObserverNotifying = false;
 }
 
 void PropertyOwner::DisconnectFromSceneGraph(BufferIndex updateBufferIndex)
 {
+  DALI_ASSERT_ALWAYS(!mObserverNotifying && "Should not be call DisconnectFromSceneGraph while notifying PropertyOwner::Observers");
+
   mIsConnectedToSceneGraph = false;
 
+  // Guard Add/Remove observer during observer notifying.
+  mObserverNotifying = true;
+
   // Notification for observers
-  const ConstObserverIter endIter = mObservers.End();
-  for(ConstObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  for(auto iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter;)
   {
-    (*iter)->PropertyOwnerDisconnected(updateBufferIndex, *this);
+    auto returnValue = (*iter)->PropertyOwnerDisconnected(updateBufferIndex, *this);
+    if(returnValue == Observer::KEEP_OBSERVING)
+    {
+      ++iter;
+    }
+    else
+    {
+      iter = mObservers.Erase(iter);
+    }
   }
 
+  mObserverNotifying = false;
+
   // Remove all constraints when disconnected from scene-graph
   mConstraints.Clear();
   mPostConstraints.Clear();
@@ -179,7 +208,8 @@ void PropertyOwner::RemovePostConstraint(ConstraintBase* constraint)
 
 PropertyOwner::PropertyOwner()
 : mUpdated(false),
-  mIsConnectedToSceneGraph(false)
+  mIsConnectedToSceneGraph(false),
+  mObserverNotifying(false)
 {
 }
 
index 9850e2f4d7722cb4e00ea11984dab5af8c7c7988..89ac96ba25f4fd2f7373018b840543f76e657e01 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -49,6 +49,13 @@ class PropertyOwner
 public:
   class Observer
   {
+  public:
+    enum NotifyReturnType
+    {
+      STOP_OBSERVING,
+      KEEP_OBSERVING,
+    };
+
   public:
     /**
      * Called when the observable object is connected to the scene graph.
@@ -60,8 +67,10 @@ public:
      * Called when the observable object is disconnected from the scene graph.
      * @param[in] currentBufferIndex The buffer to reset.
      * @param[in] owner A reference to the disconnected PropertyOwner
+     * @return NotifyReturnType::STOP_OBSERVING if we will not observe this object after this called
+     *         NotifyReturnType::KEEP_OBSERVING if we will observe this object after this called.
      */
-    virtual void PropertyOwnerDisconnected(BufferIndex updateBufferIndex, PropertyOwner& owner) = 0;
+    virtual NotifyReturnType PropertyOwnerDisconnected(BufferIndex updateBufferIndex, PropertyOwner& owner) = 0;
 
     /**
      * Called shortly before the observable object is destroyed.
@@ -284,8 +293,10 @@ private:
 
   ObserverContainer mObservers; ///< Container of observer raw-pointers (not owned)
 
-  ConstraintOwnerContainer mConstraints; ///< Container of owned constraints
+  ConstraintOwnerContainer mConstraints;     ///< Container of owned constraints
   ConstraintOwnerContainer mPostConstraints; ///< Container of owned constraints
+
+  bool mObserverNotifying : 1; ///< Whether we are currently notifying observers.
 };
 
 } // namespace SceneGraph
index 8b68fbf58534bcd2709c996e3523d9ea34709006..52ef2bbaff024bd5bfe929fd2be1f7a87f45c342 100644 (file)
@@ -108,9 +108,10 @@ public:
    * @param[in] bufferIndex the current buffer index
    * @param[in] owner The property owner
    */
-  void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
+  NotifyReturnType PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
   {
     mDisconnected = true;
+    return NotifyReturnType::KEEP_OBSERVING;
   }
 
   /**
index 2883440bcaf29429a44a31d53aa4c7b6efa64dc4..8e4e4eec28bccdafca1fd41895131c8a85bc9aa8 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENEGRAPH_RENDERER_RESETTER_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -105,8 +105,9 @@ public:
    * @param[in] bufferIndex the current buffer index
    * @param[in] owner The property owner
    */
-  void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
+  NotifyReturnType PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) override
   {
+    return NotifyReturnType::KEEP_OBSERVING;
   }
 
   /**
index 80a1bba6689cb828ea0b90525f8a14364b63211c..b150c9d3c9746a4910f43f70861a1245313a9a83 100644 (file)
@@ -136,8 +136,9 @@ private:
   /**
    * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected()
    */
-  void PropertyOwnerDisconnected(BufferIndex updateBufferIndex, PropertyOwner& owner) override
+  NotifyReturnType PropertyOwnerDisconnected(BufferIndex updateBufferIndex, PropertyOwner& owner) override
   { /* Nothing to do */
+    return NotifyReturnType::KEEP_OBSERVING;
   }
 
   /**
index 10a6cdd4ce7fde14256008b8967a5db2707234b5..499aed702c6b295f49d5e703ac36798b533aea70 100644 (file)
@@ -85,8 +85,9 @@ private: // From SceneGraph::PropertyOwner::Observer
   /**
    * @copydoc SceneGraph::PropertyOwner::Observer::PropertyOwnerDisconnected()
    */
-  void PropertyOwnerDisconnected(BufferIndex updateBufferIndex, SceneGraph::PropertyOwner& owner) override
+  NotifyReturnType PropertyOwnerDisconnected(BufferIndex updateBufferIndex, SceneGraph::PropertyOwner& owner) override
   { /* Nothing to do */
+    return NotifyReturnType::KEEP_OBSERVING;
   }
 
   /**
index dd58a5f4174e203490dc0e4d1914a63517f838ef..67d0167ced635492e8a813e62615f09a285f76f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -474,9 +474,10 @@ void RenderTask::PropertyOwnerConnected(PropertyOwner& owner)
   SetActiveStatus();
 }
 
-void RenderTask::PropertyOwnerDisconnected(BufferIndex /*updateBufferIndex*/, PropertyOwner& owner)
+PropertyOwner::Observer::NotifyReturnType RenderTask::PropertyOwnerDisconnected(BufferIndex /*updateBufferIndex*/, PropertyOwner& owner)
 {
   mActive = false; // if either source or camera disconnected, we're no longer active
+  return PropertyOwner::Observer::NotifyReturnType::KEEP_OBSERVING;
 }
 
 void RenderTask::PropertyOwnerDestroyed(PropertyOwner& owner)
index 7e07b081ebe5579fc25d2a62ef597235cf90db88..6b866a834e5850d178df1fa68f9e859bc5be7229 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * 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.
@@ -374,7 +374,7 @@ private: // from PropertyOwner::Observer
   /**
    * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected( BufferIndex updateBufferIndex, PropertyOwner& owner )
    */
-  void PropertyOwnerDisconnected(BufferIndex updateBufferIndex, PropertyOwner& owner) override;
+  PropertyOwner::Observer::NotifyReturnType PropertyOwnerDisconnected(BufferIndex updateBufferIndex, PropertyOwner& owner) override;
 
   /**
    * @copydoc PropertyOwner::Observer::PropertyOwnerDestroyed( PropertyOwner& owner )
@@ -396,7 +396,7 @@ private:
   RenderTask();
 
   // Undefined
-  RenderTask(const RenderTask&)            = delete;
+  RenderTask(const RenderTask&) = delete;
   RenderTask& operator=(const RenderTask&) = delete;
 
 public:                                          // Animatable Properties
@@ -416,11 +416,11 @@ private:
 
   RenderInstruction mRenderInstruction[2]; ///< Owned double buffered render instruction. (Double buffered because this owns render commands for the currently drawn frame)
 
-  uint32_t mRefreshRate;                   ///< REFRESH_ONCE, REFRESH_ALWAYS or render every N frames
-  uint32_t mFrameCounter;                  ///< counter for rendering every N frames
-  uint32_t mRenderedOnceCounter;           ///< Incremented whenever state changes to RENDERED_ONCE_AND_NOTIFIED
+  uint32_t mRefreshRate;         ///< REFRESH_ONCE, REFRESH_ALWAYS or render every N frames
+  uint32_t mFrameCounter;        ///< counter for rendering every N frames
+  uint32_t mRenderedOnceCounter; ///< Incremented whenever state changes to RENDERED_ONCE_AND_NOTIFIED
 
-  State mState;                            ///< Render state.
+  State mState; ///< Render state.
 
   uint32_t mRenderPassTag{0u};