Ensure the processor unregistered during the callback is not executed 82/281182/2
authorHeeyong Song <heeyong.song@samsung.com>
Wed, 14 Sep 2022 05:50:53 +0000 (14:50 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Thu, 15 Sep 2022 02:57:27 +0000 (11:57 +0900)
Change-Id: I11215bc7bb6fdec892723f176ad6497bbf61f2a7

automated-tests/src/dali/utc-Dali-Processors.cpp
dali/internal/common/core-impl.cpp
dali/internal/common/core-impl.h

index 0d1b864..c118011 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -39,6 +39,32 @@ public:
   bool processRun;
 };
 
+class NewTestProcessor : public TestProcessor
+{
+public:
+  NewTestProcessor(Integration::Core& core)
+  : core(core)
+  {
+  }
+
+  virtual void Process(bool postProcessor)
+  {
+    processRun = true;
+    if(unregisterProcessor)
+    {
+      core.UnregisterProcessor(*unregisterProcessor, postProcessor);
+    }
+  }
+
+  void SetProcessorToUnregister(Integration::Processor* processor)
+  {
+    unregisterProcessor = processor;
+  }
+
+  Integration::Processor* unregisterProcessor{nullptr};
+  Integration::Core&      core;
+};
+
 int UtcDaliCoreProcessorP(void)
 {
   TestApplication application;
@@ -149,4 +175,88 @@ int UtcDaliCorePostProcessorP(void)
   DALI_TEST_CHECK(testProcessor.processRun == false);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliCoreProcessorUnregisterDuringCallback01(void)
+{
+  // Test pre-processor
+  TestApplication    application;
+  Integration::Core& core = application.GetCore();
+
+  NewTestProcessor testProcessor1(core);
+  TestProcessor    testProcessor2;
+  TestProcessor    testProcessor3;
+
+  core.RegisterProcessor(testProcessor1);
+  core.RegisterProcessor(testProcessor2);
+  core.RegisterProcessor(testProcessor3);
+
+  DALI_TEST_CHECK(testProcessor1.processRun == false);
+  DALI_TEST_CHECK(testProcessor2.processRun == false);
+  DALI_TEST_CHECK(testProcessor3.processRun == false);
+
+  application.SendNotification();
+
+  tet_infoline("Test that the processors have been executed:");
+  DALI_TEST_CHECK(testProcessor1.processRun);
+  DALI_TEST_CHECK(testProcessor2.processRun);
+  DALI_TEST_CHECK(testProcessor3.processRun);
+
+  // Clear down for next part of test
+  testProcessor1.processRun = false;
+  testProcessor2.processRun = false;
+  testProcessor3.processRun = false;
+
+  testProcessor1.SetProcessorToUnregister(&testProcessor3);
+
+  tet_infoline("Test that the processor unregistered during the callback has not been executed");
+  application.SendNotification();
+
+  DALI_TEST_CHECK(testProcessor1.processRun);
+  DALI_TEST_CHECK(testProcessor2.processRun);
+  DALI_TEST_CHECK(!testProcessor3.processRun);
+
+  END_TEST;
+}
+
+int UtcDaliCoreProcessorUnregisterDuringCallback02(void)
+{
+  // Test post-processor
+  TestApplication    application;
+  Integration::Core& core = application.GetCore();
+
+  NewTestProcessor testProcessor1(core);
+  TestProcessor    testProcessor2;
+  TestProcessor    testProcessor3;
+
+  core.RegisterProcessor(testProcessor1, true);
+  core.RegisterProcessor(testProcessor2, true);
+  core.RegisterProcessor(testProcessor3, true);
+
+  DALI_TEST_CHECK(testProcessor1.processRun == false);
+  DALI_TEST_CHECK(testProcessor2.processRun == false);
+  DALI_TEST_CHECK(testProcessor3.processRun == false);
+
+  application.SendNotification();
+
+  tet_infoline("Test that the processors have been executed:");
+  DALI_TEST_CHECK(testProcessor1.processRun);
+  DALI_TEST_CHECK(testProcessor2.processRun);
+  DALI_TEST_CHECK(testProcessor3.processRun);
+
+  // Clear down for next part of test
+  testProcessor1.processRun = false;
+  testProcessor2.processRun = false;
+  testProcessor3.processRun = false;
+
+  testProcessor1.SetProcessorToUnregister(&testProcessor3);
+
+  tet_infoline("Test that the processor unregistered during the callback has not been executed");
+  application.SendNotification();
+
+  DALI_TEST_CHECK(testProcessor1.processRun);
+  DALI_TEST_CHECK(testProcessor2.processRun);
+  DALI_TEST_CHECK(!testProcessor3.processRun);
+
+  END_TEST;
+}
index 5e02c36..c37dd21 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -87,7 +87,9 @@ Core::Core(RenderController&                   renderController,
   mPlatform(platform),
   mGraphicsController(graphicsController),
   mProcessingEvent(false),
-  mForceNextUpdate(false)
+  mForceNextUpdate(false),
+  mProcessorUnregistered(false),
+  mPostProcessorUnregistered(false)
 {
   // Create the thread local storage
   CreateThreadLocalStorage();
@@ -347,6 +349,7 @@ void Core::UnregisterProcessor(Integration::Processor& processor, bool postProce
     if(iter != mPostProcessors.End())
     {
       mPostProcessors.Erase(iter);
+      mPostProcessorUnregistered = true;
     }
   }
   else
@@ -355,6 +358,7 @@ void Core::UnregisterProcessor(Integration::Processor& processor, bool postProce
     if(iter != mProcessors.End())
     {
       mProcessors.Erase(iter);
+      mProcessorUnregistered = true;
     }
   }
 }
@@ -364,11 +368,27 @@ void Core::RunProcessors()
   // Copy processor pointers to prevent changes to vector affecting loop iterator.
   Dali::Vector<Integration::Processor*> processors(mProcessors);
 
+  // To prevent accessing processor unregistered during the loop
+  mProcessorUnregistered = false;
+
   for(auto processor : processors)
   {
     if(processor)
     {
-      processor->Process(false);
+      if(!mProcessorUnregistered)
+      {
+        processor->Process(false);
+      }
+      else
+      {
+        // Run processor if the processor is still in the list.
+        // It may be removed during the loop.
+        auto iter = std::find(mProcessors.Begin(), mProcessors.End(), processor);
+        if(iter != mProcessors.End())
+        {
+          processor->Process(false);
+        }
+      }
     }
   }
 }
@@ -378,11 +398,27 @@ void Core::RunPostProcessors()
   // Copy processor pointers to prevent changes to vector affecting loop iterator.
   Dali::Vector<Integration::Processor*> processors(mPostProcessors);
 
+  // To prevent accessing processor unregistered during the loop
+  mPostProcessorUnregistered = false;
+
   for(auto processor : processors)
   {
     if(processor)
     {
-      processor->Process(true);
+      if(!mPostProcessorUnregistered)
+      {
+        processor->Process(true);
+      }
+      else
+      {
+        // Run processor if the processor is still in the list.
+        // It may be removed during the loop.
+        auto iter = std::find(mPostProcessors.Begin(), mPostProcessors.End(), processor);
+        if(iter != mPostProcessors.End())
+        {
+          processor->Process(true);
+        }
+      }
     }
   }
 }
index 7313d26..8d218aa 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_CORE_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -358,8 +358,10 @@ private:
 
   Graphics::Controller& mGraphicsController;
 
-  bool mProcessingEvent : 1; ///< True during ProcessEvents()
-  bool mForceNextUpdate : 1; ///< True if the next rendering is really required.
+  bool mProcessingEvent : 1;           ///< True during ProcessEvents()
+  bool mForceNextUpdate : 1;           ///< True if the next rendering is really required.
+  bool mProcessorUnregistered : 1;     ///< True if the processor is unregistered during RunProcessors()
+  bool mPostProcessorUnregistered : 1; ///< True if the post-processor is unregistered during RunPostProcessors()
 
   friend class ThreadLocalStorage;
 };