#include <cstddef>
#include <semaphore.h>
#include <math.h>
+#include <ctime>
#include <climits>
-
-namespace Dali
-{
+#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;
};
: mImpl( new Impl() )
{
mImpl->callback = callback;
- mImpl->triggeredCount = 0u;
- mImpl->expectedCount = UINT_MAX;
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()
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;
}
}