AERA
time_core.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2025 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2025 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2025 Icelandic Institute for Intelligent Machines
9 //_/_/ http://www.iiim.is
10 //_/_/
11 //_/_/ Copyright (c) 2010-2012 Eric Nivel
12 //_/_/ Center for Analysis and Design of Intelligent Agents
13 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
14 //_/_/ http://cadia.ru.is
15 //_/_/
16 //_/_/ Part of this software was developed by Eric Nivel
17 //_/_/ in the HUMANOBS EU research project, which included
18 //_/_/ the following parties:
19 //_/_/
20 //_/_/ Autonomous Systems Laboratory
21 //_/_/ Technical University of Madrid, Spain
22 //_/_/ http://www.aslab.org/
23 //_/_/
24 //_/_/ Communicative Machines
25 //_/_/ Edinburgh, United Kingdom
26 //_/_/ http://www.cmlabs.com/
27 //_/_/
28 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
29 //_/_/ University of Lugano and SUPSI, Switzerland
30 //_/_/ http://www.idsia.ch/
31 //_/_/
32 //_/_/ Institute of Cognitive Sciences and Technologies
33 //_/_/ Consiglio Nazionale delle Ricerche, Italy
34 //_/_/ http://www.istc.cnr.it/
35 //_/_/
36 //_/_/ Dipartimento di Ingegneria Informatica
37 //_/_/ University of Palermo, Italy
38 //_/_/ http://diid.unipa.it/roboticslab/
39 //_/_/
40 //_/_/
41 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
42 //_/_/
43 //_/_/ Redistribution and use in source and binary forms, with or without
44 //_/_/ modification, is permitted provided that the following conditions
45 //_/_/ are met:
46 //_/_/ - Redistributions of source code must retain the above copyright
47 //_/_/ and collaboration notice, this list of conditions and the
48 //_/_/ following disclaimer.
49 //_/_/ - Redistributions in binary form must reproduce the above copyright
50 //_/_/ notice, this list of conditions and the following disclaimer
51 //_/_/ in the documentation and/or other materials provided with
52 //_/_/ the distribution.
53 //_/_/
54 //_/_/ - Neither the name of its copyright holders nor the names of its
55 //_/_/ contributors may be used to endorse or promote products
56 //_/_/ derived from this software without specific prior
57 //_/_/ written permission.
58 //_/_/
59 //_/_/ - CADIA Clause: The license granted in and to the software
60 //_/_/ under this agreement is a limited-use license.
61 //_/_/ The software may not be used in furtherance of:
62 //_/_/ (i) intentionally causing bodily injury or severe emotional
63 //_/_/ distress to any person;
64 //_/_/ (ii) invading the personal privacy or violating the human
65 //_/_/ rights of any person; or
66 //_/_/ (iii) committing or preparing for any act of war.
67 //_/_/
68 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
69 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
70 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
71 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
72 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
73 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
75 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
78 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
79 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
81 //_/_/ OF SUCH DAMAGE.
82 //_/_/
83 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
84 
85 #include "time_core.h"
86 #include "mem.h"
87 #include "init.h"
88 
89 using namespace std::chrono;
90 
91 namespace r_exec {
92 
93 thread_ret thread_function_call TimeCore::Run(void *args) {
94 
95  TimeCore *_this = ((TimeCore *)args);
96 
97  bool run = true;
98  while (run) {
99 
100  P<TimeJob> j = _Mem::Get()->pop_time_job();
101  if (j == NULL)
102  break;
103  if (!j->is_alive()) {
104 
105  j = NULL;
106  continue;
107  }
108 
109  Timestamp target = j->target_time_;
110  Timestamp next_target(microseconds(0));
111  if (target.time_since_epoch().count() == 0) // 0 means ASAP. Control jobs (shutdown) are caught here.
112  run = j->update(next_target);
113  else {
114 
115  auto time_to_wait = duration_cast<microseconds>(target - Now());
116  if (time_to_wait.count() == 0) // right on time: do the job.
117  run = j->update(next_target);
118  else if (time_to_wait.count() > 0) { // early: spawn a delegate to wait for the due time; delegate will die when done.
119 
120  DelegatedCore *d = new DelegatedCore(j->target_time_, time_to_wait, j);
121  d->start(DelegatedCore::Wait);
122  _Mem::Get()->register_time_job_latency(time_to_wait);
123  next_target = Timestamp(seconds(0));
124  } else { // late: do the job and report.
125 
126  run = j->update(next_target);
127  j->report(-time_to_wait);
128  }
129  }
130 
131  while (next_target.time_since_epoch().count() && run) {
132 
133  if (!j->is_alive())
134  break;
135 
136  auto time_to_wait = duration_cast<microseconds>(next_target - Now());
137  next_target = Timestamp(seconds(0));
138  if (time_to_wait.count() == 0) // right on time: do the job.
139  run = j->update(next_target);
140  else if (time_to_wait.count() > 0) { // early: spawn a delegate to wait for the due time; delegate will die when done.
141  // the delegate will handle the next target when it is known (call to update()).
142  DelegatedCore *d = new DelegatedCore(next_target, time_to_wait, j);
143  d->start(DelegatedCore::Wait);
144  } else { // late: do the job and report.
145 
146  run = j->update(next_target);
147  j->report(-time_to_wait);
148  }
149  }
150  j = NULL;
151  }
152 
153  thread_ret_val(0);
154 }
155 
157 
158 TimeCore::TimeCore() : Thread() {
159 }
160 
161 TimeCore::~TimeCore() {
162 }
163 
165 
166 thread_ret thread_function_call DelegatedCore::Wait(void *args) {
167 
168  _Mem::Get()->start_core();
169  DelegatedCore *_this = ((DelegatedCore *)args);
170 
171  auto time_to_wait = _this->time_to_wait_;
172  auto target_time = _this->target_time_;
173 
174 wait: _this->timer_.start(time_to_wait);
175  _this->timer_.wait();
176 
177  if (!_this->job_->is_alive())
178  goto end;
179 
180  if (_Mem::Get()->check_state() == _Mem::RUNNING) { // checks for shutdown that could have happened during the wait on timer.
181 
182  while (Now() < target_time); // early, we have to wait; on Windows: timers resolution in ms => poll.
183  target_time = Timestamp(seconds(0));
184  _this->job_->update(target_time);
185  }
186 
187 redo: if (target_time.time_since_epoch().count()) {
188 
189  if (!_this->job_->is_alive())
190  goto end;
191  if (_Mem::Get()->check_state() != _Mem::RUNNING) // checks for shutdown that could have happened during the last update().
192  goto end;
193 
194  time_to_wait = duration_cast<microseconds>(target_time - Now());
195  if (time_to_wait.count() == 0) { // right on time: do the job.
196 
197  _this->job_->update(target_time);
198  goto redo;
199  } else if (time_to_wait.count() < 0) { // late.
200 
201  _this->job_->update(target_time);
202  _this->job_->report(-time_to_wait);
203  goto redo;
204  } else
205  goto wait;
206 }
207 
208  end: _Mem::Get()->shutdown_core();
209  delete _this;
210  thread_ret_val(0);
211 }
212 
214 
215 DelegatedCore::DelegatedCore(Timestamp target_time, microseconds time_to_wait, TimeJob *j) : Thread(), target_time_(target_time), time_to_wait_(time_to_wait), job_(j) {
216 }
217 
218 DelegatedCore::~DelegatedCore() {
219 }
220 }
core::Thread
Definition: submodules/CoreLibrary/CoreLibrary/utils.h:159
core::P
Definition: base.h:103