[dali_2.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / toolkit-event-thread-callback.cpp
index f77cdde..c85110a 100644 (file)
 #include "toolkit-event-thread-callback.h"
 
 // EXTERNAL INCLUDES
-#include <cstddef>
-#include <semaphore.h>
 #include <math.h>
+#include <semaphore.h>
+#include <unistd.h>
+#include <algorithm>
 #include <climits>
-
-namespace Dali
-{
+#include <cstddef>
+#include <cstdio>
+#include <ctime>
+#include <vector>
 
 namespace
 {
-EventThreadCallback* gEventThreadCallback = NULL;
-}
+// Note, this is not thread safe - however, should not be using
+// triggers from multiple threads - they should all be created on
+// event thread.
+std::vector<Dali::EventThreadCallback*> gEventThreadCallbacks;
+} // namespace
 
+namespace Dali
+{
 struct EventThreadCallback::Impl
 {
   CallbackBase* callback;
-  unsigned int triggeredCount;
-  unsigned int expectedCount;
-  sem_t mySemaphore;
+  sem_t         mySemaphore;
 };
 
-EventThreadCallback::EventThreadCallback( CallbackBase* callback )
-: mImpl( new Impl() )
+EventThreadCallback::EventThreadCallback(CallbackBase* callback)
+: mImpl(new Impl())
 {
   mImpl->callback = callback;
-  mImpl->triggeredCount = 0u;
-  mImpl->expectedCount = UINT_MAX;
-  sem_init( &(mImpl->mySemaphore), 0, 0 );
-  gEventThreadCallback = this;
+  sem_init(&(mImpl->mySemaphore), 0, 0);
+
+  gEventThreadCallbacks.push_back(this);
 }
 
 EventThreadCallback::~EventThreadCallback()
 {
+  std::vector<EventThreadCallback*>::iterator iter =
+    std::find(gEventThreadCallbacks.begin(), gEventThreadCallbacks.end(), this);
+  if(iter != gEventThreadCallbacks.end())
+  {
+    gEventThreadCallbacks.erase(iter);
+  }
   delete mImpl;
 }
 
 void EventThreadCallback::Trigger()
 {
-  mImpl->triggeredCount++;
-  if(  mImpl->triggeredCount >= mImpl->expectedCount )
-  {
-    sem_post( &(mImpl->mySemaphore) );
-  }
+  sem_post(&(mImpl->mySemaphore));
 }
 
-void EventThreadCallback::WaitingForTrigger(unsigned int count)
+// returns true if timed out rather than triggered
+bool EventThreadCallback::WaitingForTrigger()
 {
-  if(  mImpl->triggeredCount >= count )
+  struct timespec now;
+  clock_gettime(CLOCK_REALTIME, &now);
+  if(now.tv_nsec < 999900000) // 999, 900, 000
+    now.tv_nsec += 1000;
+  else
   {
-    return;
+    now.tv_sec += 1;
+    now.tv_nsec = 0;
   }
-  mImpl->expectedCount = count;
-  sem_wait( &(mImpl->mySemaphore) );
+
+  int error = sem_timedwait(&(mImpl->mySemaphore), &now);
+  return error != 0; // true if timeout
 }
 
 CallbackBase* EventThreadCallback::GetCallback()
@@ -78,9 +91,59 @@ CallbackBase* EventThreadCallback::GetCallback()
   return mImpl->callback;
 }
 
-EventThreadCallback* EventThreadCallback::Get()
+} // namespace Dali
+
+namespace Test
 {
-  return gEventThreadCallback;
-}
+bool WaitForEventThreadTrigger(int triggerCount, int timeoutInSeconds, int executeCallbacks)
+{
+  struct timespec startTime;
+  struct timespec now;
+  clock_gettime(CLOCK_REALTIME, &startTime);
+  now.tv_sec  = startTime.tv_sec;
+  now.tv_nsec = startTime.tv_nsec;
 
+  // Round robin poll of each semaphore:
+  while(triggerCount > 0)
+  {
+    if(gEventThreadCallbacks.size() > 0)
+    {
+      for(std::vector<Dali::EventThreadCallback*>::iterator iter = gEventThreadCallbacks.begin();
+          iter != gEventThreadCallbacks.end();
+          ++iter)
+      {
+        Dali::EventThreadCallback* eventTrigger = (*iter);
+        Dali::CallbackBase*        callback     = eventTrigger->GetCallback();
+        bool                       timedout     = eventTrigger->WaitingForTrigger();
+        if(!timedout)
+        {
+          if(executeCallbacks)
+          {
+            // Semaphore was unlocked - execute the trigger
+            Dali::CallbackBase::Execute(*callback);
+          }
+          triggerCount--;
+        }
+        if(triggerCount <= 0)
+        {
+          break;
+        }
+      }
+    }
+    clock_gettime(CLOCK_REALTIME, &now);
+    if(now.tv_sec - startTime.tv_sec > timeoutInSeconds)
+    {
+      // Ensure we break out of the loop if elapsed time has passed
+      break;
+    }
+  }
+
+  clock_gettime(CLOCK_REALTIME, &now);
+  if(now.tv_sec > startTime.tv_sec + 1)
+  {
+    fprintf(stderr, "WaitForEventThreadTrigger took %ld seconds\n", now.tv_sec - startTime.tv_sec);
+  }
+  return triggerCount == 0;
 }
+
+} // namespace Test