reverted varianttype
[profile/ivi/automotive-message-broker.git] / plugins / common / thread.cpp
1 /*
2 Copyright (C) 2012 Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 /******************************************************************
20 *
21 *       CUtil for C++
22 *
23 *       File: Thread.cpp
24 *
25 *       Revision;
26 *
27 *       07/07/13
28 *               - first revision
29 ******************************************************************/
30
31 #include <errno.h>
32 #include <stdio.h>
33
34 #include "mutex.h"
35 #include "thread.h"
36 #include <stdlib.h>
37
38 ////////////////////////////////////////////////
39 // Thread Func
40 ////////////////////////////////////////////////
41
42 static CUtil::Mutex gMutex;
43 static int gActiveThreadCount(0);
44
45 static void *PosixThreadProc(void *param)
46 {
47         gMutex.lock();
48         ++gActiveThreadCount;
49         gMutex.unlock();
50
51         CUtil::Thread *thread = (CUtil::Thread *)param;
52         thread->run();
53
54         gMutex.lock();
55         --gActiveThreadCount;
56         LOG_INFO("PosixThreadProc() - active threads: " << gActiveThreadCount);
57         gMutex.unlock();
58         return 0;
59 }
60
61 namespace CUtil{
62 ////////////////////////////////////////////////
63 // Thread
64 ////////////////////////////////////////////////
65
66 Thread::Thread() :
67     thread(0),
68     runnableFlag(false)
69 {
70     pthread_cond_init( &cond, NULL );
71     pthread_mutex_init( &mutex, NULL );
72 }
73
74 bool Thread::start()
75 {
76     pthread_mutex_lock(&mutex);
77     if (runnableFlag) {// already running
78         pthread_mutex_unlock(&mutex);
79         return false;
80     }
81     // try to run
82     if (pthread_create(&thread, NULL/*&thread_attr*/, PosixThreadProc, this) != 0) {
83                 //pthread_attr_destroy(&thread_attr);
84         pthread_mutex_unlock(&mutex);
85                 return false;
86         }
87         //pthread_attr_destroy(&thread_attr);
88     runnableFlag = true;
89     pthread_mutex_unlock(&mutex);
90         return true;
91 }
92
93 Thread::~Thread()
94 {
95         stop();
96     pthread_cond_destroy( &cond );
97     pthread_mutex_destroy( &mutex );
98     thread = 0;
99 }
100
101 void Thread::stop()
102 {
103         if (setRunnableFlag(false) == true) {
104             if( thread != 0 ){
105             if (thread == pthread_self()){
106                 int s = pthread_detach(thread);
107                 ((void)s);// prevent compiler warning in RELEASE build
108                 LOG_MESSAGE("Thread::stop() - thread " << std::hex << int(thread) << std::dec << " detached, returned value was " << s);
109             }
110             else{
111                 int s = pthread_join(thread, NULL);
112                 if (s != 0){
113                     LOG_ERROR("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
114                 }
115                 else{
116                     LOG_MESSAGE("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
117                 }
118             }
119             thread = 0;
120                 }
121         }
122         return;
123 }
124
125 bool Thread::setRunnableFlag(bool flag)
126 {
127     pthread_mutex_lock(&mutex);
128     bool retval(runnableFlag);
129     runnableFlag = flag;
130
131     if(!runnableFlag)
132         pthread_cond_signal(&cond);
133     pthread_mutex_unlock(&mutex);
134     return retval;
135 }
136
137 bool Thread::isRunnable(long miliseconds)
138 {
139     bool runnable(false);
140
141     pthread_mutex_lock(&mutex);
142     if (miliseconds != 0){
143         wait(miliseconds);
144     }
145     runnable = runnableFlag;
146
147     pthread_mutex_unlock(&mutex);
148         return runnable;
149 }
150
151 bool Thread::wait( long miliseconds )
152 {
153     struct timespec abstime;
154     clock_gettime(CLOCK_REALTIME, &abstime);
155     abstime.tv_sec += ( miliseconds / 1000 );
156     miliseconds %= 1000;
157     abstime.tv_nsec += ( miliseconds * 1000000L ); // in nanoseconds
158     if ( abstime.tv_nsec > 1000000000L /* > 1s */ ){
159         abstime.tv_sec += 1; // +1s
160         abstime.tv_nsec -= 1000000000L; // -1s
161     }
162
163     int status = pthread_cond_timedwait( &cond, &mutex, &abstime );
164     return ( status == ETIMEDOUT );
165 }
166
167 }