From 3488607febde21cc3f632102c417a10ab6fe6b0b Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Tue, 28 May 2024 13:06:18 +0900 Subject: [PATCH] Implement ProcessorOnce Since unregister processor during Process will give overhead, we'd better make another container to process only once time during ProcessCoreEvent. Change-Id: I0b38490ccdbd7da4f7ec1acf80253a1aee8c42ad Signed-off-by: Eunki, Hong --- automated-tests/src/dali/utc-Dali-Processors.cpp | 257 +++++++++++++++++++++++ dali/integration-api/core.cpp | 10 + dali/integration-api/core.h | 18 +- dali/internal/common/core-impl.cpp | 180 ++++++++++++++++ dali/internal/common/core-impl.h | 15 ++ 5 files changed, 479 insertions(+), 1 deletion(-) diff --git a/automated-tests/src/dali/utc-Dali-Processors.cpp b/automated-tests/src/dali/utc-Dali-Processors.cpp index acc8a9e..a66d4c0 100644 --- a/automated-tests/src/dali/utc-Dali-Processors.cpp +++ b/automated-tests/src/dali/utc-Dali-Processors.cpp @@ -75,6 +75,29 @@ public: Integration::Core& core; }; +class NewTestProcessorOnce : public NewTestProcessor +{ +public: + NewTestProcessorOnce(Integration::Core& core) + : NewTestProcessor(core) + { + } + + virtual void Process(bool postProcessor) + { + processRun = true; + if(unregisterProcessor) + { + core.UnregisterProcessorOnce(*unregisterProcessor, postProcessor); + } + } + + std::string_view GetProcessorName() const override + { + return "NewTestProcessorOnce"; + } +}; + int UtcDaliCoreProcessorP(void) { TestApplication application; @@ -102,6 +125,38 @@ int UtcDaliCoreProcessorP(void) END_TEST; } +int UtcDaliCoreProcessorOnceP(void) +{ + TestApplication application; + + TestProcessor testProcessor; + Integration::Core& core = application.GetCore(); + core.RegisterProcessorOnce(testProcessor); + + tet_infoline("Test that the processor has not been executed yet:"); + DALI_TEST_CHECK(testProcessor.processRun == false); + + application.SendNotification(); + + tet_infoline("Test that the processor has been executed:"); + DALI_TEST_CHECK(testProcessor.processRun); + + // Clear down for next part of test + testProcessor.processRun = false; + + application.SendNotification(); + tet_infoline("Test that the processor has not been executed:"); + DALI_TEST_CHECK(!testProcessor.processRun); + + core.RegisterProcessorOnce(testProcessor); + core.UnregisterProcessorOnce(testProcessor); + application.SendNotification(); + tet_infoline("Test that the processor has not been executed again:"); + DALI_TEST_CHECK(!testProcessor.processRun); + + END_TEST; +} + int UtcDaliCoreProcessorMultipleP(void) { TestApplication application; @@ -152,6 +207,63 @@ int UtcDaliCoreProcessorMultipleP(void) END_TEST; } +int UtcDaliCoreProcessorOnceMultipleP(void) +{ + TestApplication application; + + TestProcessor testProcessor1; + TestProcessor testProcessor2; + TestProcessor testProcessor3; + + Integration::Core& core = application.GetCore(); + core.RegisterProcessorOnce(testProcessor1); + + tet_infoline("Test that the processor has not been executed yet:"); + DALI_TEST_CHECK(testProcessor1.processRun == false); + + application.SendNotification(); + + tet_infoline("Test that the processor has been executed:"); + DALI_TEST_CHECK(testProcessor1.processRun); + + // Clear down for next part of test + testProcessor1.processRun = false; + + core.RegisterProcessorOnce(testProcessor1); + core.RegisterProcessorOnce(testProcessor2); + core.RegisterProcessorOnce(testProcessor3); + + tet_infoline("Test that the processors have not been executed yet:"); + 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; + + core.RegisterProcessorOnce(testProcessor1); + core.RegisterProcessorOnce(testProcessor2); + core.RegisterProcessorOnce(testProcessor3); + + core.UnregisterProcessorOnce(testProcessor2); + application.SendNotification(); + tet_infoline("Test that the unregistered processor has not been executed again but others have"); + DALI_TEST_CHECK(testProcessor1.processRun); + DALI_TEST_CHECK(testProcessor2.processRun == false); + DALI_TEST_CHECK(testProcessor3.processRun); + + END_TEST; +} + int UtcDaliCorePostProcessorP(void) { TestApplication application; @@ -187,6 +299,38 @@ int UtcDaliCorePostProcessorP(void) END_TEST; } +int UtcDaliCorePostProcessorOnceP(void) +{ + TestApplication application; + + TestProcessor testProcessor; + Integration::Core& core = application.GetCore(); + core.RegisterProcessorOnce(testProcessor, true); + + tet_infoline("Test that the processor has not been executed yet:"); + DALI_TEST_CHECK(testProcessor.processRun == false); + + application.SendNotification(); + + tet_infoline("Test that the processor has been executed:"); + DALI_TEST_CHECK(testProcessor.processRun); + + // Clear down for next part of test + testProcessor.processRun = false; + + application.SendNotification(); + tet_infoline("Test that the processor has not been executed:"); + DALI_TEST_CHECK(!testProcessor.processRun); + + core.RegisterProcessorOnce(testProcessor, true); + core.UnregisterProcessorOnce(testProcessor, true); + application.SendNotification(); + tet_infoline("Test that the processor has not been executed again:"); + DALI_TEST_CHECK(!testProcessor.processRun); + + END_TEST; +} + int UtcDaliCoreProcessorUnregisterDuringCallback01(void) { // Test pre-processor @@ -271,6 +415,112 @@ int UtcDaliCoreProcessorUnregisterDuringCallback02(void) END_TEST; } +int UtcDaliCoreProcessorOnceUnregisterDuringCallback01(void) +{ + // Test post-processor + TestApplication application; + Integration::Core& core = application.GetCore(); + + NewTestProcessorOnce testProcessor1(core); + TestProcessor testProcessor2; + TestProcessor testProcessor3; + + core.RegisterProcessorOnce(testProcessor1); + core.RegisterProcessorOnce(testProcessor2); + core.RegisterProcessorOnce(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; + + application.SendNotification(); + + tet_infoline("Test that the processors have not been executed:"); + DALI_TEST_CHECK(!testProcessor1.processRun); + DALI_TEST_CHECK(!testProcessor2.processRun); + DALI_TEST_CHECK(!testProcessor3.processRun); + + core.RegisterProcessorOnce(testProcessor1); + core.RegisterProcessorOnce(testProcessor2); + core.RegisterProcessorOnce(testProcessor3); + + 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 UtcDaliCoreProcessorOnceUnregisterDuringCallback02(void) +{ + // Test post-processor + TestApplication application; + Integration::Core& core = application.GetCore(); + + NewTestProcessorOnce testProcessor1(core); + TestProcessor testProcessor2; + TestProcessor testProcessor3; + + core.RegisterProcessorOnce(testProcessor1, true); + core.RegisterProcessorOnce(testProcessor2, true); + core.RegisterProcessorOnce(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; + + application.SendNotification(); + + tet_infoline("Test that the processors have not been executed:"); + DALI_TEST_CHECK(!testProcessor1.processRun); + DALI_TEST_CHECK(!testProcessor2.processRun); + DALI_TEST_CHECK(!testProcessor3.processRun); + + core.RegisterProcessorOnce(testProcessor1, true); + core.RegisterProcessorOnce(testProcessor2, true); + core.RegisterProcessorOnce(testProcessor3, true); + + 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 UtcDaliCoreProcessorGetProcessorName(void) { // Test post-processor @@ -293,6 +543,8 @@ int UtcDaliCoreProcessorUnregisterProcessors(void) TestProcessor testProcessor1; TestProcessor testProcessor2; TestProcessor testProcessor3; + TestProcessor testProcessor4; + TestProcessor testProcessor5; Integration::Core& core = application.GetCore(); core.RegisterProcessor(testProcessor1); @@ -328,12 +580,17 @@ int UtcDaliCoreProcessorUnregisterProcessors(void) testProcessor2.processRun = false; testProcessor3.processRun = false; + core.RegisterProcessorOnce(testProcessor4); + core.RegisterProcessorOnce(testProcessor5, true); + core.UnregisterProcessors(); application.SendNotification(); tet_infoline("Test that all processors has not been executed again"); DALI_TEST_CHECK(testProcessor1.processRun == false); DALI_TEST_CHECK(testProcessor2.processRun == false); DALI_TEST_CHECK(testProcessor3.processRun == false); + DALI_TEST_CHECK(testProcessor4.processRun == false); + DALI_TEST_CHECK(testProcessor5.processRun == false); END_TEST; diff --git a/dali/integration-api/core.cpp b/dali/integration-api/core.cpp index 02520f0..f6b5600 100644 --- a/dali/integration-api/core.cpp +++ b/dali/integration-api/core.cpp @@ -139,6 +139,16 @@ void Core::UnregisterProcessor(Processor& processor, bool postProcessor) mImpl->UnregisterProcessor(processor, postProcessor); } +void Core::RegisterProcessorOnce(Processor& processor, bool postProcessor) +{ + mImpl->RegisterProcessorOnce(processor, postProcessor); +} + +void Core::UnregisterProcessorOnce(Processor& processor, bool postProcessor) +{ + mImpl->UnregisterProcessorOnce(processor, postProcessor); +} + void Core::UnregisterProcessors() { mImpl->UnregisterProcessors(); diff --git a/dali/integration-api/core.h b/dali/integration-api/core.h index 1075bc6..b2ab889 100644 --- a/dali/integration-api/core.h +++ b/dali/integration-api/core.h @@ -406,7 +406,23 @@ public: void UnregisterProcessor(Processor& processor, bool postProcessor = false); /** - * @brief Unregister all processors and post processors what we registered before. + * @brief Register a processor for once execute + * + * Note, Core does not take ownership of this processor. + * @param[in] processor The process to register + * @param[in] postProcessor set this processor required to be called after size negotiation. Default is false. + */ + void RegisterProcessorOnce(Processor& processor, bool postProcessor = false); + + /** + * @brief Unregister a processor for once execute + * @param[in] processor The process to unregister + * @param[in] postProcessor True if the processor to be unregister is for post processor. + */ + void UnregisterProcessorOnce(Processor& processor, bool postProcessor = false); + + /** + * @brief Unregister all processors and post processors (include once) what we registered before. */ void UnregisterProcessors(); diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 6143a31..bf43498 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -82,6 +82,8 @@ Core::Core(RenderController& renderController, : mRenderController(renderController), mPlatform(platform), mGraphicsController(graphicsController), + mProcessorOnceIndex(0u), + mPostProcessorOnceIndex(0u), mProcessingEvent(false), mProcessorUnregistered(false), mPostProcessorUnregistered(false), @@ -420,16 +422,132 @@ void Core::UnregisterProcessor(Integration::Processor& processor, bool postProce } } +void Core::RegisterProcessorOnce(Integration::Processor& processor, bool postProcessor) +{ + if(postProcessor) + { + mPostProcessorsOnce[mPostProcessorOnceIndex].PushBack(&processor); + } + else + { + mProcessorsOnce[mProcessorOnceIndex].PushBack(&processor); + } +} + +void Core::UnregisterProcessorOnce(Integration::Processor& processor, bool postProcessor) +{ + if(postProcessor) + { + for(uint32_t index = 0; index < 2; ++index) + { + auto iter = std::find(mPostProcessorsOnce[index].Begin(), mPostProcessorsOnce[index].End(), &processor); + if(iter != mPostProcessorsOnce[index].End()) + { + mPostProcessorsOnce[index].Erase(iter); + if(index != mPostProcessorOnceIndex) + { + // Check processor unregistered during processing. + mPostProcessorUnregistered = true; + } + } + } + } + else + { + for(uint32_t index = 0; index < 2; ++index) + { + auto iter = std::find(mProcessorsOnce[index].Begin(), mProcessorsOnce[index].End(), &processor); + if(iter != mProcessorsOnce[index].End()) + { + mProcessorsOnce[index].Erase(iter); + if(index != mProcessorOnceIndex) + { + // Check processor unregistered during processing. + mProcessorUnregistered = true; + } + } + } + } +} + void Core::UnregisterProcessors() { mPostProcessors.Clear(); mPostProcessorUnregistered = true; mProcessors.Clear(); mProcessorUnregistered = true; + + for(uint32_t index = 0; index < 2; ++index) + { + mPostProcessorsOnce[index].Clear(); + mProcessorsOnce[index].Clear(); + } } void Core::RunProcessors() { + if(mProcessorsOnce[mProcessorOnceIndex].Count() != 0) + { + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) { + oss << "[" << mProcessorOnceIndex << ":" << mProcessorsOnce[mProcessorOnceIndex].Count() << "]"; + }); + + // Swap processor index. + uint32_t currentIndex = mProcessorOnceIndex; + mProcessorOnceIndex ^= 1; + + // Copy processor pointers to prevent changes to vector affecting loop iterator. + Dali::Vector processors(mProcessorsOnce[currentIndex]); + + // To prevent accessing processor unregistered during the loop + mProcessorUnregistered = false; + + for(auto processor : processors) + { + if(processor) + { + if(!mProcessorUnregistered) + { + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + processor->Process(false); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + } + else + { + // Run processor if the processor is still in the list. + // It may be removed during the loop. + auto iter = std::find(mProcessorsOnce[currentIndex].Begin(), mProcessorsOnce[currentIndex].End(), processor); + if(iter != mProcessorsOnce[currentIndex].End()) + { + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + processor->Process(false); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + } + } + } + } + + // Clear once processor. + mProcessorsOnce[currentIndex].Clear(); + + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) { + oss << "[" << currentIndex; + if(mProcessorUnregistered) + { + oss << ", processor changed"; + } + oss << "]"; + }); + } + if(mProcessors.Count() != 0) { DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) { @@ -487,6 +605,68 @@ void Core::RunProcessors() void Core::RunPostProcessors() { + if(mPostProcessorsOnce[mPostProcessorOnceIndex].Count() != 0) + { + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) { + oss << "[" << mPostProcessorOnceIndex << ":" << mPostProcessorsOnce[mPostProcessorOnceIndex].Count() << "]"; + }); + + // Swap processor index. + uint32_t currentIndex = mPostProcessorOnceIndex; + mPostProcessorOnceIndex ^= 1; + + // Copy processor pointers to prevent changes to vector affecting loop iterator. + Dali::Vector processors(mPostProcessorsOnce[currentIndex]); + + // To prevent accessing processor unregistered during the loop + mPostProcessorUnregistered = false; + + for(auto processor : processors) + { + if(processor) + { + if(!mPostProcessorUnregistered) + { + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + processor->Process(true); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + } + else + { + // Run processor if the processor is still in the list. + // It may be removed during the loop. + auto iter = std::find(mPostProcessorsOnce[currentIndex].Begin(), mPostProcessorsOnce[currentIndex].End(), processor); + if(iter != mPostProcessorsOnce[currentIndex].End()) + { + DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + processor->Process(true); + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) { + oss << "[" << processor->GetProcessorName() << "]"; + }); + } + } + } + } + + // Clear once processor. + mPostProcessorsOnce[currentIndex].Clear(); + + DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) { + oss << "[" << currentIndex; + if(mPostProcessorUnregistered) + { + oss << ", processor changed"; + } + oss << "]"; + }); + } + if(mPostProcessors.Count() != 0) { DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) { diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h index f393e83..508e718 100644 --- a/dali/internal/common/core-impl.h +++ b/dali/internal/common/core-impl.h @@ -182,6 +182,16 @@ public: void UnregisterProcessor(Dali::Integration::Processor& processor, bool postProcessor = false); /** + * @copydoc Dali::Integration::Core::RegisterProcessorOnce + */ + void RegisterProcessorOnce(Integration::Processor& processor, bool postProcessor = false); + + /** + * @copydoc Dali::Integration::Core::UnregisterProcessorOnce + */ + void UnregisterProcessorOnce(Dali::Integration::Processor& processor, bool postProcessor = false); + + /** * @copydoc Dali::Integration::Core::UnregisterProcessors */ void UnregisterProcessors(); @@ -353,6 +363,8 @@ private: OwnerPointer mGestureEventProcessor; ///< The gesture event processor Dali::Vector mProcessors; ///< Registered processors (not owned) Dali::Vector mPostProcessors; ///< Registered post processors those will called after relayout(not owned) + Dali::Vector mProcessorsOnce[2]; ///< Registered processors for once (not owned) + Dali::Vector mPostProcessorsOnce[2]; ///< Registered post processors for once. those will called after relayout(not owned) SceneContainer mScenes; ///< A container of scenes that bound to a surface for rendering, owned by Core @@ -361,6 +373,9 @@ private: Graphics::Controller& mGraphicsController; + uint32_t mProcessorOnceIndex : 1; ///< Index of the once processor in mProcessorsOnce + uint32_t mPostProcessorOnceIndex : 1; ///< Index of the once processor in mProcessorsOnce + bool mProcessingEvent : 1; ///< True during ProcessEvents() bool mProcessorUnregistered : 1; ///< True if the processor is unregistered during RunProcessors() bool mPostProcessorUnregistered : 1; ///< True if the post-processor is unregistered during RunPostProcessors() -- 2.7.4