2 * Copyright (c) 2021 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>
32 int UtcDaliMutexSingleThread(void)
34 tet_infoline("Testing Dali::Mutex in a single thread");
38 DALI_TEST_EQUALS(false, mutex1.IsLocked(), TEST_LOCATION);
43 Mutex::ScopedLock lock(mutex2);
44 DALI_TEST_EQUALS(true, mutex2.IsLocked(), TEST_LOCATION);
49 Mutex::ScopedLock lock(mutex3);
51 DALI_TEST_EQUALS(false, mutex3.IsLocked(), TEST_LOCATION);
55 Mutex mutex5(std::move(mutex4)); // move constructor
56 Mutex::ScopedLock lock(mutex5);
57 DALI_TEST_EQUALS(true, mutex5.IsLocked(), TEST_LOCATION);
62 mutex5 = std::move(mutex4); // move assignment
63 Mutex::ScopedLock lock(mutex5);
64 DALI_TEST_EQUALS(true, mutex5.IsLocked(), TEST_LOCATION);
70 namespace // for local variables to avoid name clashes
72 // make all these volatile to pre-empt any optimization screwing up the logic
73 volatile int gGlobalValue = 0;
74 volatile bool gWorkerThreadWait = true;
75 volatile enum ThreadState { INIT,
78 TERMINATE } gWorkerThreadState = INIT;
79 Mutex* volatile gGlobalValueMutex; // volatile pointer to a mutex object
81 class TestThread : public Thread
85 gWorkerThreadState = RUN;
87 Mutex::ScopedLock lock(*gGlobalValueMutex);
88 gWorkerThreadState = LOCKING;
90 while(gWorkerThreadWait) // wait till we can exit
92 usleep(1); // 1 microsecond
95 gWorkerThreadState = TERMINATE;
100 int UtcDaliMutexMultiThread(void)
102 tet_infoline("Testing Dali::Mutex multithreaded");
104 gGlobalValueMutex = new Dali::Mutex();
109 gWorkerThreadWait = true;
110 DALI_TEST_EQUALS(INIT, gWorkerThreadState, TEST_LOCATION);
111 DALI_TEST_EQUALS(0, gGlobalValue, TEST_LOCATION);
112 DALI_TEST_EQUALS(false, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
116 Mutex::ScopedLock lock(*gGlobalValueMutex);
117 DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
119 // wait till the thread is in run state
120 while(RUN != gWorkerThreadState)
122 usleep(1); // 1 microsecond
124 // now the thread is running and mutex is still locked by this thread so value is not changed
125 DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
126 DALI_TEST_EQUALS(0, gGlobalValue, TEST_LOCATION);
127 // drop out of scope, releases our lock
129 // now child thread is allowed to change the value
130 // wait till the thread is in locking state
131 while(LOCKING != gWorkerThreadState)
133 usleep(1); // 1 microsecond
135 // mutex is locked, but not by us, by the child thread
136 DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
138 DALI_TEST_EQUALS(-1, gGlobalValue, TEST_LOCATION);
140 gWorkerThreadWait = false;
141 // wait till the thread is terminated state
142 while(TERMINATE != gWorkerThreadState)
144 usleep(1); // 1 microsecond
146 DALI_TEST_EQUALS(false, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
152 int UtcDaliMutexNonCopyable(void)
154 // we want to make sure that mutex is not copyable (its copy constructor is not defined)
155 // this test will stop compiling if Mutex has compiler generated copy constructor
156 static_assert(!__has_trivial_copy(Mutex), "Mutex should NOT be copyable");
158 DALI_TEST_CHECK(true);