General IRI utilities
thread.cpp
1 // Copyright (C) 2009-2010 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
2 // Author Sergi Hernandez (shernand@iri.upc.edu)
3 // All rights reserved.
4 //
5 // This file is part of iriutils
6 // iriutils is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
19 #include "threadexceptions.h"
20 #include "thread.h"
21 #include <exception>
22 #include <string.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <netdb.h>
27 
28 CThread::CThread(const std::string& id)
29 {
30  this->user_thread_function=NULL;
31  this->state=detached;
32  this->set_id(id);
33 }
34 
35 void CThread::attach(void *(*user_thread_function)(void *param),void *param)
36 {
37  this->access.enter();
38  if(user_thread_function==NULL)
39  {
40  this->access.exit();
41  /* handle exceptions */
42  throw CThreadException(_HERE_,"Invalid thread function",this->thread_id);
43  }
44  else
45  {
46  this->user_thread_function=user_thread_function;
47  this->param=param;
48  this->state=attached;
49  this->access.exit();
50  }
51 }
52 
53 void CThread::start(void)
54 {
55  int error;
56 
57  this->access.enter();
58  if(this->user_thread_function==NULL)
59  {
60  this->access.exit();
61  /* handle exceptions */
62  throw CThreadException(_HERE_,"The thread has not been attached to a function",this->thread_id);
63  }
64  else
65  {
66  if((error=pthread_create(&this->thread,NULL,this->thread_function,this))!=0)
67  {
68  this->access.exit();
69  /* handle exceptions */
70  throw CThreadException(_HERE_,"Impossible to start the thread",this->thread_id);
71  }
72  else
73  {
74  this->state=starting;
75  this->access.exit();
76  }
77  }
78 }
79 
80 void CThread::end(void)
81 {
82  int error;
83 
84  this->access.enter();
85  if(this->state==active || this->state==starting)
86  {
87  this->access.exit();
88  if((error=pthread_join(this->thread,NULL))!=0)
89  {
90  /* handle exceptions */
91  throw CThreadException(_HERE_,"Error while waiting the thread to end",this->thread_id);
92  }
93  this->access.enter();
94  this->state=attached;
95  }
96  this->access.exit();
97  /* otherwise do nothing */
98 }
99 
100 void CThread::kill(void)
101 {
102  int error;
103 
104  this->access.enter();
105  if(this->state==active || this->state==starting)
106  {
107  this->access.exit();
108  if((error=pthread_cancel(this->thread))!=0)
109  {
110  /* handle the exceptions */
111  if(error!=ESRCH)
112  throw CThreadException(_HERE_,"Error while cancelling the thread",this->thread_id);
113  //otherwise, the thread has already finished
114  }
115  if((error=pthread_join(this->thread,NULL))!=0)
116  {
117  /* handle exceptions */
118  throw CThreadException(_HERE_,"Error while waiting the thread to end",this->thread_id);
119  }
120  this->access.enter();
121  this->state=attached;
122  }
123  this->access.exit();
124 }
125 
126 void CThread::detach(void)
127 {
128  this->access.enter();
129  if(this->state==attached)
130  {
131  this->user_thread_function=NULL;
132  this->param=NULL;
133  this->state=detached;
134  }
135  this->access.exit();
136  /* otherwise do nothing */
137 }
138 
140 {
141  int tmp_state;
142 
143  this->access.enter();
144  tmp_state=this->state;
145  this->access.exit();
146 
147  return tmp_state;
148 }
149 
150 void CThread::set_id(const std::string& id)
151 {
152  if(id.size()==0)
153  {
154  /* handle exception */
155  throw CThreadException(_HERE_,"Invalid thread id","empty string");
156  }
157  else
158  this->thread_id=id;
159 }
160 
161 std::string CThread::get_id(void)
162 {
163  return this->thread_id;
164 }
165 
166 void *CThread::thread_function(void *param)
167 {
168  CThread *thread=(CThread *)param;
169 
170  thread->access.enter();
171  thread->state=active;
172  thread->access.exit();
173  thread->user_thread_function(thread->param);
174  pthread_exit(NULL);
175 }
176 
178 {
179  this->kill();
180  this->detach();
181 }
182 
183 
static void * thread_function(void *param)
Internal thread function.
Definition: thread.cpp:166
Implementation of a parallel thread of execution.
Definition: thread.h:76
std::string get_id(void)
Function to get the thread identifier.
Definition: thread.cpp:161
Thread exception class.
void attach(void *(*user_thread_function)(void *param), void *param)
Function to attach the user function of the thread.
Definition: thread.cpp:35
virtual ~CThread()
Destructor.
Definition: thread.cpp:177
int get_state(void)
Function to retrieve the state of the thread.
Definition: thread.cpp:139
void end(void)
Function to request the end of the execution of the thread.
Definition: thread.cpp:80
void detach(void)
Function to remove the assigned user function.
Definition: thread.cpp:126
void set_id(const std::string &id)
Function to set the thread identifier.
Definition: thread.cpp:150
void exit(void)
function to release the critical section
Definition: mutex.cpp:64
void enter(void)
function to request access to the critical section
Definition: mutex.cpp:35
void kill(void)
Function to immediatelly terminate the execution of the thread.
Definition: thread.cpp:100
void start(void)
Function to start the execution of the thread.
Definition: thread.cpp:53
CThread(const std::string &id)
Constructor.
Definition: thread.cpp:28