2 * Copyright (c) 2020 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.
18 #include <dali-test-suite-utils.h>
19 #include <dali/devel-api/threading/mutex.h>
20 #include <dali/devel-api/threading/thread.h>
21 #include <dali/public-api/dali-core.h>
26 #include <type_traits>
31 int UtcDaliMutexSingleThread(void)
33 tet_infoline("Testing Dali::Mutex in a single thread");
37 DALI_TEST_EQUALS(false, mutex1.IsLocked(), TEST_LOCATION);
42 Mutex::ScopedLock lock(mutex2);
43 DALI_TEST_EQUALS(true, mutex2.IsLocked(), TEST_LOCATION);
48 Mutex::ScopedLock lock(mutex3);
50 DALI_TEST_EQUALS(false, mutex3.IsLocked(), TEST_LOCATION);
55 namespace // for local variables to avoid name clashes
57 // make all these volatile to pre-empt any optimization screwing up the logic
58 volatile int gGlobalValue = 0;
59 volatile bool gWorkerThreadWait = true;
60 volatile enum ThreadState { INIT,
63 TERMINATE } gWorkerThreadState = INIT;
64 Mutex* volatile gGlobalValueMutex; // volatile pointer to a mutex object
66 class TestThread : public Thread
70 gWorkerThreadState = RUN;
72 Mutex::ScopedLock lock(*gGlobalValueMutex);
73 gWorkerThreadState = LOCKING;
75 while(gWorkerThreadWait) // wait till we can exit
77 usleep(1); // 1 microsecond
80 gWorkerThreadState = TERMINATE;
85 int UtcDaliMutexMultiThread(void)
87 tet_infoline("Testing Dali::Mutex multithreaded");
89 gGlobalValueMutex = new Dali::Mutex();
94 gWorkerThreadWait = true;
95 DALI_TEST_EQUALS(INIT, gWorkerThreadState, TEST_LOCATION);
96 DALI_TEST_EQUALS(0, gGlobalValue, TEST_LOCATION);
97 DALI_TEST_EQUALS(false, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
101 Mutex::ScopedLock lock(*gGlobalValueMutex);
102 DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
104 // wait till the thread is in run state
105 while(RUN != gWorkerThreadState)
107 usleep(1); // 1 microsecond
109 // now the thread is running and mutex is still locked by this thread so value is not changed
110 DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
111 DALI_TEST_EQUALS(0, gGlobalValue, TEST_LOCATION);
112 // drop out of scope, releases our lock
114 // now child thread is allowed to change the value
115 // wait till the thread is in locking state
116 while(LOCKING != gWorkerThreadState)
118 usleep(1); // 1 microsecond
120 // mutex is locked, but not by us, by the child thread
121 DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
123 DALI_TEST_EQUALS(-1, gGlobalValue, TEST_LOCATION);
125 gWorkerThreadWait = false;
126 // wait till the thread is terminated state
127 while(TERMINATE != gWorkerThreadState)
129 usleep(1); // 1 microsecond
131 DALI_TEST_EQUALS(false, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
137 int UtcDaliMutexNonCopyable(void)
139 // we want to make sure that mutex is not copyable (its copy constructor is not defined)
140 // this test will stop compiling if Mutex has compiler generated copy constructor
141 static_assert(!__has_trivial_copy(Mutex), "Mutex should NOT be copyable");
143 DALI_TEST_CHECK(true);