Orocos Real-Time Toolkit  2.9.0
TimerThread.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Wed Apr 17 16:01:31 CEST 2002 TimerThread.cpp
3 
4  TimerThread.cpp - description
5  -------------------
6  begin : Wed April 17 2002
7  copyright : (C) 2002 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 #include "TimerThread.hpp"
39 #include "PeriodicActivity.hpp"
40 
41 #include "rtt-config.h"
42 
43 #include "../Time.hpp"
44 #include "../Logger.hpp"
45 #include <algorithm>
46 #include "../os/MutexLock.hpp"
47 #include "../os/MainThread.hpp"
48 
49 namespace RTT {
50  using namespace extras;
51  using namespace base;
52  using os::MutexLock;
53  using namespace std;
54 
56 
58  {
59  return Instance(ORO_SCHED_RT, pri, per);
60  }
61 
62  TimerThreadPtr TimerThread::Instance(int scheduler, int pri, double per)
63  {
64  return Instance(scheduler, pri, per, 0);
65  }
66 
67  TimerThreadPtr TimerThread::Instance(int scheduler, int pri, double per, unsigned cpu_affinity)
68  {
69  // Since the period is stored as nsecs, we convert per to NS in order
70  // to get a match.
71  os::CheckPriority(scheduler, pri);
72  if (cpu_affinity == 0) cpu_affinity = os::MainThread::Instance()->getCpuAffinity();
73  TimerThreadList::iterator it = TimerThreads.begin();
74  while ( it != TimerThreads.end() ) {
75  TimerThreadPtr tptr = it->lock();
76  // detect old pointer.
77  if ( !tptr ) {
78  TimerThreads.erase(it);
79  it = TimerThreads.begin();
80  continue;
81  }
82  if ( tptr->getScheduler() == scheduler &&
83  tptr->getPriority() == pri &&
84  tptr->getPeriodNS() == Seconds_to_nsecs(per) &&
85  tptr->getCpuAffinity() == cpu_affinity ) {
86  return tptr;
87  }
88  ++it;
89  }
90  TimerThreadPtr ret( new TimerThread(scheduler, pri, "TimerThreadInstance", per, cpu_affinity) );
91  TimerThreads.push_back( ret );
92  return ret;
93  }
94 
95  TimerThread::TimerThread(int priority, const std::string& name, double periodicity, unsigned cpu_affinity)
96  : Thread( ORO_SCHED_RT, priority, periodicity, cpu_affinity, name), cleanup(false)
97  {
98  tasks.reserve(MAX_ACTIVITIES);
99  }
100 
101  TimerThread::TimerThread(int scheduler, int priority, const std::string& name, double periodicity, unsigned cpu_affinity)
102  : Thread(scheduler, priority, periodicity, cpu_affinity, name), cleanup(false)
103  {
104  tasks.reserve(MAX_ACTIVITIES);
105  }
106 
108  {
109  // make sure the thread does not run when we start deleting clocks...
110  this->stop();
111  }
112 
114  MutexLock lock(mutex);
115  if ( tasks.size() == MAX_ACTIVITIES ) {
116 // Logger::log() << Logger:: << "TimerThread : tasks queue full, failed to add Activity : "<< t << Logger::endl;
117  return false;
118  }
119  tasks.push_back( t );
120 // Logger::log() << Logger::Debug << "TimerThread : successfully started Activity : "<< t << Logger::endl;
121  return true;
122  }
123 
125  MutexLock lock(mutex);
126  ActivityList::iterator it = find(tasks.begin(), tasks.end(), t);
127  if ( it != tasks.end() ) {
128  *it = 0; // clear task away
129  cleanup = true;
130  return true;
131  }
132 // Logger::log() << Logger::Debug << "TimerThread : failed to stop Activity : "<< t->getPeriod() << Logger::endl;
133  return false;
134  }
135 
137  return true;
138  }
139 
141  MutexLock lock(mutex);
142 
143  for( ActivityList::iterator t_iter = tasks.begin(); t_iter != tasks.end(); ++t_iter)
144  if ( *t_iter )
145  (*t_iter)->stop(); // stop() calls us back to removeActivity (recursive mutex).
146  if ( cleanup )
147  this->reorderList();
148  }
149 
151  MutexLock lock(mutex);
152 
153  // The size of the tasks vector does not change during add/remove, thus
154  // t_iter is never invalidated.
155  for( ActivityList::iterator t_iter = tasks.begin(); t_iter != tasks.end(); ++t_iter)
156  if ( *t_iter ) {
157  (*t_iter)->step();
158  if (*t_iter)
159  (*t_iter)->work(RunnableInterface::TimeOut);
160  }
161 
162  if ( cleanup )
163  this->reorderList();
164  }
165 
167  // reorder the list to remove clear'ed tasks
168  ActivityList::iterator begin = tasks.begin();
169  // first zero :
170  PeriodicActivity* nullActivity = 0;
171  ActivityList::iterator it = tasks.begin();
172 
173  it = find( tasks.begin(), tasks.end(), nullActivity); // First zero
174  begin = it+1;
175  while ( it != tasks.end() ) {
176  // Look for first non-zero after 'it' :
177  while ( begin != tasks.end() && *begin == 0 )
178  ++begin;
179  if ( begin == tasks.end() ) { // if no task found after zero :
180 // Logger::log() << Logger::Error << "beginBefore resize :"<< tasks.size() << Logger::endl;
181  tasks.resize( it - tasks.begin() ); // cut out the items after 'it'
182 // Logger::log() << Logger::Error << "beginAfter resize :"<< tasks.size() << Logger::endl;
183  break; // This is our exit condition !
184  }
185  // first zero after begin :
186  ActivityList::iterator end = find ( begin, tasks.end(), nullActivity);
187  // if end == tasks.end() ==> next while will copy all
188  // if end != tasks.end() ==> next while will copy first zero's
189  while ( begin != end ) {
190  *it = *begin; // copy operation
191  ++begin;
192  ++it; // go to next slot to inspect.
193  }
194  }
195 
196  cleanup = false;
197  }
198 
199 
200 }
virtual ~TimerThread()
Destructor.
bool removeActivity(PeriodicActivity *t)
This Periodic Thread is meant for executing a PeriodicActivity object periodically.
Definition: TimerThread.hpp:69
static ThreadInterface * Instance()
Return an object which represents the main thread.
Definition: MainThread.cpp:58
A Thread object executes user code in its own thread.
Definition: Thread.hpp:109
std::vector< boost::weak_ptr< TimerThread > > TimerThreadList
A Boost weak pointer is used to store non-owning pointers to shared objects.
STL namespace.
static const unsigned int MAX_ACTIVITIES
Definition: TimerThread.hpp:76
bool CheckPriority(int &sched_type, int &priority)
Check if the scheduler type and priority match and adapt to a valid value.
Definition: threads.cpp:51
os::MutexRecursive mutex
A Activity can not create a activity of same priority from step().
boost::shared_ptr< TimerThread > TimerThreadPtr
TimerThread objects are reference counted such that when the last PeriodicActivity which uses it is d...
Definition: TimerThread.hpp:61
static TimerThreadList TimerThreads
All timer threads.
static TimerThreadPtr Instance(int priority, double periodicity)
Create a TimerThread with a given priority and periodicity, using the default scheduler, ORO_SCHED_RT.
Definition: TimerThread.cpp:57
bool addActivity(PeriodicActivity *t)
Add an Timer that will be ticked every execution period Once added, a timer can not be removed...
virtual bool initialize()
A PeriodicActivity is the general implementation of a Activity which has (realtime) periodic constrai...
virtual unsigned getCpuAffinity() const =0
nsecs Seconds_to_nsecs(const Seconds s)
Definition: Time.hpp:107
#define ORO_SCHED_RT
Definition: fosi.h:49
virtual bool stop()
Stop the Thread.
Definition: Thread.cpp:417
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
TimerThread(int priority, const std::string &name, double periodicity, unsigned cpu_affinity=~0)
Create a periodic Timer thread.
Definition: TimerThread.cpp:95
MutexLock is a scope based Monitor, protecting critical sections with a Mutex object through locking ...
Definition: MutexLock.hpp:51