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