Ensured ImageView requests inside ResourceReady signal handler are queued.
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / toolkit-event-thread-callback.cpp
index e8ee062..02f3d8f 100644 (file)
 #include <cstddef>
 #include <semaphore.h>
 #include <math.h>
-
-namespace Dali
-{
+#include <ctime>
+#include <climits>
+#include <cstdio>
+#include <unistd.h>
+#include <vector>
+#include <algorithm>
 
 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 Dali
+{
+
 struct EventThreadCallback::Impl
 {
   CallbackBase* callback;
-  unsigned int triggeredCount;
-  unsigned int expectedCount;
   sem_t mySemaphore;
 };
 
@@ -42,34 +50,42 @@ EventThreadCallback::EventThreadCallback( CallbackBase* callback )
 : mImpl( new Impl() )
 {
   mImpl->callback = callback;
-  mImpl->triggeredCount = 0u;
-  mImpl->expectedCount = INFINITY;
   sem_init( &(mImpl->mySemaphore), 0, 0 );
-  gEventThreadCallback = this;
+
+  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()
@@ -77,9 +93,57 @@ CallbackBase* EventThreadCallback::GetCallback()
   return mImpl->callback;
 }
 
-EventThreadCallback* EventThreadCallback::Get()
+}
+
+
+namespace Test
+{
+
+bool WaitForEventThreadTrigger( int triggerCount, int timeoutInSeconds )
 {
-  return gEventThreadCallback;
+  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 )
+        {
+          // 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;
 }
 
 }