[dali_2.3.20] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / toolkit-event-thread-callback.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // CLASS HEADER
18 #include "toolkit-event-thread-callback.h"
19
20 // EXTERNAL INCLUDES
21 #include <math.h>
22 #include <semaphore.h>
23 #include <unistd.h>
24 #include <algorithm>
25 #include <climits>
26 #include <cstddef>
27 #include <cstdio>
28 #include <ctime>
29 #include <vector>
30
31 namespace
32 {
33 // Note, this is not thread safe - however, should not be using
34 // triggers from multiple threads - they should all be created on
35 // event thread.
36 std::vector<Dali::EventThreadCallback*> gEventThreadCallbacks;
37 } // namespace
38
39 namespace Dali
40 {
41 struct EventThreadCallback::Impl
42 {
43   CallbackBase* callback;
44   sem_t         mySemaphore;
45 };
46
47 EventThreadCallback::EventThreadCallback(CallbackBase* callback)
48 : mImpl(new Impl())
49 {
50   mImpl->callback = callback;
51   sem_init(&(mImpl->mySemaphore), 0, 0);
52
53   gEventThreadCallbacks.push_back(this);
54 }
55
56 EventThreadCallback::~EventThreadCallback()
57 {
58   std::vector<EventThreadCallback*>::iterator iter =
59     std::find(gEventThreadCallbacks.begin(), gEventThreadCallbacks.end(), this);
60   if(iter != gEventThreadCallbacks.end())
61   {
62     gEventThreadCallbacks.erase(iter);
63   }
64   delete mImpl;
65 }
66
67 void EventThreadCallback::Trigger()
68 {
69   sem_post(&(mImpl->mySemaphore));
70 }
71
72 // returns true if timed out rather than triggered
73 bool EventThreadCallback::WaitingForTrigger()
74 {
75   struct timespec now;
76   clock_gettime(CLOCK_REALTIME, &now);
77   if(now.tv_nsec < 999900000) // 999, 900, 000
78     now.tv_nsec += 1000;
79   else
80   {
81     now.tv_sec += 1;
82     now.tv_nsec = 0;
83   }
84
85   int error = sem_timedwait(&(mImpl->mySemaphore), &now);
86   return error != 0; // true if timeout
87 }
88
89 CallbackBase* EventThreadCallback::GetCallback()
90 {
91   return mImpl->callback;
92 }
93
94 } // namespace Dali
95
96 namespace Test
97 {
98 bool WaitForEventThreadTrigger(int triggerCount, int timeoutInSeconds, int executeCallbacks)
99 {
100   struct timespec startTime;
101   struct timespec now;
102   clock_gettime(CLOCK_REALTIME, &startTime);
103   now.tv_sec  = startTime.tv_sec;
104   now.tv_nsec = startTime.tv_nsec;
105
106   // Round robin poll of each semaphore:
107   while(triggerCount > 0)
108   {
109     if(gEventThreadCallbacks.size() > 0)
110     {
111       for(std::vector<Dali::EventThreadCallback*>::iterator iter = gEventThreadCallbacks.begin();
112           iter != gEventThreadCallbacks.end();
113           ++iter)
114       {
115         Dali::EventThreadCallback* eventTrigger = (*iter);
116         Dali::CallbackBase*        callback     = eventTrigger->GetCallback();
117         bool                       timedout     = eventTrigger->WaitingForTrigger();
118         if(!timedout)
119         {
120           if(executeCallbacks)
121           {
122             // Semaphore was unlocked - execute the trigger
123             Dali::CallbackBase::Execute(*callback);
124           }
125           triggerCount--;
126         }
127         if(triggerCount <= 0)
128         {
129           break;
130         }
131       }
132     }
133     clock_gettime(CLOCK_REALTIME, &now);
134     if(now.tv_sec - startTime.tv_sec > timeoutInSeconds)
135     {
136       // Ensure we break out of the loop if elapsed time has passed
137       break;
138     }
139   }
140
141   clock_gettime(CLOCK_REALTIME, &now);
142   if(now.tv_sec > startTime.tv_sec + 1)
143   {
144     fprintf(stderr, "WaitForEventThreadTrigger took %ld seconds\n", now.tv_sec - startTime.tv_sec);
145   }
146   return triggerCount == 0;
147 }
148
149 } // namespace Test