AERA
group.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 "group.h"
86 #include "factory.h"
87 #include "mem.h"
88 #include "pgm_controller.h"
89 #include "cst_controller.h"
90 #include "mdl_controller.h"
91 #include <math.h>
92 
93 using namespace std;
94 using namespace std::chrono;
95 using namespace r_code;
96 
97 namespace r_exec {
98 
99 inline bool Group::is_active_pgm(View *view) {
100 
101  return view->get_act() > get_act_thr() &&
102  get_c_sln() > get_c_sln_thr() &&
103  get_c_act() > get_c_act_thr(); // active ipgm/icpp_pgm/cst/mdl in a c-salient and c-active group.
104 }
105 
106 inline bool Group::is_eligible_input(View *view) {
107 
108  return view->get_sln() > get_sln_thr() &&
109  get_c_sln() > get_c_sln_thr() &&
110  get_c_act() > get_c_act_thr(); // active ipgm/icpp_pgm/cst/mdl in a c-salient and c-active group.
111 }
112 
113 View *Group::get_view(uint32 OID) {
114 
115  unordered_map<uint32, P<View> >::const_iterator it = other_views_.find(OID);
116  if (it != other_views_.end())
117  return it->second;
118  it = group_views_.find(OID);
119  if (it != group_views_.end())
120  return it->second;
121  it = ipgm_views_.find(OID);
122  if (it != ipgm_views_.end())
123  return it->second;
124  it = anti_ipgm_views_.find(OID);
125  if (it != anti_ipgm_views_.end())
126  return it->second;
127  it = input_less_ipgm_views_.find(OID);
128  if (it != input_less_ipgm_views_.end())
129  return it->second;
130  it = notification_views_.find(OID);
131  if (it != notification_views_.end())
132  return it->second;
133  return NULL;
134 }
135 
136 void Group::reset_ctrl_values() {
137 
138  sln_thr_changes_ = 0;
139  acc_sln_thr_ = 0;
140  act_thr_changes_ = 0;
141  acc_act_thr_ = 0;
142  vis_thr_changes_ = 0;
143  acc_vis_thr_ = 0;
144  c_sln_changes_ = 0;
145  acc_c_sln_ = 0;
146  c_act_changes_ = 0;
147  acc_c_act_ = 0;
148  c_sln_thr_changes_ = 0;
149  acc_c_sln_thr_ = 0;
150  c_act_thr_changes_ = 0;
151  acc_c_act_thr_ = 0;
152 }
153 
154 void Group::reset_stats() {
155 
156  avg_sln_ = 0;
157  high_sln_ = 0;
158  low_sln_ = 1;
159  avg_act_ = 0;
160  high_act_ = 0;
161  low_act_ = 1;
162 
163  sln_updates_ = 0;
164  act_updates_ = 0;
165 
166  if (sln_change_monitoring_periods_to_go_ <= 0) { // 0:reactivate, -1: activate.
167 
168  if (get_sln_chg_thr() < 1) // activate monitoring.
169  sln_change_monitoring_periods_to_go_ = get_sln_chg_prd();
170  } else if (get_sln_chg_thr() == 1) // deactivate monitoring.
171  sln_change_monitoring_periods_to_go_ = -1;
172  else
173  --sln_change_monitoring_periods_to_go_; // notification will occur when =0.
174 
175  if (act_change_monitoring_periods_to_go_ <= 0) { // 0:reactivate, -1: activate.
176 
177  if (get_act_chg_thr() < 1) // activate monitoring.
178  act_change_monitoring_periods_to_go_ = get_act_chg_prd();
179  } else if (get_act_chg_thr() == 1) // deactivate monitoring.
180  act_change_monitoring_periods_to_go_ = -1;
181  else
182  --act_change_monitoring_periods_to_go_; // notification will occur when =0.
183 }
184 
185 void Group::update_stats() {
186 
187  if (decay_periods_to_go_ > 0)
188  --decay_periods_to_go_;
189 
190  // auto restart: iff dcy_auto==1.
191  if (code(GRP_DCY_AUTO).asFloat()) {
192 
193  float32 period = code(GRP_DCY_PRD).asFloat();
194  if (decay_periods_to_go_ <= 0 && period > 0)
195  decay_periods_to_go_ = period;
196  }
197 
198  if (sln_updates_)
199  avg_sln_ = avg_sln_ / (float32)sln_updates_;
200  if (act_updates_)
201  avg_act_ = avg_act_ / (float32)act_updates_;
202 
203  code(GRP_AVG_SLN) = Atom::Float(avg_sln_);
204  code(GRP_AVG_ACT) = Atom::Float(avg_act_);
205  code(GRP_HIGH_SLN) = Atom::Float(high_sln_);
206  code(GRP_LOW_SLN) = Atom::Float(low_sln_);
207  code(GRP_HIGH_ACT) = Atom::Float(high_act_);
208  code(GRP_LOW_ACT) = Atom::Float(low_act_);
209 
210  if (sln_change_monitoring_periods_to_go_ == 0) {
211 
212  FOR_ALL_NON_NTF_VIEWS_BEGIN(this, v)
213 
214  float32 change = v->second->update_sln_delta();
215  if (fabs(change) > get_sln_chg_thr()) {
216 
217  uint16 ntf_grp_count = get_ntf_grp_count();
218  for (uint16 i = 1; i <= ntf_grp_count; ++i)
219  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkSlnChg(_Mem::Get(), v->second->object_, change)), false);
220  }
221 
222  FOR_ALL_NON_NTF_VIEWS_END
223  }
224 
225  if (act_change_monitoring_periods_to_go_ == 0) {
226 
227  FOR_ALL_NON_NTF_VIEWS_BEGIN(this, v)
228 
229  float32 change = v->second->update_act_delta();
230  if (fabs(change) > get_act_chg_thr()) {
231 
232  uint16 ntf_grp_count = get_ntf_grp_count();
233  for (uint16 i = 1; i <= ntf_grp_count; ++i)
234  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkActChg(_Mem::Get(), v->second->object_, change)), false);
235  }
236 
237  FOR_ALL_NON_NTF_VIEWS_END
238  }
239 }
240 
241 void Group::reset_decay_values() {
242 
243  sln_thr_decay_ = 0;
244  sln_decay_ = 0;
245  decay_periods_to_go_ = -1;
246  decay_percentage_per_period_ = 0;
247  decay_target_ = -1;
248 }
249 
250 float32 Group::update_sln_thr() {
251 
252  float32 percentage = code(GRP_DCY_PER).asFloat();
253  float32 period = code(GRP_DCY_PRD).asFloat();
254  if (percentage == 0 || period == 0)
255  reset_decay_values();
256  else {
257 
258  float32 percentage_per_period = percentage / period;
259  if (percentage_per_period != decay_percentage_per_period_ || code(GRP_DCY_TGT).asFloat() != decay_target_) { // recompute decay.
260 
261  decay_periods_to_go_ = period;
262  decay_percentage_per_period_ = percentage_per_period;
263  decay_target_ = code(GRP_DCY_TGT).asFloat();
264 
265  if (code(GRP_DCY_TGT).asFloat() == 0) {
266 
267  sln_thr_decay_ = 0;
268  sln_decay_ = percentage_per_period;
269  } else {
270 
271  sln_decay_ = 0;
272  sln_thr_decay_ = percentage_per_period;
273  }
274  }
275  }
276 
277  if (decay_periods_to_go_ > 0) {
278 
279  if (sln_thr_decay_ != 0)
280  mod_sln_thr(get_sln_thr()*sln_thr_decay_);
281  }
282 
283  if (sln_thr_changes_) {
284 
285  float32 new_sln_thr = get_sln_thr() + acc_sln_thr_ / sln_thr_changes_;
286  if (new_sln_thr < 0)
287  new_sln_thr = 0;
288  else if (new_sln_thr > 1)
289  new_sln_thr = 1;
290  code(GRP_SLN_THR) = r_code::Atom::Float(new_sln_thr);
291  }
292  acc_sln_thr_ = 0;
293  sln_thr_changes_ = 0;
294  return get_sln_thr();
295 }
296 
297 float32 Group::update_act_thr() {
298 
299  if (act_thr_changes_) {
300 
301  float32 new_act_thr = get_act_thr() + acc_act_thr_ / act_thr_changes_;
302  if (new_act_thr < 0)
303  new_act_thr = 0;
304  else if (new_act_thr > 1)
305  new_act_thr = 1;
306  code(GRP_ACT_THR) = r_code::Atom::Float(new_act_thr);
307  }
308  acc_act_thr_ = 0;
309  act_thr_changes_ = 0;
310  return get_act_thr();
311 }
312 
313 float32 Group::update_vis_thr() {
314 
315  if (vis_thr_changes_) {
316 
317  float32 new_vis_thr = get_vis_thr() + acc_vis_thr_ / vis_thr_changes_;
318  if (new_vis_thr < 0)
319  new_vis_thr = 0;
320  else if (new_vis_thr > 1)
321  new_vis_thr = 1;
322  code(GRP_VIS_THR) = r_code::Atom::Float(new_vis_thr);
323  }
324  acc_vis_thr_ = 0;
325  vis_thr_changes_ = 0;
326  return get_vis_thr();
327 }
328 
329 float32 Group::update_c_sln() {
330 
331  if (c_sln_changes_) {
332 
333  float32 new_c_sln = get_c_sln() + acc_c_sln_ / c_sln_changes_;
334  if (new_c_sln < 0)
335  new_c_sln = 0;
336  else if (new_c_sln > 1)
337  new_c_sln = 1;
338  code(GRP_C_SLN) = r_code::Atom::Float(new_c_sln);
339  }
340  acc_c_sln_ = 0;
341  c_sln_changes_ = 0;
342  return get_c_sln();
343 }
344 
345 float32 Group::update_c_act() {
346 
347  if (c_act_changes_) {
348 
349  float32 new_c_act = get_c_act() + acc_c_act_ / c_act_changes_;
350  if (new_c_act < 0)
351  new_c_act = 0;
352  else if (new_c_act > 1)
353  new_c_act = 1;
354  code(GRP_C_ACT) = r_code::Atom::Float(new_c_act);
355  }
356  acc_c_act_ = 0;
357  c_act_changes_ = 0;
358  return get_c_act();
359 }
360 
361 float32 Group::update_c_sln_thr() {
362 
363  if (c_sln_thr_changes_) {
364 
365  float32 new_c_sln_thr = get_c_sln_thr() + acc_c_sln_thr_ / c_sln_thr_changes_;
366  if (new_c_sln_thr < 0)
367  new_c_sln_thr = 0;
368  else if (new_c_sln_thr > 1)
369  new_c_sln_thr = 1;
370  code(GRP_C_SLN_THR) = r_code::Atom::Float(new_c_sln_thr);
371  }
372  acc_c_sln_thr_ = 0;
373  c_sln_thr_changes_ = 0;
374  return get_c_sln_thr();
375 }
376 
377 float32 Group::update_c_act_thr() {
378 
379  if (c_act_thr_changes_) {
380 
381  float32 new_c_act_thr = get_c_act_thr() + acc_c_act_thr_ / c_act_thr_changes_;
382  if (new_c_act_thr < 0)
383  new_c_act_thr = 0;
384  else if (new_c_act_thr > 1)
385  new_c_act_thr = 1;
386  code(GRP_C_ACT_THR) = r_code::Atom::Float(new_c_act_thr);
387  }
388  acc_c_act_thr_ = 0;
389  c_act_thr_changes_ = 0;
390  return get_c_act_thr();
391 }
392 
393 float32 Group::update_res(View *v) {
394 
395  if (v->object_->is_invalidated())
396  return 0;
397  float res = v->update_res();
398  if (!v->is_notification() && res > 0 && res < get_low_res_thr()) {
399 
400  uint16 ntf_grp_count = get_ntf_grp_count();
401  for (uint16 i = 1; i <= ntf_grp_count; ++i)
402  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkLowRes(_Mem::Get(), v->object_)), false);
403  }
404  return res;
405 }
406 
407 float32 Group::update_sln(View *v) {
408 
409  if (decay_periods_to_go_ > 0 && sln_decay_ != 0)
410  v->mod_sln(v->get_sln()*sln_decay_);
411 
412  float32 sln = v->update_sln(get_low_sln_thr(), get_high_sln_thr());
413  avg_sln_ += sln;
414  if (sln > high_sln_)
415  high_sln_ = sln;
416  else if (sln < low_sln_)
417  low_sln_ = sln;
418  ++sln_updates_;
419  if (!v->is_notification()) {
420 
421  if (v->periods_at_high_sln_ == get_sln_ntf_prd()) {
422 
423  v->periods_at_high_sln_ = 0;
424  uint16 ntf_grp_count = get_ntf_grp_count();
425  for (uint16 i = 1; i <= ntf_grp_count; ++i)
426  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkHighSln(_Mem::Get(), v->object_)), false);
427  } else if (v->periods_at_low_sln_ == get_sln_ntf_prd()) {
428 
429  v->periods_at_low_sln_ = 0;
430  uint16 ntf_grp_count = get_ntf_grp_count();
431  for (uint16 i = 1; i <= ntf_grp_count; ++i)
432  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkLowSln(_Mem::Get(), v->object_)), false);
433  }
434  }
435  return sln;
436 }
437 
438 float32 Group::update_act(View *v) {
439 
440  float32 act = v->update_act(get_low_act_thr(), get_high_act_thr());
441  avg_act_ += act;
442  if (act > high_act_)
443  high_act_ = act;
444  else if (act < low_act_)
445  low_act_ = act;
446  ++act_updates_;
447  if (!v->is_notification()) {
448 
449  if (v->periods_at_high_act_ == get_act_ntf_prd()) {
450 
451  v->periods_at_high_act_ = 0;
452  uint16 ntf_grp_count = get_ntf_grp_count();
453  for (uint16 i = 1; i <= ntf_grp_count; ++i)
454  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkHighAct(_Mem::Get(), v->object_)), false);
455  } else if (v->periods_at_low_act_ == get_act_ntf_prd()) {
456 
457  v->periods_at_low_act_ = 0;
458  uint16 ntf_grp_count = get_ntf_grp_count();
459  for (uint16 i = 1; i <= ntf_grp_count; ++i)
460  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkLowAct(_Mem::Get(), v->object_)), false);
461  }
462  }
463  return act;
464 }
465 
467 
468 bool Group::load(View *view, Code *object) {
469 
470  switch (object->code(0).getDescriptor()) {
471  case Atom::GROUP: {
472  group_views_[view->get_oid()] = view;
473 
474  // init viewing_group.
475  bool viewing_c_active = get_c_act() > get_c_act_thr();
476  bool viewing_c_salient = get_c_sln() > get_c_sln_thr();
477  bool viewed_visible = view->get_vis() > get_vis_thr();
478  if (viewing_c_active && viewing_c_salient && viewed_visible) // visible group in a c-salient, c-active group.
479  ((Group *)object)->viewing_groups_[this] = view->get_cov(); // init the group's viewing groups.
480  break;
481  }case Atom::INSTANTIATED_PROGRAM: {
482  ipgm_views_[view->get_oid()] = view;
483  PGMController *c = new PGMController(view); // now will be added to the deadline at start time.
484  view->controller_ = c;
485  if (is_active_pgm(view))
486  c->gain_activation();
487  break;
488  }case Atom::INSTANTIATED_INPUT_LESS_PROGRAM: {
489  input_less_ipgm_views_[view->get_oid()] = view;
490  InputLessPGMController *c = new InputLessPGMController(view); // now will be added to the deadline at start time.
491  view->controller_ = c;
492  if (is_active_pgm(view))
493  c->gain_activation();
494  break;
495  }case Atom::INSTANTIATED_ANTI_PROGRAM: {
496  anti_ipgm_views_[view->get_oid()] = view;
497  AntiPGMController *c = new AntiPGMController(view); // now will be added to the deadline at start time.
498  view->controller_ = c;
499  if (is_active_pgm(view))
500  c->gain_activation();
501  break;
502  }case Atom::INSTANTIATED_CPP_PROGRAM: {
503  ipgm_views_[view->get_oid()] = view;
504  Controller *c = CPPPrograms::New(Utils::GetString<Code>(view->object_, ICPP_PGM_NAME), view); // now will be added to the deadline at start time.
505  if (!c)
506  return false;
507  view->controller_ = c;
508  if (is_active_pgm(view))
509  c->gain_activation();
510  break;
511  }case Atom::COMPOSITE_STATE: {
512  ipgm_views_[view->get_oid()] = view;
513  CSTController *c = new CSTController(view);
514  view->controller_ = c;
515  c->set_secondary_host(get_secondary_group());
516  if (is_active_pgm(view))
517  c->gain_activation();
518 #ifdef WITH_DETAIL_OID
519  OUTPUT_LINE(MDL_OUT, "load cst " << view->object_->get_oid() <<
520  ", CSTController(" + to_string(c->get_detail_oid()) + ")");
521 #endif
522  break;
523  }case Atom::MODEL: {
524  ipgm_views_[view->get_oid()] = view;
525  bool inject_in_secondary_group;
526  MDLController *c = MDLController::New(view, inject_in_secondary_group);
527  view->controller_ = c;
528  if (inject_in_secondary_group) {
529  Group* secondary_group = get_secondary_group();
530  // We don't expect the secondary_group to be NULL, but check anyway.
531  if (secondary_group)
532  secondary_group->load_secondary_mdl_controller(view);
533  }
534  if (is_active_pgm(view))
535  c->gain_activation();
536 #ifdef WITH_DETAIL_OID
537  OUTPUT_LINE(MDL_OUT, "load mdl " << view->object_->get_oid() <<
538  ", MDLController(" + to_string(c->get_detail_oid()) + ") strength:" <<
539  view->object_->code(MDL_STRENGTH).asFloat() << " cnt:" << view->object_->code(MDL_CNT).asFloat() <<
540  " sr:" << view->object_->code(MDL_SR).asFloat());
541 #endif
542  break;
543  }case Atom::MARKER: // populate the marker set of the referenced objects.
544  for (uint32 i = 0; i < object->references_size(); ++i)
545  object->get_reference(i)->markers_.push_back(object);
546  other_views_[view->get_oid()] = view;
547  break;
548  case Atom::OBJECT:
549  other_views_[view->get_oid()] = view;
550  break;
551  }
552 
553  return true;
554 }
555 
556 void Group::update(Timestamp planned_time) {
557 
558  enter();
559 
560  if (this != _Mem::Get()->get_root() && views_.size() == 0) {
561 
562  invalidate();
563  leave();
564  return;
565  }
566 
567  auto now = Now();
568  newly_salient_views_.clear();
569 
570  // execute pending operations.
571  for (uint32 i = 0; i < pending_operations_.size(); ++i) {
572 
573  pending_operations_[i]->execute(this);
574  delete pending_operations_[i];
575  }
576  pending_operations_.clear();
577 
578  // update group's ctrl values.
579  update_sln_thr(); // applies decay on sln thr.
580  update_act_thr();
581  update_vis_thr();
582 
583  GroupState state(get_sln_thr(), get_c_act() > get_c_act_thr(), update_c_act() > get_c_act_thr(), get_c_sln() > get_c_sln_thr(), update_c_sln() > get_c_sln_thr());
584 
585  reset_stats();
586 
587  FOR_ALL_VIEWS_BEGIN_NO_INC(this, v)
588 
589  if (v->second->object_->is_invalidated()) // no need to update the view set.
590  delete_view(v);
591  else {
592 
593  auto ijt = v->second->get_ijt();
594  if (ijt >= planned_time) { // in case the update happens later than planned, don't touch views that were injected after the planned update time: update next time.
595 
596  ++v;
597  continue;
598  }
599 
600  float32 res = update_res(v->second); // update resilience: decrement res by 1 in addition to the accumulated changes.
601  if (res > 0) {
602 
603  _update_saliency(&state, v->second); // apply decay.
604 
605  switch (v->second->object_->code(0).getDescriptor()) {
606  case Atom::GROUP:
607  _update_visibility(&state, v->second);
608  break;
609  case Atom::NULL_PROGRAM:
610  case Atom::INSTANTIATED_PROGRAM:
611  case Atom::INSTANTIATED_ANTI_PROGRAM:
612  case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
613  case Atom::INSTANTIATED_CPP_PROGRAM:
614  case Atom::COMPOSITE_STATE:
615  case Atom::MODEL:
616  _update_activation(&state, v->second);
617  break;
618  }
619  ++v;
620  } else { // view has no resilience: delete it from the group.
621 
622  v->second->delete_from_object();
623  delete_view(v);
624  }
625  }
626  FOR_ALL_VIEWS_END
627 
628  if (state.is_c_salient)
629  cov();
630 
631  // build reduction jobs.
632  std::multiset<P<View>, _View::Less>::const_iterator v;
633  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
634  inject_reduction_jobs(*v);
635 
636  if (state.is_c_active && state.is_c_salient) { // build signaling jobs for new ipgms.
637 
638  for (uint32 i = 0; i < new_controllers_.size(); ++i) {
639 
640  switch (new_controllers_[i]->get_object()->code(0).getDescriptor()) {
641  case Atom::INSTANTIATED_ANTI_PROGRAM: { // inject signaling jobs for |ipgm (tsc).
642  P<TimeJob> j = new AntiPGMSignalingJob((r_exec::View *)new_controllers_[i]->get_view(), now + Utils::GetDuration<Code>(new_controllers_[i]->get_object(), IPGM_TSC));
643  _Mem::Get()->push_time_job(j);
644  break;
645  }case Atom::INSTANTIATED_INPUT_LESS_PROGRAM: { // inject a signaling job for an input-less pgm.
646 
647  P<TimeJob> j = new InputLessPGMSignalingJob((r_exec::View *)new_controllers_[i]->get_view(), now + Utils::GetDuration<Code>(new_controllers_[i]->get_object(), IPGM_TSC));
648  _Mem::Get()->push_time_job(j);
649  break;
650  }
651  }
652  }
653 
654  new_controllers_.clear();
655  }
656 
657  update_stats(); // triggers notifications.
658 
659  if (get_upr() > 0) { // inject the next update job for the group.
660 
661  P<TimeJob> j = new UpdateJob(this, planned_time + get_upr()*Utils::GetBasePeriod());
662  _Mem::Get()->push_time_job(j);
663  }
664 
665  leave();
666 }
667 
668 void Group::_update_saliency(GroupState *state, View *view) {
669 
670  float32 view_old_sln = view->get_sln();
671  bool wiew_was_salient = view_old_sln > state->former_sln_thr;
672  float32 view_new_sln = update_sln(view);
673  bool wiew_is_salient = view_new_sln > get_sln_thr();
674 
675  if (state->is_c_salient) {
676 
677  if (wiew_is_salient) {
678 
679  switch (view->get_sync()) {
680  case View::SYNC_ONCE:
681  case View::SYNC_ONCE_AXIOM:
682  case View::SYNC_PERIODIC:
683  if (!wiew_was_salient) // sync on front: crosses the threshold upward: record as a newly salient view.
684  newly_salient_views_.insert(view);
685  break;
686  case View::SYNC_HOLD:
687  case View::SYNC_AXIOM: // sync on state: treat as if it was a new injection.
688  view->set_ijt(Now());
689  newly_salient_views_.insert(view);
690  break;
691  }
692  }
693 
694  // inject sln propagation jobs.
695  // the idea is to propagate sln changes when a view "occurs to the mind", i.e. becomes more salient in a group and is eligible for reduction in that group.
696  // - when a view is now salient because the group becomes c-salient, no propagation;
697  // - when a view is now salient because the group's sln_thr gets lower, no propagation;
698  // - propagation can occur only if the group is c_active. For efficiency reasons, no propagation occurs even if some of the group's viewing groups are c-active and c-salient.
699  if (state->is_c_active)
700  _initiate_sln_propagation(view->object_, view_new_sln - view_old_sln, get_sln_thr());
701  }
702 }
703 
704 void Group::_update_visibility(GroupState *state, View *view) {
705 
706  bool view_was_visible = view->get_vis() > get_vis_thr();
707  bool view_is_visible = view->update_vis() > get_vis_thr();
708  bool cov = view->get_cov();
709 
710  // update viewing groups.
711  if (state->was_c_active && state->was_c_salient) {
712 
713  if (!state->is_c_active || !state->is_c_salient) // group is not c-active and c-salient anymore: unregister as a viewing group.
714  ((Group *)view->object_)->viewing_groups_.erase(this);
715  else { // group remains c-active and c-salient.
716 
717  if (!view_was_visible) {
718 
719  if (view_is_visible) // newly visible view.
720  ((Group *)view->object_)->viewing_groups_[this] = cov;
721  } else {
722 
723  if (!view_is_visible) // the view is no longer visible.
724  ((Group *)view->object_)->viewing_groups_.erase(this);
725  else // the view is still visible, cov might have changed.
726  ((Group *)view->object_)->viewing_groups_[this] = cov;
727  }
728  }
729  } else if (state->is_c_active && state->is_c_salient) { // group becomes c-active and c-salient.
730 
731  if (view_is_visible) // update viewing groups for any visible group.
732  ((Group *)view->object_)->viewing_groups_[this] = cov;
733  }
734 }
735 
736 void Group::_update_activation(GroupState *state, View *view) {
737 
738  bool view_was_active = view->get_act() > get_act_thr();
739  bool view_is_active = update_act(view) > get_act_thr();
740 
741  // kill newly inactive controllers, register newly active ones.
742  if (state->was_c_active && state->was_c_salient) {
743 
744  if (!state->is_c_active || !state->is_c_salient) // group is not c-active and c-salient anymore: kill the view's controller.
745  view->controller_->lose_activation();
746  else { // group remains c-active and c-salient.
747 
748  if (!view_was_active) {
749 
750  if (view_is_active) { // register the controller for the newly active ipgm view.
751 
752  view->controller_->gain_activation();
753  new_controllers_.push_back(view->controller_);
754  }
755  } else {
756 
757  if (!view_is_active) // kill the newly inactive ipgm view's overlays.
758  view->controller_->lose_activation();
759  }
760  }
761  } else if (state->is_c_active && state->is_c_salient) { // group becomes c-active and c-salient.
762 
763  if (view_is_active) { // register the controller for any active ipgm view.
764 
765  view->controller_->gain_activation();
766  new_controllers_.push_back(view->controller_);
767  }
768  }
769 }
770 
772 
773 void Group::_initiate_sln_propagation(Code *object, float32 change, float32 source_sln_thr) const {
774 
775  if (fabs(change) > object->get_psln_thr()) {
776 
777  vector<Code *> path;
778  path.push_back(object);
779 
780  if (object->code(0).getDescriptor() == Atom::MARKER) { // if marker, propagate to references.
781 
782  for (uint16 i = 0; i < object->references_size(); ++i)
783  _propagate_sln(object->get_reference(i), change, source_sln_thr, path);
784  }
785 
786  // propagate to markers
787  object->acq_markers();
789  for (m = object->markers_.begin(); m != object->markers_.end(); ++m)
790  _propagate_sln(*m, change, source_sln_thr, path);
791  object->rel_markers();
792  }
793 }
794 
795 void Group::_initiate_sln_propagation(Code *object, float32 change, float32 source_sln_thr, vector<Code *> &path) const {
796 
797  if (fabs(change) > object->get_psln_thr()) {
798 
799  // prevent loops.
800  for (uint32 i = 0; i < path.size(); ++i)
801  if (path[i] == object)
802  return;
803  path.push_back(object);
804 
805  if (object->code(0).getDescriptor() == Atom::MARKER) // if marker, propagate to references.
806  for (uint16 i = 0; i < object->references_size(); ++i)
807  _propagate_sln(object->get_reference(i), change, source_sln_thr, path);
808 
809  // propagate to markers
810  object->acq_markers();
812  for (m = object->markers_.begin(); m != object->markers_.end(); ++m)
813  _propagate_sln(*m, change, source_sln_thr, path);
814  object->rel_markers();
815  }
816 }
817 
818 void Group::_propagate_sln(Code *object, float32 change, float32 source_sln_thr, vector<Code *> &path) const {
819 
820  if (object == _Mem::Get()->get_root())
821  return;
822 
823  // prevent loops.
824  for (uint32 i = 0; i < path.size(); ++i)
825  if (path[i] == object)
826  return;
827  path.push_back(object);
828 
829  P<TimeJob> j = new SaliencyPropagationJob(object, change, source_sln_thr, Timestamp(seconds(0)));
830  _Mem::Get()->push_time_job(j);
831 
832  _initiate_sln_propagation(object, change, source_sln_thr, path);
833 }
834 
836 
837 void Group::inject_hlps(vector<View *> &views) {
838 
839  enter();
840 
841  vector<View *>::const_iterator view;
842  for (view = views.begin(); view != views.end(); ++view) {
843 
844  Atom a = (*view)->object_->code(0);
845  switch (a.getDescriptor()) {
846  case Atom::COMPOSITE_STATE: {
847  ipgm_views_[(*view)->get_oid()] = *view;
848  CSTController *c = new CSTController(*view);
849  (*view)->controller_ = c;
850  c->set_secondary_host(get_secondary_group());
851  string controllerInfo;
852 #ifdef WITH_DETAIL_OID
853  controllerInfo = ", CSTController(" + to_string(c->get_detail_oid()) + ")";
854 #endif
855  OUTPUT_LINE(CST_OUT, Utils::RelativeTime(Now()) << " -> cst " << (*view)->object_->get_oid() << controllerInfo);
856  break;
857  }
858  case Atom::MODEL: {
859  ipgm_views_[(*view)->get_oid()] = *view;
860  bool inject_in_secondary_group;
861  MDLController *c = MDLController::New(*view, inject_in_secondary_group);
862  (*view)->controller_ = c;
863  if (inject_in_secondary_group)
864  get_secondary_group()->inject_secondary_mdl_controller(*view);
865  string controllerInfo;
866 #ifdef WITH_DETAIL_OID
867  controllerInfo = ", MDLController(" + to_string(c->get_detail_oid()) + ")";
868 #endif
869  OUTPUT_LINE(MDL_OUT, Utils::RelativeTime(Now()) << " -> mdl " << (*view)->object_->get_oid() <<
870  " strength:" << (*view)->object_->code(MDL_STRENGTH).asFloat() << " cnt:" <<
871  (*view)->object_->code(MDL_CNT).asFloat() << " sr:" << (*view)->object_->code(MDL_SR).asFloat() << controllerInfo);
872  break;
873  }
874  }
875  (*view)->set_ijt(Now());
876  }
877 
878  for (view = views.begin(); view != views.end(); ++view) {
879 
880  if (is_active_pgm(*view)) {
881 
882  (*view)->controller_->gain_activation();
883  std::multiset<P<View>, _View::Less>::const_iterator v;
884  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
885  (*view)->controller_->_take_input(*v); // view will be copied.
886  }
887  }
888 
889  leave();
890 }
891 
892 void Group::inject(View *view) { // the view can hold anything but groups and notifications.
893 
894  enter();
895 
896  Atom a = view->object_->code(0);
897  auto now = Now();
898  view->set_ijt(now);
899  switch (a.getDescriptor()) {
900  case Atom::NULL_PROGRAM: // the view comes with a controller.
901  ipgm_views_[view->get_oid()] = view;
902  if (is_active_pgm(view)) {
903 
904  view->controller_->gain_activation();
905  if (a.takesPastInputs()) {
906 
907  std::multiset<P<View>, _View::Less>::const_iterator v;
908  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
909  view->controller_->_take_input(*v); // view will be copied.
910  }
911  }
912  break;
913  case Atom::INSTANTIATED_PROGRAM: {
914  ipgm_views_[view->get_oid()] = view;
915  PGMController *c = new PGMController(view);
916  view->controller_ = c;
917  if (is_active_pgm(view)) {
918 
919  c->gain_activation();
920  std::multiset<P<View>, _View::Less>::const_iterator v;
921  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
922  c->_take_input(*v); // view will be copied.
923  }
924  break;
925  }case Atom::INSTANTIATED_CPP_PROGRAM: {
926  ipgm_views_[view->get_oid()] = view;
927  Controller *c = CPPPrograms::New(Utils::GetString<Code>(view->object_, ICPP_PGM_NAME), view);
928  if (!c)
929  return;
930  view->controller_ = c;
931  if (is_active_pgm(view)) {
932 
933  c->gain_activation();
934  std::multiset<P<View>, _View::Less>::const_iterator v;
935  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
936  c->_take_input(*v); // view will be copied.
937  }
938  break;
939  }case Atom::INSTANTIATED_ANTI_PROGRAM: {
940  anti_ipgm_views_[view->get_oid()] = view;
941  AntiPGMController *c = new AntiPGMController(view);
942  view->controller_ = c;
943  if (is_active_pgm(view)) {
944 
945  c->gain_activation();
946  std::multiset<P<View>, _View::Less>::const_iterator v;
947  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
948  c->_take_input(*v); // view will be copied.
949  _Mem::Get()->push_time_job(new AntiPGMSignalingJob(view, now + Utils::GetDuration<Code>(c->get_object(), IPGM_TSC)));
950  }
951  break;
952  }case Atom::INSTANTIATED_INPUT_LESS_PROGRAM: {
953  input_less_ipgm_views_[view->get_oid()] = view;
954  InputLessPGMController *c = new InputLessPGMController(view);
955  view->controller_ = c;
956  if (is_active_pgm(view)) {
957 
958  c->gain_activation();
959  _Mem::Get()->push_time_job(new InputLessPGMSignalingJob(view, now + Utils::GetDuration<Code>(view->object_, IPGM_TSC)));
960  }
961  break;
962  }case Atom::MARKER: // the marker has already been added to the mks of its references.
963  other_views_[view->get_oid()] = view;
964  cov(view);
965  break;
966  case Atom::OBJECT:
967  other_views_[view->get_oid()] = view;
968  cov(view);
969  break;
970  case Atom::COMPOSITE_STATE: {
971  OUTPUT_LINE(HLP_INJ, Utils::RelativeTime(Now()) << " cst " << view->object_->get_oid() << " injected");
972  ipgm_views_[view->get_oid()] = view;
973  CSTController *c = new CSTController(view);
974  view->controller_ = c;
975  c->set_secondary_host(get_secondary_group());
976  if (is_active_pgm(view)) {
977 
978  c->gain_activation();
979  std::multiset<P<View>, _View::Less>::const_iterator v;
980  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
981  c->_take_input(*v); // view will be copied.
982  }
983  break;
984  }case Atom::MODEL: {
985  OUTPUT_LINE(HLP_INJ, Utils::RelativeTime(Now()) << " mdl " << view->object_->get_oid() << " injected");
986  ipgm_views_[view->get_oid()] = view;
987  bool inject_in_secondary_group;
988  MDLController *c = MDLController::New(view, inject_in_secondary_group);
989  view->controller_ = c;
990  if (inject_in_secondary_group)
991  get_secondary_group()->inject_secondary_mdl_controller(view);
992  if (is_active_pgm(view)) {
993 
994  c->gain_activation();
995  std::multiset<P<View>, _View::Less>::const_iterator v;
996  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v)
997  c->Controller::_take_input(*v); // view will be copied.
998  }
999  break;
1000  }
1001  }
1002 
1003  if (is_eligible_input(view)) { // have existing programs reduce the new view.
1004 
1005  newly_salient_views_.insert(view);
1006  inject_reduction_jobs(view);
1007  }
1008 
1009  leave();
1010 }
1011 
1012 void Group::inject_new_object(View *view) { // the view can hold anything but groups and notifications.
1013 //uint64 t0=Now();
1014  switch (view->object_->code(0).getDescriptor()) {
1015  case Atom::MARKER: // the marker does not exist yet: add it to the mks of its references.
1016  for (uint32 i = 0; i < view->object_->references_size(); ++i) {
1017 
1018  Code *ref = view->object_->get_reference(i);
1019  ref->acq_markers();
1020  ref->markers_.push_back(view->object_);
1021  ref->rel_markers();
1022  }
1023  break;
1024  default:
1025  break;
1026  }
1027 
1028  inject(view);
1029  notifyNew(view);
1030 }
1031 
1032 void Group::inject_existing_object(View *view) { // the view can hold anything but groups and notifications.
1033 
1034  Code *object = view->object_;
1035  object->acq_views();
1036  View *existing_view = (View *)object->get_view(this, false);
1037  if (!existing_view) { // no existing view: add the view to the object's view_map and inject.
1038 
1039  object->views_.insert(view);
1040  object->rel_views();
1041 
1042  inject(view);
1043  } else { // call set on the ctrl values of the existing view with the new view's ctrl values, including sync. NB: org left unchanged.
1044 
1045  object->rel_views();
1046 
1047  enter();
1048 
1049  pending_operations_.push_back(new Group::Set(existing_view->get_oid(), VIEW_RES, view->get_res()));
1050  pending_operations_.push_back(new Group::Set(existing_view->get_oid(), VIEW_SLN, view->get_sln()));
1051  switch (object->code(0).getDescriptor()) {
1052  case Atom::INSTANTIATED_PROGRAM:
1053  case Atom::INSTANTIATED_ANTI_PROGRAM:
1054  case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
1055  case Atom::INSTANTIATED_CPP_PROGRAM:
1056  case Atom::COMPOSITE_STATE:
1057  case Atom::MODEL:
1058  pending_operations_.push_back(new Group::Set(existing_view->get_oid(), VIEW_ACT, view->get_act()));
1059  break;
1060  }
1061 
1062  existing_view->code(VIEW_SYNC) = view->code(VIEW_SYNC);
1063  existing_view->set_ijt(Now());
1064 
1065  bool wiew_is_salient = view->get_sln() > get_sln_thr();
1066  bool wiew_was_salient = existing_view->get_sln() > get_sln_thr();
1067  bool reduce_view = (!wiew_was_salient && wiew_is_salient);
1068 
1069  // give a chance to ipgms to reduce the new view.
1070  bool group_is_c_active = update_c_act() > get_c_act_thr();
1071  bool group_is_c_salient = update_c_sln() > get_c_sln_thr();
1072  if (group_is_c_active && group_is_c_salient && reduce_view) {
1073 
1074  newly_salient_views_.insert(view);
1075  inject_reduction_jobs(view);
1076  }
1077 
1078  leave();
1079  }
1080 }
1081 
1082 void Group::inject_group(View *view) { // the view holds a group.
1083 
1084  enter();
1085 
1086  group_views_[view->get_oid()] = view;
1087 
1088  if (get_c_sln() > get_c_sln_thr() && view->get_sln() > get_sln_thr()) { // group is c-salient and view is salient.
1089 
1090  if (view->get_vis() > get_vis_thr()) // new visible group in a c-active and c-salient host.
1091  ((Group *)view->object_)->viewing_groups_[this] = view->get_cov();
1092 
1093  inject_reduction_jobs(view);
1094  }
1095 
1096  leave();
1097 
1098  if (((Group *)view->object_)->get_upr() > 0) // inject the next update job for the group.
1099  _Mem::Get()->push_time_job(new UpdateJob((Group *)view->object_, ((Group *)view->object_)->get_next_upr_time(Now())));
1100 
1101  notifyNew(view);
1102 }
1103 
1104 void Group::inject_notification(View *view, bool lock) {
1105 
1106  if (lock)
1107  enter();
1108 
1109  notification_views_[view->get_oid()] = view;
1110 
1111  for (uint32 i = 0; i < view->object_->references_size(); ++i) {
1112 
1113  Code *ref = view->object_->get_reference(i);
1114  ref->acq_markers();
1115  ref->markers_.push_back(view->object_);
1116  ref->rel_markers();
1117  }
1118 
1119  view->set_ijt(Now());
1120 
1121  if (get_c_sln() > get_c_sln_thr() && view->get_sln() > get_sln_thr()) // group is c-salient and view is salient.
1122  inject_reduction_jobs(view);
1123 
1124  if (lock)
1125  leave();
1126 }
1127 
1128 void Group::inject_reduction_jobs(View *view) { // group is assumed to be c-salient; already protected.
1129 
1130  if (get_c_act() > get_c_act_thr()) { // host is c-active.
1131 
1132  // build reduction jobs from host's own inputs and own overlays.
1133  FOR_ALL_VIEWS_WITH_INPUTS_BEGIN(this, v)
1134 
1135  if (v->second->get_act() > get_act_thr())//{ // active ipgm/icpp_pgm/rgrp view.
1136  v->second->controller_->_take_input(view); // view will be copied.
1137 
1138  FOR_ALL_VIEWS_WITH_INPUTS_END
1139  }
1140 
1141  // build reduction jobs from host's own inputs and overlays from viewing groups, if no cov and view is not a notification.
1142  // NB: visibility is not transitive;
1143  // no shadowing: if a view already exists in the viewing group, there will be twice the reductions: all of the identicals will be trimmed down at injection time.
1144  unordered_map<Group *, bool>::const_iterator vg;
1145  for (vg = viewing_groups_.begin(); vg != viewing_groups_.end(); ++vg) {
1146 
1147  if (vg->second || view->is_notification()) // no reduction jobs when cov==true or view is a notification.
1148  continue;
1149 
1150  FOR_ALL_VIEWS_WITH_INPUTS_BEGIN(vg->first, v)
1151 
1152  if (v->second->get_act() > vg->first->get_act_thr()) // active ipgm/icpp_pgm/rgrp view.
1153  v->second->controller_->_take_input(view); // view will be copied.
1154 
1155  FOR_ALL_VIEWS_WITH_INPUTS_END
1156  }
1157 }
1158 
1159 void Group::notifyNew(View *view) {
1160 
1161  if (get_ntf_new() == 1) {
1162 
1163  uint16 ntf_grp_count = get_ntf_grp_count();
1164  for (uint16 i = 1; i <= ntf_grp_count; ++i)
1165  _Mem::Get()->inject_notification(new NotificationView(this, get_ntf_grp(i), new MkNew(_Mem::Get(), view->object_)), get_ntf_grp(i) != this); // the object appears for the first time in the group: notify.
1166  }
1167 }
1168 
1169 void Group::cov(View *view) {
1170 
1171  unordered_map<Group *, bool>::const_iterator vg;
1172  for (vg = viewing_groups_.begin(); vg != viewing_groups_.end(); ++vg) {
1173 
1174  if (vg->second) // cov==true, viewing group c-salient and c-active (otherwise it wouldn't be a viewing group).
1175  _Mem::Get()->inject_copy(view, vg->first);
1176  }
1177 }
1178 
1179 void Group::cov() {
1180 
1181  // cov, i.e. injecting now newly salient views in the viewing groups from which the group is visible and has cov.
1182  // reduction jobs will be added at each of the eligible viewing groups' own update time.
1183  unordered_map<Group *, bool>::const_iterator vg;
1184  for (vg = viewing_groups_.begin(); vg != viewing_groups_.end(); ++vg) {
1185 
1186  if (vg->second) { // cov==true.
1187 
1188  std::multiset<P<View>, _View::Less>::const_iterator v;
1189  for (v = newly_salient_views_.begin(); v != newly_salient_views_.end(); ++v) { // no cov for pgm (all sorts), groups, notifications.
1190 
1191  if ((*v)->is_notification())
1192  continue;
1193  switch ((*v)->object_->code(0).getDescriptor()) {
1194  case Atom::GROUP:
1195  case Atom::NULL_PROGRAM:
1196  case Atom::INSTANTIATED_PROGRAM:
1197  case Atom::INSTANTIATED_CPP_PROGRAM:
1198  case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
1199  case Atom::INSTANTIATED_ANTI_PROGRAM:
1200  case Atom::COMPOSITE_STATE:
1201  case Atom::MODEL:
1202  break;
1203  default:
1204  _Mem::Get()->inject_copy(*v, vg->first); // no need to protect group->newly_salient_views_[i] since the support values for the ctrl values are not even read.
1205  break;
1206  }
1207  }
1208  }
1209  }
1210 }
1211 
1212 void Group::delete_view(View *v) {
1213 
1214  if (v->is_notification())
1215  notification_views_.erase(v->get_oid());
1216  else switch (v->object_->code(0).getDescriptor()) {
1217  case Atom::NULL_PROGRAM:
1218  case Atom::INSTANTIATED_PROGRAM:
1219  case Atom::INSTANTIATED_CPP_PROGRAM:
1220  case Atom::COMPOSITE_STATE:
1221  case Atom::MODEL:
1222  ipgm_views_.erase(v->get_oid());
1223  break;
1224  case Atom::INSTANTIATED_ANTI_PROGRAM:
1225  anti_ipgm_views_.erase(v->get_oid());
1226  break;
1227  case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
1228  input_less_ipgm_views_.erase(v->get_oid());
1229  break;
1230  case Atom::OBJECT:
1231  case Atom::MARKER:
1232  other_views_.erase(v->get_oid());
1233  break;
1234  case Atom::GROUP:
1235  group_views_.erase(v->get_oid());
1236  break;
1237  }
1238 }
1239 
1240 void Group::delete_view(unordered_map<uint32, P<View> >::const_iterator &v) {
1241 
1242  if (v->second->is_notification())
1243  v = notification_views_.erase(v);
1244  else switch (v->second->object_->code(0).getDescriptor()) {
1245  case Atom::NULL_PROGRAM:
1246  case Atom::INSTANTIATED_PROGRAM:
1247  case Atom::INSTANTIATED_CPP_PROGRAM:
1248  case Atom::COMPOSITE_STATE:
1249  case Atom::MODEL:
1250  v = ipgm_views_.erase(v);
1251  break;
1252  case Atom::INSTANTIATED_ANTI_PROGRAM:
1253  v = anti_ipgm_views_.erase(v);
1254  break;
1255  case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
1256  v = input_less_ipgm_views_.erase(v);
1257  break;
1258  case Atom::OBJECT:
1259  case Atom::MARKER:
1260  v = other_views_.erase(v);
1261  break;
1262  case Atom::GROUP:
1263  v = group_views_.erase(v);
1264  break;
1265  }
1266 }
1267 
1268 Group *Group::get_secondary_group() {
1269 
1270  Group *secondary = NULL;
1272  acq_markers();
1273  for (m = markers_.begin(); m != markers_.end(); ++m) {
1274 
1275  if ((*m)->code(0).asOpcode() == Opcodes::MkGrpPair) {
1276 
1277  if ((Group *)(*m)->get_reference((*m)->code(GRP_PAIR_FIRST).asIndex()) == this) {
1278 
1279  secondary = (Group *)(*m)->get_reference((*m)->code(GRP_PAIR_SECOND).asIndex());
1280  break;
1281  }
1282  }
1283  }
1284  rel_markers();
1285  return secondary;
1286 }
1287 
1288 void Group::load_secondary_mdl_controller(View *view) {
1289 
1290  PrimaryMDLController *p = (PrimaryMDLController *)view->controller_;
1291  View *_view = new View(view, true);
1292  _view->code(VIEW_ACT) = Atom::Float(0);
1293  _view->references_[0] = this;
1294  ipgm_views_[_view->get_oid()] = _view;
1295  SecondaryMDLController *s = new SecondaryMDLController(_view);
1296  _view->controller_ = s;
1297  view->object_->views_.insert(_view);
1298  p->set_secondary(s);
1299  s->set_primary(p);
1300 }
1301 
1302 void Group::inject_secondary_mdl_controller(View *view) {
1303 
1304  PrimaryMDLController *p = (PrimaryMDLController *)view->controller_;
1305  View *_view = new View(view, true);
1306  _view->code(VIEW_ACT) = Atom::Float(0);
1307  _view->references_[0] = this;
1308  ipgm_views_[_view->get_oid()] = _view;
1309  SecondaryMDLController *s = new SecondaryMDLController(_view);
1310  _view->controller_ = s;
1311  view->object_->views_.insert(_view);
1312  p->set_secondary(s);
1313  s->set_primary(p);
1314 }
1315 
1316 Timestamp Group::get_next_upr_time(Timestamp now) const {
1317 
1318  uint32 __upr = get_upr();
1319  if (__upr == 0)
1320  return Utils_MaxTime;
1321  auto _upr = __upr * Utils::GetBasePeriod();
1322  auto delta = (now - Utils::GetTimeReference()) % _upr;
1323  return now - delta + _upr;
1324 }
1325 
1326 Timestamp Group::get_prev_upr_time(Timestamp now) const {
1327 
1328  uint32 __upr = get_upr();
1329  if (__upr == 0)
1330  return Utils_MaxTime;
1331  auto _upr = __upr * Utils::GetBasePeriod();
1332  auto delta = (now - Utils::GetTimeReference()) % _upr;
1333  return now - delta;
1334 }
1335 }
r_code::list::const_iterator
Definition: list.h:266
r_code::Atom
Definition: atom.h:104
core::P
Definition: base.h:103
r_code::_View::Less
Definition: r_code/object.h:215
r_code::Code
Definition: r_code/object.h:224
r_exec::View
Definition: view.h:102