[libamb] - added value quality, removed deprecated GetFoo call, made updateFrequency...
[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 }