From: Heeyong Song Date: Wed, 14 Sep 2022 05:50:53 +0000 (+0900) Subject: Ensure the processor unregistered during the callback is not executed X-Git-Tag: dali_2.1.40~2^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-core.git;a=commitdiff_plain;h=4d7887f8ac273ab2151e8006c6d1e2ad50aa158f Ensure the processor unregistered during the callback is not executed Change-Id: I11215bc7bb6fdec892723f176ad6497bbf61f2a7 --- diff --git a/automated-tests/src/dali/utc-Dali-Processors.cpp b/automated-tests/src/dali/utc-Dali-Processors.cpp index 0d1b864..c118011 100644 --- a/automated-tests/src/dali/utc-Dali-Processors.cpp +++ b/automated-tests/src/dali/utc-Dali-Processors.cpp @@ -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; +} diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 5e02c36..c37dd21 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -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 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 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); + } + } } } } diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h index 7313d26..8d218aa 100644 --- a/dali/internal/common/core-impl.h +++ b/dali/internal/common/core-impl.h @@ -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; };