Add an info log in Terminate()
[platform/framework/native/appfw.git] / inc / FBaseRtMutexGuard.h
1 //
2 // Copyright (c) 2012 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 * @file         FBaseRtMutexGuard.h
19 * @brief        This is the header file for the %MutexGuard class.
20 *
21 * This header file contains the declarations of the %MutexGuard class.
22 */
23
24 #ifndef _FBASE_RT_MUTEX_GUARD_H_
25 #define _FBASE_RT_MUTEX_GUARD_H_
26
27 #include <FBaseRtMutex.h>
28 #include <FBaseRtTypes.h>
29
30 namespace Tizen { namespace Base { namespace Runtime
31 {
32
33 /**
34 * @class        MutexGuard
35 * @brief        This class is the RAII style class for %Mutex class.
36 *
37 * @since 2.0
38 *
39 * The following example demonstrates how to use this %MutexGuard class
40 *
41 * @code
42 *
43 * #include <FBase.h>
44 * #include <FBaseRt.h>
45 *
46 * using namespace std;
47 * using namespace Tizen::Base::Runtime;
48 *
49 * class SynchronizedCounter
50 * {
51 * public:
52 *     explicit SynchronizedCounter(long long initialValue = 0)
53 *         : __m()
54 *         , __count(initialValue)
55 *     {
56 *         __m.Create();
57 *     }
58 *
59 *     SynchronizedCounter(const SynchronizedCounter& rhs)
60 *         : __m()
61 *         , __count(rhs.__count)
62 *     {
63 *         __m.Create();
64 *     }
65 *
66 *     SynchronizedCounter& operator =(SynchronizedCounter rhs)
67 *     {
68 *         __count = rhs.__count;
69 *         return *this;
70 *     }
71 *
72 *     SynchronizedCounter& operator ++()
73 *     {
74 *         IncrementImpl(1);
75 *         return *this;
76 *     }
77 *
78 *     SynchronizedCounter& operator --()
79 *     {
80 *         IncrementImpl(-1);
81 *         return *this;
82 *     }
83 *
84 *     bool TryToIncrement(void)
85 *     {
86 *         return TryToIncrementImpl(1);
87 *     }
88 *
89 *     bool TryToDecrement(void)
90 *     {
91 *         return TryToIncrementImpl(-1);
92 *     }
93 *
94 *     long long GetCount() const
95 *     {
96 *         return __count;
97 *     }
98 *
99 * private:
100 *     void IncrementImpl(int amount)
101 *     {
102 *         MutexGuard lock(__m);
103 *         __count += amount;
104 *     } // The acquired lock will be released when going out of scope
105 *
106 *     bool TryToIncrementImpl(int amount)
107 *     {
108 *         MutexGuard lock(__m, Try);    // Uses predefined Try const object for non-blocking mode locking
109 *         TryReturn(lock.IsLocked(), false, “Failed to lock mutex”);
110 *         __count += amount;
111 *         return true;
112 *     }
113 *
114 *     Mutex __m;
115 *     long long __count;
116 * };
117 *
118 * class MyThread
119 *     : public Thread
120 * {
121 * public:
122 *     static SynchronizedCounter counter;
123 *     static const long long LOOP_COUNT = 10000000;
124 *
125 *     virtual Object* Run(void)
126 *     {
127 *         for (long long i = 0; i < LOOP_COUNT; ++i)
128 *         {
129 *             ++counter;
130 *         }
131 *
132 *         return null;
133 *     }
134 * };
135 *
136 * SynchronizedCounter MyThread::counter;
137 *
138 * void
139 * ButtonPanel::OnActionPerformed(const Tizen::Ui::Control& source, int actionId)
140 * {
141 *     switch (actionId)
142 *     {
143 *     case ID_BUTTON:
144 *         {
145 *             static const int NUM_THREADS = 10;
146 *             MyThread thrs[NUM_THREADS];
147 *
148 *             __pLabel->SetText(L"Button is clicked!");
149 *             AppLog("Button is pressed!");
150 *
151 *             for (int i = 0; i < NUM_THREADS; ++i)
152 *             {
153 *                 thrs[i].Construct();
154 *                 thrs[i].Start();
155 *             }
156 *
157 *             for (int i = 0; i < NUM_THREADS; ++i)
158 *             {
159 *                 thrs[i].Join();
160 *             }
161 *
162 *             AppLog("Total Count = [%lld]", MyThread::counter.GetCount());
163 *             AppAssertf(MyThread::counter.GetCount() == NUM_THREADS * MyThread::LOOP_COUNT,
164 *                        "[Assert] Count is wrong");
165 *         }
166 *         break;
167 *     }
168 *     Invalidate(true);
169 * }
170 *
171 * @endcode
172 */
173
174 class MutexGuard
175 {
176 public:
177         /**
178         * This constructor acquires the lock in a blocking way.
179         *
180         * @since 2.0
181         *
182         * @param[in]    m       The %Mutex instance to be manipulated
183         * @remarks              The specific error code can be accessed using the GetLastResult() method.
184         * @see                  Mutex::Acquire() for detailed exceptions
185         */
186         MutexGuard(Mutex& m)
187                 : __m(m)
188                 , __locked(false)
189         {
190                 SetLastResult(Lock());
191         }
192
193         /**
194         * This constructor acquires the lock in a non-blocking way.
195         *
196         * @since 2.0
197         *
198         * @param[in]    m       The %Mutex instance to be manipulated
199         * @remarks              The specific error code can be accessed using the GetLastResult() method.
200         * @see                  Mutex::TryToAcquire() for detailed exceptions
201         */
202         MutexGuard(Mutex& m, TryTag)
203                 : __m(m)
204                 , __locked(false)
205         {
206                 SetLastResult(TryToLock());
207         }
208
209         /**
210         * This destructor releases the lock if acquired when going out of a scope
211         *
212         * @since 2.0
213         *
214         * @remarks      The specific error code can be accessed using the GetLastResult() method.
215         * @see          Mutex::Release() for detailed exceptions
216         */
217         ~MutexGuard(void)
218         {
219                 SetLastResult(Unlock());
220         }
221
222         /**
223         * Returns whether this instance owns the lock on the given mutex at constructor.
224         *
225         * @since 2.0
226         *
227         * @return       true if the lock is owned, @n
228         *                       false otherwise.
229         */
230         bool IsLocked(void) const
231         {
232                 return __locked;
233         }
234
235         /**
236         * Returns whether this instance owns the lock on the given mutex at constructor. @n
237         * Have same effects to calling IsLocked().
238         *
239         * @since 2.0
240         */
241         operator bool() const
242         {
243                 return IsLocked();
244         }
245
246         /**
247         * Acquires the lock manually on the given mutex at constructor in a blocking way
248         *
249         * @since 2.0
250         *
251         * @return       An error code.
252         * @see          Mutex::Acquire() for detailed exceptions
253         */
254         result Lock(void)
255         {
256                 return SetLockedAndReturn(__m.Acquire());
257         }
258
259         /**
260         * Acquires the lock manually on the given mutex at constructor in a non-blocking way
261         *
262         * @since 2.0
263         *
264         * @return       An error code.
265         * @see          Mutex::TryToAcquire() for detailed exceptions
266         */
267         result TryToLock(void)
268         {
269                 return SetLockedAndReturn(__m.TryToAcquire());
270         }
271
272         /**
273         * Releases the lock manually
274         *
275         * @since 2.0
276         *
277         * @return       An error code.
278         * @see          Mutex::Release() for detailed exceptions
279         */
280         result Unlock(void)
281         {
282                 result r = E_SUCCESS;
283                 if (__locked)
284                 {
285                         r = __m.Release();
286                         __locked = false;
287                 }
288                 return r;
289         }
290
291 private:
292         /**
293         * The implementation of this copy constructor is intentionally blank and declared as private 
294         * to prohibit copying of objects.
295         *
296         * @since 2.0
297         */
298         MutexGuard(const MutexGuard& rhs);
299
300         /**
301         * The implementation of this copy assignment operator is intentionally blank and declared as private
302         * to prohibit copying of objects.
303         *
304         * @since 2.0
305         */
306         MutexGuard& operator =(const MutexGuard& rhs);
307
308         // helper function
309         result SetLockedAndReturn(result r)
310         {
311                 __locked = (r == E_SUCCESS);
312                 return r;
313         }
314
315 private:
316         Mutex& __m;
317         bool __locked;
318 }; // MutexGuard
319
320 }}} // Tizen::Base::Runtime
321
322 #endif // _FBASE_RT_MUTEX_GUARD_H_