MADARA  3.2.3
WorkerThread.cpp
Go to the documentation of this file.
1 #include "WorkerThread.h"
4 
5 #ifdef _MADARA_JAVA_
6 #include <jni.h>
7 #include "madara_jni.h"
9 #endif
10 
11 
12 #include <iostream>
13 #include <algorithm>
14 
15 namespace madara { namespace threads {
16 
18  const std::string & name,
19  BaseThread * thread,
22  double hertz)
23  : name_ (name), thread_ (thread), control_ (control), data_ (data),
24  hertz_ (hertz)
25 {
26  if (thread)
27  {
28  std::stringstream base_string;
29  base_string << name;
30 
31  thread->name = name;
32  thread->init_control_vars (control);
33 
35  base_string.str () + ".finished", control);
37  base_string.str () + ".started", control);
39  base_string.str () + ".hertz", control);
40 
41  finished_ = 0;
42  started_ = 0;
44  }
45 }
46 
48 {
49  try {
50  if (me_.joinable()) {
52  "WorkerThread::~WorkerThread(%s):" \
53  " thread wasn't joined before destruction\n", name_.c_str());
54  me_.detach();
55  }
56  }
57  catch (const std::system_error &e) {
59  "WorkerThread::~WorkerThread(%s):" \
60  " error trying to detach: %s\n", name_.c_str(), e.what());
61  }
62 }
63 
64 /*
65 void
66 WorkerThread::operator= (const WorkerThread & input)
67 {
68  if (this != &input)
69  {
70  this->name_ = input.name_;
71  this->thread_ = input.thread_;
72  this->control_ = input.control_;
73  this->data_ = input.data_;
74  this->finished_ = input.finished_;
75  this->started_ = input.started_;
76  this->new_hertz_ = input.new_hertz_;
77  this->hertz_ = input.hertz_;
78  }
79 }*/
80 
81 void
83 {
84 #ifndef _WIN32
85 #else
86  //result = 0;
87  //_beginthreadex(NULL, 0, worker_thread_windows_glue, (void*)this, 0, 0);
88 
89 #endif
90  try {
91  me_ = std::thread(&WorkerThread::svc, this);
92 
93  std::ostringstream os;
94  os << std::this_thread::get_id() << " spawned " << me_.get_id() << std::endl;
95 
97  "WorkerThread::WorkerThread(%s):" \
98  " thread started %s\n", name_.c_str (), os.str().c_str());
99  }
100  catch (const std::exception &e)
101  {
103  "WorkerThread::WorkerThread(%s):" \
104  " failed to create thread: %s\n", name_.c_str (), e.what ());
105  throw;
106  }
107 }
108 
109 int
111 {
113  "WorkerThread(%s)::svc:" \
114  " checking thread existence\n", name_.c_str ());
115 
116  if (thread_)
117  {
118  started_ = 1;
119 
120 #ifdef _MADARA_JAVA_
121  // try detaching one more time, just to make sure.
122  utility::java::Acquire_VM jvm (false);
123 #endif
124 
125  thread_->init (data_);
126 
127  {
129  utility::TimeValue next_epoch;
130  utility::Duration frequency;
131 
132  bool one_shot = true;
133  bool blaster = false;
134 
135  knowledge::VariableReference terminated;
137 
138  terminated = control_.get_ref (name_ + ".terminated");
139  paused = control_.get_ref (name_ + ".paused");
140 
141  // change thread frequency
142  change_frequency (hertz_, current, frequency, next_epoch,
143  one_shot, blaster);
144 
145  while (control_.get (terminated).is_false ())
146  {
148  "WorkerThread(%s)::svc:" \
149  " thread checking for pause\n", name_.c_str ());
150 
151  if (control_.get (paused).is_false ())
152  {
154  "WorkerThread(%s)::svc:" \
155  " thread calling run function\n", name_.c_str ());
156 
157  try {
158  thread_->run ();
159  } catch (const std::exception &e) {
161  "WorkerThread(%s)::svc:" \
162  " exception thrown: %s\n", name_.c_str (), e.what());
163  }
164  }
165 
166  if (one_shot)
167  break;
168 
169  // check for a change in frequency/hertz
170  if (new_hertz_ != hertz_)
171  {
173  current, frequency, next_epoch, one_shot, blaster);
174  }
175 
176  if (!blaster)
177  {
178  current = utility::get_time_value ();
179 
181  "WorkerThread(%s)::svc:" \
182  " thread checking for next hertz epoch\n", name_.c_str ());
183 
184  if (current < next_epoch)
185  utility::sleep (next_epoch - current);
186 
188  "WorkerThread(%s)::svc:" \
189  " thread past epoch\n", name_.c_str ());
190 
191  next_epoch += frequency;
192  }
193  } // end while !terminated
194 
196  "WorkerThread(%s)::svc:" \
197  " thread has been terminated\n", name_.c_str ());
198 
199  }
200 
202  "WorkerThread(%s)::svc:" \
203  " calling thread cleanup method\n", name_.c_str ());
204 
205  thread_->cleanup ();
206 
208  "WorkerThread(%s)::svc:" \
209  " deleting thread\n", name_.c_str ());
210 
212  "WorkerThread(%s)::svc:" \
213  " setting finished to 1\n", finished_.get_name ().c_str ());
214 
215  finished_ = 1;
216  }
217  else
218  {
220  "WorkerThread(%s)::svc:" \
221  " thread creation failed\n", name_.c_str ());
222  }
223 
224  return 0;
225 }
226 
227 } }
WorkerThread()
Default constructor.
Definition: WorkerThread.h:42
This class encapsulates attaching and detaching to a VM.
Definition: Acquire_VM.h:24
std::string get_name(void) const
Returns the name of the container.
void set_name(const std::string &var_name, KnowledgeBase &knowledge)
Sets the variable name that this refers to.
Definition: Integer.inl:58
knowledge::containers::Double new_hertz_
thread safe hertz reference
Definition: WorkerThread.h:148
~WorkerThread() noexcept
Destructor.
virtual void init_control_vars(knowledge::KnowledgeBase &control)
Initializes the Java thread implementation&#39;s control plane variables.
Definition: BaseThread.h:86
double hertz_
hertz rate for worker thread executions
Definition: WorkerThread.h:153
MADARA_EXPORT utility::Refcounter< logger::Logger > global_logger
void run(void)
Starts the thread, with entry point svc()
std::chrono::time_point< Clock > TimeValue
time point
Definition: Utility.h:36
Optimized reference to a variable within the knowledge base.
madara::knowledge::KnowledgeRecord get(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings(false))
Retrieves a knowledge value.
Provides a quality-of-service-enabled threading library.
Definition: BaseThread.h:27
double sleep(double sleep_time)
Sleeps for a certain amount of time.
Definition: Utility.cpp:619
TimeValue get_time_value(void)
Returns a time of day as a chrono time value If simtime feature is enabled, this may be simulation ti...
Definition: Utility.inl:243
std::thread me_
Assignment operator.
Definition: WorkerThread.h:94
static struct madara::knowledge::tags::string_t string
std::unique_ptr< BaseThread > thread_
the contained thread
Definition: WorkerThread.h:125
Abstract base class for implementing threads.
Definition: BaseThread.h:38
#define madara_logger_ptr_log(logger, level,...)
Fast version of the madara::logger::log method for Logger pointers.
Definition: Logger.h:32
This class provides a distributed knowledge base to users.
Definition: KnowledgeBase.h:45
std::string name_
the name of the contained thread
Definition: WorkerThread.h:122
void change_frequency(double hertz, utility::TimeValue &current, utility::Duration &frequency, utility::TimeValue &next_epoch, bool &one_shot, bool &blaster)
Changes the frequency given a hertz rate.
knowledge::containers::Integer started_
thread safe start flag that will be sent to the knowledge base on launch of the thread ...
Definition: WorkerThread.h:143
std::string name
The unique name of your thread.
Definition: BaseThread.h:96
knowledge::containers::Integer finished_
thread safe finished flag that will be sent to the knowledge base on completion of the thread ...
Definition: WorkerThread.h:137
knowledge::KnowledgeBase control_
the control plane to the knowledge base
Definition: WorkerThread.h:128
int svc(void)
Task loop.
knowledge::KnowledgeBase data_
the data plane (the knowledge base)
Definition: WorkerThread.h:131
Copyright (c) 2015 Carnegie Mellon University.
bool is_false(void) const
Checks to see if the record is false.
void set_name(const std::string &var_name, KnowledgeBase &knowledge)
Sets the variable name that this refers to.
Definition: Double.cpp:146
VariableReference get_ref(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings(false))
Atomically returns a reference to the variable.
std::chrono::nanoseconds Duration
default clock duration
Definition: Utility.h:30