2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <type_traits>
22 #include <dali-test-suite-utils.h>
23 #include <dali/devel-api/threading/conditional-wait.h>
24 #include <dali/devel-api/threading/thread.h>
26 using Dali::ConditionalWait;
29 namespace // for local variables to avoid name clashes
31 volatile int gGlobalValue = 0;
32 volatile bool gWorkerThreadWait = true;
33 enum ThreadState { INIT, RUN, TERMINATE } volatile gWorkerThreadState = INIT;
34 ConditionalWait* volatile gConditionalWait; // volatile pointer to a ConditionalWait object
36 class WorkerThreadNotify : public Thread
41 while( gWorkerThreadWait ) // wait till we can exit
43 gWorkerThreadState = RUN;
44 usleep( 1 ); // 1 microseconds
46 usleep( 200 ); // give other thread time to get to Wait
48 gConditionalWait->Notify();
49 gWorkerThreadState = TERMINATE;
53 volatile int gNotifyCount = 0;
54 class WorkerThreadNotifyN : public Thread
58 while( gNotifyCount > 0 )
60 gConditionalWait->Notify();
61 usleep( 10 ); // 10 microseconds between each notify
66 class WorkerThreadWaitN : public Thread
70 gConditionalWait->Wait();
76 int UtcConditionalWait1P(void)
78 tet_infoline("Testing ConditionalWait - scenario: wait - notify with 2 threads");
80 WorkerThreadNotify thread1;
82 gConditionalWait = new ConditionalWait();
83 gWorkerThreadWait = true;
84 DALI_TEST_EQUALS( INIT, gWorkerThreadState, TEST_LOCATION );
85 DALI_TEST_EQUALS( 0, gGlobalValue, TEST_LOCATION );
88 // wait till the thread is in run state
89 while( RUN != gWorkerThreadState )
91 usleep( 1 ); // 1 microsecond
93 // let worker continue and finish
94 gWorkerThreadWait = false;
95 gConditionalWait->Wait();
96 DALI_TEST_EQUALS( 1, gGlobalValue, TEST_LOCATION );
97 DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
99 // wait till the thread is terminated state
100 while( TERMINATE != gWorkerThreadState )
102 usleep( 1 ); // 1 microsecond
107 delete gConditionalWait;
111 int UtcConditionalWait2P(void)
113 tet_infoline("Testing ConditionalWait - scenario: notify without wait");
115 ConditionalWait wait;
116 DALI_TEST_EQUALS( 0u, wait.GetWaitCount(), TEST_LOCATION );
118 DALI_TEST_EQUALS( 0u, wait.GetWaitCount(), TEST_LOCATION );
124 int UtcConditionalWait3P(void)
126 tet_infoline("Testing ConditionalWait - scenario: wait - notify N times 2 threads");
129 gConditionalWait = new ConditionalWait();
132 WorkerThreadNotifyN thread1;
135 while( gNotifyCount > 0 )
137 gConditionalWait->Wait();
139 DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
140 usleep( 10 ); // 10 microseconds between each notify
142 DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
146 delete gConditionalWait;
150 int UtcConditionalWait4P(void)
152 tet_infoline("Testing ConditionalWait - scenario: wait - notify N times from 3 threads");
155 gConditionalWait = new ConditionalWait();
158 WorkerThreadNotifyN thread1;
160 WorkerThreadNotifyN thread2;
162 WorkerThreadNotifyN thread3;
165 while( gNotifyCount > 0 )
167 gConditionalWait->Wait();
169 DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
170 usleep( 10 ); // 10 microseconds between each notify
177 delete gConditionalWait;
181 int UtcConditionalWait5P(void)
183 tet_infoline("Testing ConditionalWait - scenario: 4 threads wait - notify once from 1 thread");
186 gConditionalWait = new ConditionalWait();
188 WorkerThreadWaitN thread1;
190 WorkerThreadWaitN thread2;
192 WorkerThreadWaitN thread3;
194 WorkerThreadWaitN thread4;
196 // wait till all child threads are waiting
197 while( gConditionalWait->GetWaitCount() < 4 )
200 // notify once, it will resume all threads
201 gConditionalWait->Notify();
208 DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
210 delete gConditionalWait;
214 int UtcConditionalWait6P(void)
216 tet_infoline("Testing ConditionalWait - scenario: 4 threads wait - notify once from 1 thread");
219 gConditionalWait = new ConditionalWait();
221 WorkerThreadWaitN thread1;
223 WorkerThreadWaitN thread2;
225 WorkerThreadWaitN thread3;
227 WorkerThreadWaitN thread4;
229 // wait till all child threads are waiting
230 while( gConditionalWait->GetWaitCount() < 4 )
233 // notify once but with a scoped lock, it will resume all threads
235 ConditionalWait::ScopedLock lock( *gConditionalWait );
236 gConditionalWait->Notify( lock );
244 DALI_TEST_EQUALS( 0u, gConditionalWait->GetWaitCount(), TEST_LOCATION );
246 delete gConditionalWait;
250 int UtcConditionalWaitNonCopyable(void)
252 // we want to make sure that ConditionalWait is not copyable (its copy constructor is not defined)
253 // this test will stop compiling if ConditionalWait has compiler generated copy constructor
254 static_assert( !__has_trivial_copy( ConditionalWait ), "ConditionalWait should NOT be copyable" );
256 DALI_TEST_CHECK( true );