Updated comments and fixed tabbing
[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
94 bool Thread::setPriority(int priority)
95 {
96     pthread_mutex_lock(&mutex);
97     if (!runnableFlag) {// not running yet or terminated already
98         pthread_mutex_unlock(&mutex);
99         return false;
100     }
101
102     priority = priority < 1  ? 1  : priority;
103     priority = priority < 99 ? priority : 99;
104
105     // set priority
106     struct sched_param pr;
107     pr.__sched_priority = priority;
108     if (pthread_setschedparam(thread, SCHED_FIFO, &pr) < 0)
109     {
110         pthread_mutex_unlock(&mutex);
111         return false;
112     }
113
114     pthread_mutex_unlock(&mutex);
115     return true;
116 }
117
118 Thread::~Thread()
119 {
120     stop();
121     pthread_cond_destroy( &cond );
122     pthread_mutex_destroy( &mutex );
123     thread = 0;
124 }
125
126 void Thread::stop()
127 {
128     if (setRunnableFlag(false) == true) {
129         if( thread != 0 ){
130             if (thread == pthread_self()){
131                 int s = pthread_detach(thread);
132                 ((void)s);// prevent compiler warning in RELEASE build
133                 LOG_MESSAGE("Thread::stop() - thread " << std::hex << int(thread) << std::dec << " detached, returned value was " << s);
134             }
135             else{
136                 int s = pthread_join(thread, NULL);
137                 if (s != 0){
138                     LOG_ERROR("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
139                 }
140                 else{
141                     LOG_MESSAGE("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
142                 }
143             }
144             thread = 0;
145         }
146     }
147     return;
148 }
149
150 bool Thread::setRunnableFlag(bool flag)
151 {
152     pthread_mutex_lock(&mutex);
153     bool retval(runnableFlag);
154     runnableFlag = flag;
155
156     if(!runnableFlag)
157         pthread_cond_signal(&cond);
158     pthread_mutex_unlock(&mutex);
159     return retval;
160 }
161
162 bool Thread::isRunnable(long miliseconds)
163 {
164     bool runnable(false);
165
166     pthread_mutex_lock(&mutex);
167     if (miliseconds != 0){
168         wait(miliseconds);
169     }
170     runnable = runnableFlag;
171
172     pthread_mutex_unlock(&mutex);
173     return runnable;
174 }
175
176 bool Thread::wait( long miliseconds )
177 {
178     struct timespec abstime;
179     clock_gettime(CLOCK_REALTIME, &abstime);
180     abstime.tv_sec += ( miliseconds / 1000 );
181     miliseconds %= 1000;
182     abstime.tv_nsec += ( miliseconds * 1000000L ); // in nanoseconds
183     if ( abstime.tv_nsec > 1000000000L /* > 1s */ ){
184         abstime.tv_sec += 1; // +1s
185         abstime.tv_nsec -= 1000000000L; // -1s
186     }
187
188     int status = pthread_cond_timedwait( &cond, &mutex, &abstime );
189     return ( status == ETIMEDOUT );
190 }
191
192 }