Implement ProcessorOnce 95/311795/2
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 28 May 2024 04:06:18 +0000 (13:06 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Tue, 28 May 2024 04:40:22 +0000 (13:40 +0900)
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 <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-Processors.cpp
dali/integration-api/core.cpp
dali/integration-api/core.h
dali/internal/common/core-impl.cpp
dali/internal/common/core-impl.h

index acc8a9ead6b1dcbd46a85e6fcce540425683b82a..a66d4c02cbcf86bc9ea91c9163d0a7b465661146 100644 (file)
@@ -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;
 
index 02520f0c5962db4149df49d997f59be76c283203..f6b5600904e49cbf6a707b2b3d3b7b1c738f0073 100644 (file)
@@ -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();
index 1075bc65239befabcb555bf9cf1048d1e012515a..b2ab889a42547cdb98f6902d9c25fa1d3fdd7477 100644 (file)
@@ -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();
 
index 6143a310602e8dc4143415bbaa0c73a3d195e791..bf43498ce813b248805cd5d7a1b84376b3e24b4d 100644 (file)
@@ -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<Integration::Processor*> 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<Integration::Processor*> 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) {
index f393e8340c5dfc66da211756c0c4926516ebea29..508e718411670341893df0ab8f4ba019a75d8201 100644 (file)
@@ -181,6 +181,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
    */
@@ -353,6 +363,8 @@ private:
   OwnerPointer<GestureEventProcessor>           mGestureEventProcessor; ///< The gesture event processor
   Dali::Vector<Integration::Processor*>         mProcessors;            ///< Registered processors (not owned)
   Dali::Vector<Integration::Processor*>         mPostProcessors;        ///< Registered post processors those will called after relayout(not owned)
+  Dali::Vector<Integration::Processor*>         mProcessorsOnce[2];     ///< Registered processors for once (not owned)
+  Dali::Vector<Integration::Processor*>         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()