DALi Version 2.0.1
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-Mutex.cpp
1 /*
2  * Copyright (c) 2020 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
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>
22 #include <stdlib.h>
23 #include <unistd.h>
24
25 #include <iostream>
26 #include <type_traits>
27
28 using Dali::Mutex;
29 using Dali::Thread;
30
31 int UtcDaliMutexSingleThread(void)
32 {
33   tet_infoline("Testing Dali::Mutex in a single thread");
34
35   {
36     Mutex mutex1;
37     DALI_TEST_EQUALS(false, mutex1.IsLocked(), TEST_LOCATION);
38   }
39
40   {
41     Mutex             mutex2;
42     Mutex::ScopedLock lock(mutex2);
43     DALI_TEST_EQUALS(true, mutex2.IsLocked(), TEST_LOCATION);
44   }
45
46   Mutex mutex3;
47   {
48     Mutex::ScopedLock lock(mutex3);
49   }
50   DALI_TEST_EQUALS(false, mutex3.IsLocked(), TEST_LOCATION);
51
52   END_TEST;
53 }
54
55 namespace // for local variables to avoid name clashes
56 {
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,
61                             RUN,
62                             LOCKING,
63                             TERMINATE } gWorkerThreadState = INIT;
64 Mutex* volatile gGlobalValueMutex; // volatile pointer to a mutex object
65
66 class TestThread : public Thread
67 {
68   virtual void Run()
69   {
70     gWorkerThreadState = RUN;
71     {
72       Mutex::ScopedLock lock(*gGlobalValueMutex);
73       gWorkerThreadState = LOCKING;
74       gGlobalValue       = -1;
75       while(gWorkerThreadWait) // wait till we can exit
76       {
77         usleep(1); // 1 microsecond
78       }
79     }
80     gWorkerThreadState = TERMINATE;
81   }
82 };
83 } // namespace
84
85 int UtcDaliMutexMultiThread(void)
86 {
87   tet_infoline("Testing Dali::Mutex multithreaded");
88
89   gGlobalValueMutex = new Dali::Mutex();
90
91   TestThread thread1;
92   // initialize values
93   gGlobalValue      = 0;
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);
98
99   // lock the mutex
100   {
101     Mutex::ScopedLock lock(*gGlobalValueMutex);
102     DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
103     thread1.Start();
104     // wait till the thread is in run state
105     while(RUN != gWorkerThreadState)
106     {
107       usleep(1); // 1 microsecond
108     }
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
113   }
114   // now child thread is allowed to change the value
115   // wait till the thread is in locking state
116   while(LOCKING != gWorkerThreadState)
117   {
118     usleep(1); // 1 microsecond
119   }
120   // mutex is locked, but not by us, by the child thread
121   DALI_TEST_EQUALS(true, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
122   // value is changed
123   DALI_TEST_EQUALS(-1, gGlobalValue, TEST_LOCATION);
124   // let worker finish
125   gWorkerThreadWait = false;
126   // wait till the thread is terminated state
127   while(TERMINATE != gWorkerThreadState)
128   {
129     usleep(1); // 1 microsecond
130   }
131   DALI_TEST_EQUALS(false, gGlobalValueMutex->IsLocked(), TEST_LOCATION);
132   thread1.Join();
133
134   END_TEST;
135 }
136
137 int UtcDaliMutexNonCopyable(void)
138 {
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");
142
143   DALI_TEST_CHECK(true);
144   END_TEST;
145 }