iotivity 0.9.0
[platform/upstream/iotivity.git] / service / soft-sensor-manager / SSMCore / src / Common / ThreadManager.h
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20 #ifndef _ThreadManager_H_
21 #define _ThreadManager_H_
22
23 #include "PlatformLayer.h"
24
25 static const OID OID_IThreadClient = { 0x6f379191, 0xd9f1, 0x480c, { 0xac, 0x23, 0xb2, 0x88, 0x9e, 0x69, 0x28, 0x7b } };
26 /**
27 * @class    IThreadClient
28 * @brief    IThreadClient Interface
29 *            This class represents thread client that called from worker thread.\n
30 *            The application who wants to use worker thread, inherit this interface
31 *
32 * @see
33 */
34 class IThreadClient : public IBase
35 {
36     public:
37         /**
38         * @fn     onExecute
39         * @brief Called when worker thread is ready execute message
40         *
41         * @param [in] void *pArg - Optional argument
42         *
43         * @return SSMRESULT
44         * @warning
45         * @exception
46         * @see
47         */
48         virtual void onExecute(void *pArg) = 0;
49
50         /**
51         * @fn     onTerminate
52         * @brief Called when worker thread has finished last executed message
53         *
54         * @param [in] void *pArg - Optional argument
55         *
56         * @return SSMRESULT
57         * @warning
58         * @exception
59         * @see
60         */
61         virtual void onTerminate(void *pArg) = 0;
62         virtual ~IThreadClient() {};
63 };
64
65 /**
66 * @class    CObjectMultiThreadModel
67 * @brief    CObjectMultiThreadModel Interface
68 *            This class represents declared CObject's threading model
69 *
70 * @see
71 */
72 class CObjectMultiThreadModel
73 {
74     public:
75         /**
76         * @fn     Increment
77         * @brief Called when reference counter need to increase
78         *
79         * @param [in] volatile unsigned long *p - Reference counter's pointer
80         *
81         * @return unsigned long
82         * @warning
83         * @exception
84         * @see
85         */
86         static unsigned long increment(volatile unsigned long *p)
87         {
88 #if defined(WIN32)
89             return InterlockedIncrement(p);
90 #elif defined(LINUX)
91             return __sync_add_and_fetch(p, 1);
92 #else
93 #error WIN32 or LINUX tag must be defined
94 #endif
95         }
96
97         /**
98         * @fn     decrement
99         * @brief Called when reference counter need to decrease
100         *
101         * @param [in] volatile unsigned long *p - Reference counter's pointer
102         *
103         * @return unsigned long
104         * @warning
105         * @exception
106         * @see
107         */
108         static unsigned long decrement(volatile unsigned long *p)
109         {
110 #if defined(WIN32)
111             return InterlockedDecrement(p);
112 #elif defined(LINUX)
113             return __sync_add_and_fetch(p, -1);
114 #else
115 #error WIN32 or LINUX tag must be defined
116 #endif
117         }
118 };
119
120 /**
121 * @class    CNullMutex
122 * @brief    CNullMutex Interface
123 *            This class represents mutex strategy
124 *
125 * @see
126 */
127 class CNullMutex
128 {
129     public:
130         /**
131         * @fn     lock
132         * @brief Called when current thread need to locked
133         *
134         * @param NONE
135         *
136         * @return NONE
137         * @warning
138         * @exception
139         * @see
140         */
141         void lock() {}
142
143         /**
144         * @fn     unlock
145         * @brief Called when current thread need to unlocked
146         *
147         * @param NONE
148         *
149         * @return NONE
150         * @warning
151         * @exception
152         * @see
153         */
154         void unlock() {}
155 };
156
157 /**
158 * @class    CAutoMutex
159 * @brief    CAutoMutex Interface
160 *            This class represents automated mutex class
161 *
162 * @see
163 */
164 template<typename T>
165 class CAutoMutex
166 {
167     public:
168         CAutoMutex(T &t) :
169             t_(t)
170         {
171             t_.lock();
172         }
173         ~CAutoMutex()
174         {
175             t_.unlock();
176         }
177
178     private:
179         T &t_;
180 };
181
182 /**
183 * @class    CSimpleMutex
184 * @brief    CSimpleMutex Interface
185 *            This class represents basic mutex class.\n
186 *            This mutex must support recursive locking mechanism
187 *
188 * @see
189 */
190 class CSimpleMutex
191 {
192     private:
193 #if defined(WIN32)
194         CRITICAL_SECTION m_criticalSection;
195 #elif defined(LINUX)
196         pthread_mutex_t         m_mutex;
197         pthread_mutexattr_t     m_mutexAttribute;
198 #else
199 #error WIN32 or LINUX tag must be defined
200 #endif
201
202     public:
203         CSimpleMutex();
204
205         ~CSimpleMutex();
206
207         /**
208         * @fn     lock
209         * @brief Lock current thread
210         *
211         * @param NONE
212         *
213         * @return NONE
214         * @warning
215         * @exception
216         * @see
217         */
218         void lock();
219
220         /**
221         * @fn     unlock
222         * @brief Unlock current thread
223         *
224         * @param NONE
225         *
226         * @return NONE
227         * @warning
228         * @exception
229         * @see
230         */
231         void unlock();
232 };
233
234 class CSemaphore
235 {
236     private:
237 #if defined(WIN32)
238         HANDLE hSemaphore;
239 #elif defined(LINUX)
240         sem_t hSemaphore;
241 #else
242 #error WIN32 or LINUX tag must be defined
243 #endif
244
245     public:
246         CSemaphore();
247
248         ~CSemaphore();
249
250         SSMRESULT initialize();
251
252         SSMRESULT destroy();
253
254         SSMRESULT take();
255
256         SSMRESULT give();
257 };
258
259
260 static const OID OID_IWorkerThread = { 0x12a67457, 0xce97, 0x41c4, { 0x90, 0xb8, 0xcc, 0x72, 0x5f, 0xc4, 0x40, 0x27 } };
261 /**
262 * @class    IWorkerThread
263 * @brief    IWorkerThread Interface
264 *            This class represents worker thread utility
265 *
266 * @see
267 */
268 class IWorkerThread : public IBase
269 {
270     public:
271         /**
272         * @fn     initialize
273         * @brief Initialize current worker thread
274         *
275         * @param NONE
276         *
277         * @return SSMRESULT
278         * @warning
279         * @exception
280         * @see
281         */
282         virtual SSMRESULT initialize() = 0;
283
284         /**
285         * @fn     terminate
286         * @brief Terminate current worker thread.\n
287         *         All remained tasks are destroyed after IThreadClient::OnTerminate called
288         *
289         * @param NONE
290         *
291         * @return SSMRESULT
292         * @warning
293         * @exception
294         * @see
295         */
296         virtual SSMRESULT terminate() = 0;
297
298         /**
299         * @fn     addTask
300         * @brief Add task to current worker thread.\n
301         *         Each task called only once
302         *
303         * @param [in] IThreadClient *pThreadClient - Implemented thread client class instance that called from worker thread.
304         * @param [in] void *param - Optional parameter that IThreadClient::OnExecute/OnTerminate can receive
305         *
306         * @return SSMRESULT
307         * @warning
308         * @exception
309         * @see
310         */
311         virtual SSMRESULT addTask(IThreadClient *pThreadClient, void *param) = 0;
312 };
313
314 /**
315 * @class    CWorkerThread
316 * @brief    CWorkerThread Interface
317 *            This class represents worker thread utility that holds one thread
318 *
319 * @see
320 */
321 class CWorkerThread :
322     public CObjectRoot<CObjectMultiThreadModel>
323     , public IWorkerThread
324 {
325     private:
326         struct ClientEntry
327         {
328             IThreadClient   *pClient;
329             void            *pArg;
330         };
331 #if defined(WIN32)
332         HANDLE m_hThread;
333 #elif defined(LINUX)
334         pthread_t m_hThread;
335 #else
336 #error WIN32 or LINUX tag must be defined
337 #endif
338         CSemaphore              m_semInit;
339         CSemaphore              m_semTerm;
340
341         CSimpleMutex            m_mtxClientEntry;
342         CSimpleMutex            m_mtxThreadTerm;
343         CSemaphore              m_semTask;
344
345         bool                    m_bThreadTerm;
346
347         std::list<ClientEntry>  m_ClientEntry;
348
349         bool getTask(ClientEntry *clientEntry);
350
351         void worker();
352
353         static void _worker(void *pArg)
354         {
355             CWorkerThread *pThread = (CWorkerThread *)pArg;
356             return pThread->worker();
357         }
358
359     public:
360         SSMRESULT finalConstruct();
361         void finalRelease();
362
363         SSMRESULT queryInterface(const OID &objectID, IBase **ppObject)
364         {
365             if (ppObject == NULL)
366                 return SSM_E_POINTER;
367
368             if (IsEqualOID(objectID, OID_IWorkerThread))
369             {
370                 IBase *pBase = (IWorkerThread *)this;
371                 pBase->addRef();
372                 *ppObject = pBase;
373                 return SSM_S_OK;
374             }
375
376             return SSM_E_NOINTERFACE;
377         }
378
379         /**
380         * @fn     initialize
381         * @brief Initialize current worker thread
382         *
383         * @param NONE
384         *
385         * @return SSMRESULT
386         * @warning
387         * @exception
388         * @see
389         */
390         SSMRESULT initialize();
391
392         /**
393         * @fn     terminate
394         * @brief Terminate current worker thread.\n
395         *         All remained tasks are destroyed after IThreadClient::OnTerminate called
396         *
397         * @param NONE
398         *
399         * @return SSMRESULT
400         * @warning
401         * @exception
402         * @see
403         */
404         SSMRESULT terminate();
405
406         /**
407         * @fn     addTask
408         * @brief Add task to current worker thread.\n
409         *         Each task called only once
410         *
411         * @param [in] IThreadClient *pThreadClient - Implemented thread client class instance that called from worker thread.
412         * @param [in] void *param - Optional parameter that IThreadClient::OnExecute/OnTerminate can receive
413         *
414         * @return SSMRESULT
415         * @warning
416         * @exception
417         * @see
418         */
419         SSMRESULT addTask(IThreadClient *pThreadClient, void *param);
420 };
421
422
423 static const OID OID_IThreadPool = { 0x53855605, 0xb2a0, 0x4a31, { 0xa2, 0x60, 0x36, 0x4d, 0x43, 0xc1, 0x2f, 0x96 } };
424 /**
425 * @class    IThreadPool
426 * @brief    IThreadPool Interface
427 *            This class represents worker thread utility
428 *
429 * @see
430 */
431 class IThreadPool : public IBase
432 {
433     public:
434         virtual SSMRESULT createWorkerThread(OUT IWorkerThread **ppWorkerThread) = 0;
435         virtual SSMRESULT destroyThreadPool() = 0;
436 };
437
438 /**
439 * @class    CThreadPool
440 * @brief    CThreadPool Interface
441 *            This class represents worker thread pool utility that can holds multiple thread
442 *
443 * @see
444 */
445 class CThreadPool :
446     public CObjectRoot<CObjectMultiThreadModel>
447     , public IThreadPool
448 {
449     private:
450         std::vector<IWorkerThread *> m_lstWorkerThread;
451
452     public:
453         SSMRESULT finalConstruct();
454         void finalRelease();
455
456         SSMRESULT queryInterface(const OID &objectID, IBase **ppObject)
457         {
458             if (ppObject == NULL)
459                 return SSM_E_POINTER;
460
461             if (IsEqualOID(objectID, OID_IThreadPool))
462             {
463                 IBase *pBase = this;
464                 pBase->addRef();
465                 *ppObject = pBase;
466                 return SSM_S_OK;
467             }
468
469             return SSM_E_NOINTERFACE;
470         }
471
472         SSMRESULT createWorkerThread(OUT IWorkerThread **ppWorkerThread);
473
474         SSMRESULT destroyThreadPool();
475 };
476
477 static const OID OID_ITasker = { 0x8f2b0b4f, 0xaab8, 0x4cbc, { 0x99, 0x1, 0x65, 0xde, 0x89, 0x82, 0x9f, 0x7a } };
478 /**
479 * @class    ITasker
480 * @brief    ITasker Interface
481 *            This class represents worker thread utility
482 *
483 * @see
484 */
485 class ITasker : public IBase
486 {
487     public:
488         virtual SSMRESULT addTask(IThreadClient *pThreadClient, void *param) = 0;
489 };
490
491 class CTasker :
492     public CObjectRoot<CObjectMultiThreadModel>
493     , public ITasker
494 {
495     private:
496         CObjectPtr<IThreadPool>     m_pThreadPool;
497         CObjectPtr<IWorkerThread>   m_pWorkerThread;
498
499     public:
500         SSMRESULT finalConstruct();
501         void finalRelease();
502
503         SSMRESULT queryInterface(const OID &objectID, IBase **ppObject)
504         {
505             if (ppObject == NULL)
506                 return SSM_E_POINTER;
507
508             if (IsEqualOID(objectID, OID_ITasker))
509             {
510                 IBase *pBase = this;
511                 pBase->addRef();
512                 *ppObject = pBase;
513                 return SSM_S_OK;
514             }
515
516             return SSM_E_NOINTERFACE;
517         }
518
519         SSMRESULT addTask(IThreadClient *pThreadClient, void *param);
520 };
521 #endif