NEURON
point.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* /local/src/master/nrn/src/nrnoc/point.cpp,v 1.13 1999/03/23 16:12:09 hines Exp */
3 
4 /* modl description via modlreg calls point_register_mech() and
5 saves the pointtype as later argument to create and loc */
6 
7 #include <stdlib.h>
8 
9 #include "membfunc.h"
10 #include "nrniv_mf.h"
11 #include "ocnotify.h"
12 #include "parse_with_deps.hpp"
13 #include "section.h"
14 
15 
16 extern char* pnt_map;
17 extern Symbol** pointsym; /*list of variable symbols in s->u.ppsym[k]
18  with number in s->s_varn */
19 
20 extern short* nrn_is_artificial_;
21 extern Prop* prop_alloc(Prop**, int, Node*);
22 
23 static double ppp_dummy = 42.0;
24 static int cppp_semaphore = 0; /* connect point process pointer semaphore */
25 static Datum* cppp_datum = nullptr;
26 static void free_one_point(Point_process* pnt);
27 static void create_artcell_prop(Point_process* pnt, short type);
28 
30 void (*nrnpy_o2loc_p_)(Object*, Section**, double*);
31 void (*nrnpy_o2loc2_p_)(Object*, Section**, double*);
32 
34  auto* const pp = new Point_process{};
35  pp->ob = ho;
38  return pp;
39  }
40  if (ho && ho->ctemplate->steer && ifarg(1)) {
41  loc_point_process(pointtype, (void*) pp);
42  }
43  return pp;
44 }
45 
47  void* v;
48  extern Object* hoc_new_opoint(int);
49  Object* ob;
51  int pointtype;
52  assert(sym->type == MECHANISM && memb_func[sym->subtype].is_point);
53  pointtype = pnt_map[sym->subtype];
54  if (memb_func[sym->subtype].hoc_mech) {
55  ob = hoc_new_opoint(sym->subtype);
56  } else {
57  hoc_push_frame(sym, 0);
58  v = create_point_process(pointtype, nullptr);
59  hoc_pop_frame();
61  ob = hoc_new_object(sym, v);
62  ((Point_process*) v)->ob = ob;
63  }
64  return ob;
65 }
66 
67 void destroy_point_process(void* v) {
68  // might be NULL if error handling because of error in construction
69  if (v) {
70  auto* const pp = static_cast<Point_process*>(v);
71  free_one_point(pp);
72  delete pp;
73  }
74 }
75 
77  extern Prop* prop_alloc_disallow(Prop * *pp, short type, Node* nd);
80  if (pnt->prop) {
81  // Make the old Node forget about pnt->prop
82  if (auto* const old_node = pnt->node; old_node) {
83  auto* const p = pnt->prop;
84  if (!nrn_is_artificial_[p->_type]) {
85  auto* p1 = old_node->prop;
86  if (p1 == p) {
87  old_node->prop = p1->next;
88  } else {
89  for (; p1; p1 = p1->next) {
90  if (p1->next == p) {
91  p1->next = p->next;
92  break;
93  }
94  }
95  }
96  }
97  v_structure_change = 1; // needed?
98  }
99  // Tell the new Node about pnt->prop
100  pnt->prop->next = node->prop;
101  node->prop = pnt->prop;
102  // Call the nrn_alloc function from the MOD file with nrn_point_prop_ set: this will skip
103  // resetting parameter values and calling the CONSTRUCTOR block, but it *will* update ion
104  // variables to point to the ion mechanism instance in the new Node
106  } else {
107  // Allocate a new Prop for this Point_process
108  Prop* p;
109  auto const x = nrn_arc_position(sec, node);
110  nrn_point_prop_ = pnt->prop;
112  // Both branches of this tell `node` about the new Prop `p`
113  if (x == 0. || x == 1.) {
115  } else {
117  }
118  nrn_pnt_sec_for_need_ = nullptr;
119  nrn_point_prop_ = nullptr;
120  pnt->prop = p;
121  pnt->prop->dparam[1] = {neuron::container::do_not_search, pnt};
122  }
123  // Update pnt->sec with sec, unreffing the old value and reffing the new one
124  nrn_sec_ref(&pnt->sec, sec);
125  pnt->node = node; // tell pnt which node it belongs to now
126  pnt->prop->dparam[0] = node->area_handle();
127  if (pnt->ob) {
128  if (pnt->ob->observers) {
129  hoc_obj_notify(pnt->ob);
130  }
131  if (pnt->ob->ctemplate->observers) {
132  hoc_template_notify(pnt->ob, 2);
133  }
134  }
135 }
136 
137 static void create_artcell_prop(Point_process* pnt, short type) {
138  Prop* p = (Prop*) 0;
139  nrn_point_prop_ = (Prop*) 0;
140  pnt->prop = prop_alloc(&p, type, (Node*) 0);
141  pnt->prop->dparam[0] = static_cast<double*>(nullptr);
142  pnt->prop->dparam[1] = pnt;
143  if (pnt->ob) {
144  if (pnt->ob->observers) {
145  hoc_obj_notify(pnt->ob);
146  }
147  if (pnt->ob->ctemplate->observers) {
148  hoc_template_notify(pnt->ob, 2);
149  }
150  }
151 }
152 
153 void nrn_relocate_old_points(Section* oldsec, Node* oldnode, Section* sec, Node* node) {
154  if (oldnode)
155  for (Prop *p = oldnode->prop, *pn; p; p = pn) {
156  pn = p->next;
157  if (memb_func[p->_type].is_point) {
158  auto* pnt = p->dparam[1].get<Point_process*>();
159  if (oldsec == pnt->sec) {
160  if (oldnode == node) {
161  nrn_sec_ref(&pnt->sec, sec);
162  } else {
163  nrn_loc_point_process(pnt_map[p->_type], pnt, sec, node);
164  }
165  }
166  }
167  }
168 }
169 
170 void nrn_seg_or_x_arg(int iarg, Section** psec, double* px) {
171  if (hoc_is_double_arg(iarg)) {
172  *px = chkarg(iarg, 0., 1.);
173  *psec = chk_access();
174  } else {
175  Object* o = *hoc_objgetarg(iarg);
176  *psec = (Section*) 0;
177  if (nrnpy_o2loc_p_) {
178  (*nrnpy_o2loc_p_)(o, psec, px);
179  }
180  if (!(*psec)) {
181  assert(0);
182  }
183  }
184 }
185 
186 void nrn_seg_or_x_arg2(int iarg, Section** psec, double* px) {
187  if (hoc_is_double_arg(iarg)) {
188  *px = chkarg(iarg, 0., 1.);
189  *psec = chk_access();
190  } else {
191  Object* o = *hoc_objgetarg(iarg);
192  *psec = (Section*) 0;
193  if (nrnpy_o2loc2_p_) {
194  (*nrnpy_o2loc2_p_)(o, psec, px);
195  }
196  if (!(*psec)) {
197  assert(0);
198  }
199  }
200 }
201 
202 double loc_point_process(int pointtype, void* v) {
203  Point_process* pnt = (Point_process*) v;
204  double x;
205  Section* sec;
206  Node* node;
207 
209  hoc_execerror("ARTIFICIAL_CELLs are not located in a section", (char*) 0);
210  }
211  nrn_seg_or_x_arg(1, &sec, &x);
212  node = node_exact(sec, x);
214  return x;
215 }
216 
217 double get_loc_point_process(void* v) {
218  double x;
219  Point_process* pnt = (Point_process*) v;
220  Section* sec;
221 
222  if (pnt->prop == (Prop*) 0) {
223  hoc_execerror("point process not located in a section", (char*) 0);
224  }
225  if (nrn_is_artificial_[pnt->prop->_type]) {
226  hoc_execerror("ARTIFICIAL_CELLs are not located in a section", (char*) 0);
227  }
228  sec = pnt->sec;
229  x = nrn_arc_position(sec, pnt->node);
231  return x;
232 }
233 
234 double has_loc_point(void* v) {
235  Point_process* pnt = (Point_process*) v;
236  return (pnt->sec != 0);
237 }
238 
240  Symbol* sym,
241  int index) {
242  if (!pnt->prop) {
243  if (nrn_inpython_ == 1) { /* python will handle the error */
244  hoc_warning("point process not located in a section", nullptr);
245  nrn_inpython_ = 2;
246  return {};
247  } else {
248  hoc_execerror("point process not located in a section", nullptr);
249  }
250  }
251  if (sym->subtype == NRNPOINTER) {
252  auto& datum = pnt->prop->dparam[sym->u.rng.index + index];
253  if (cppp_semaphore) {
254  ++cppp_semaphore;
255  cppp_datum = &datum; // we will store a value in `datum` later
257  &ppp_dummy};
258  } else {
259  // In case _p_somevar is being used as an opaque void* in a VERBATIM
260  // block then then the Datum will hold a literal void* and will not
261  // be convertible to double*. If instead somevar is used in the MOD
262  // file and it was set from the interpreter (mech._ref_pv =
263  // seg._ref_v), then the Datum will hold either data_handle<double>
264  // or a literal double*. If we attempt to access a POINTER or
265  // BBCOREPOINTER variable that is being used as an opaque void* from
266  // the interpreter -- as is done in test_datareturn.py, for example
267  // -- then we will reach this code when the datum holds a literal
268  // void*. We don't know what type that pointer really refers to, so
269  // in the first instance let's return nullptr in that case, not
270  // void*-cast-to-double*.
271  if (datum.holds<double*>()) {
272  return static_cast<neuron::container::data_handle<double>>(datum);
273  } else {
274  return {};
275  }
276  }
277  } else {
278  if (pnt->prop->ob) {
280  pnt->prop->ob->u.dataspace[sym->u.rng.index].pval + index};
281  } else {
282  return pnt->prop->param_handle_legacy(sym->u.rng.index + index);
283  }
284  }
285 }
286 
287 // put the right data handle on the stack
288 void steer_point_process(void* v) {
289  auto* const pnt = static_cast<Point_process*>(v);
290  auto* const sym = hoc_spop();
291  auto const index = is_array(*sym) ? hoc_araypt(sym, SYMBOL) : 0;
293 }
294 
295 void nrn_cppp(void) {
296  cppp_semaphore = 1;
297 }
298 
300  if (cppp_semaphore != 2) {
301  cppp_semaphore = 0;
302  hoc_execerror("not a point process pointer", (char*) 0);
303  }
304  cppp_semaphore = 0;
305  *cppp_datum = hoc_pop_handle<double>();
306  hoc_nopop();
307 }
308 
309 // must unlink from node property list also
310 static void free_one_point(Point_process* pnt) {
311  auto* p = pnt->prop;
312  if (!p) {
313  return;
314  }
315  if (!nrn_is_artificial_[p->_type]) {
316  auto* p1 = pnt->node->prop;
317  if (p1 == p) {
318  pnt->node->prop = p1->next;
319  } else
320  for (; p1; p1 = p1->next) {
321  if (p1->next == p) {
322  p1->next = p->next;
323  break;
324  }
325  }
326  }
327  v_structure_change = 1;
328  if (memb_func[p->_type].destructor) {
329  memb_func[p->_type].destructor(p);
330  }
331  if (auto got = nrn_mech_inst_destruct.find(p->_type); got != nrn_mech_inst_destruct.end()) {
332  (got->second)(p);
333  }
334  if (p->dparam) {
335  nrn_prop_datum_free(p->_type, p->dparam);
336  }
337  delete p;
338  pnt->prop = (Prop*) 0;
339  pnt->node = (Node*) 0;
340  if (pnt->sec) {
341  section_unref(pnt->sec);
342  }
343  pnt->sec = (Section*) 0;
344 }
345 
346 // called from prop_free
348  auto* const pnt = p->dparam[1].get<Point_process*>();
349  if (pnt) {
350  free_one_point(pnt);
351  if (pnt->ob) {
352  if (pnt->ob->observers) {
353  hoc_obj_notify(pnt->ob);
354  }
355  if (pnt->ob->ctemplate->observers) {
356  hoc_template_notify(pnt->ob, 2);
357  }
358  }
359  } else {
360  if (p->ob) {
361  hoc_obj_unref(p->ob);
362  }
363  if (p->dparam) {
364  nrn_prop_datum_free(p->_type, p->dparam);
365  }
366  delete p;
367  }
368 }
369 
371  if (ob) {
372  return ob->ctemplate->is_point_ != 0;
373  }
374  return 0;
375 }
Section * chk_access()
Definition: cabcode.cpp:449
double nrn_arc_position(Section *sec, Node *node)
Definition: cabcode.cpp:1755
void hoc_level_pushsec(Section *sec)
turn off section stack fixing (in case of return, continue, break in a section statement) between exp...
Definition: cabcode.cpp:2187
Node * node_exact(Section *sec, double x)
like node_index but give proper node when x is 0 or 1 as well as in between
Definition: cabcode.cpp:1800
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:48
#define v
Definition: md1redef.h:11
#define sec
Definition: md1redef.h:20
void nrn_prop_datum_free(int type, Datum *ppd)
Definition: cxprop.cpp:54
double chkarg(int, double low, double high)
Definition: code2.cpp:626
void hoc_push_frame(Symbol *sp, int narg)
Definition: code.cpp:1376
void hoc_template_notify(Object *ob, int message)
Definition: ocobserv.cpp:37
Object * hoc_new_object(Symbol *symtemp, void *v)
Definition: hoc_oop.cpp:450
int hoc_is_double_arg(int narg)
Definition: code.cpp:864
void hoc_obj_notify(Object *ob)
Definition: ocobserv.cpp:10
Symbol * hoc_spop()
Definition: code.cpp:928
void hoc_pop_frame(void)
Definition: code.cpp:1387
void hoc_nopop()
Definition: code.cpp:972
void hoc_obj_unref(Object *obj)
Definition: hoc_oop.cpp:1881
void hoc_push(neuron::container::generic_data_handle handle)
Definition: code.cpp:850
#define assert(ex)
Definition: hocassrt.h:24
bool is_array(const Symbol &sym)
Definition: hocdec.h:136
Object * hoc_new_opoint(int)
Definition: hocmech.cpp:165
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
int hoc_araypt(Symbol *, int)
Definition: code.cpp:2340
#define NRNPOINTER
Definition: membfunc.hpp:83
#define SYMBOL
Definition: model.h:91
long subtype
Definition: init.cpp:107
int v_structure_change
Definition: nrnoc_aux.cpp:20
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
constexpr do_not_search_t do_not_search
Definition: data_handle.hpp:11
void section_unref(Section *)
Definition: solve.cpp:509
void nrn_sec_ref(Section **, Section *)
Definition: solve.cpp:525
static Node * node(Object *)
Definition: netcvode.cpp:291
size_t p
int ifarg(int)
Definition: code.cpp:1607
void prop_update_ion_variables(Prop *, Node *)
Definition: treeset.cpp:690
short index
Definition: cabvars.h:11
std::vector< Memb_func > memb_func
Definition: init.cpp:145
short type
Definition: cabvars.h:10
static int pointtype
Definition: init.cpp:447
std::unordered_map< int, void(*)(Prop *)> nrn_mech_inst_destruct
Definition: init.cpp:167
int nrn_inpython_
Definition: hoc.cpp:52
double loc_point_process(int pointtype, void *v)
Definition: point.cpp:202
short * nrn_is_artificial_
Definition: init.cpp:214
static double ppp_dummy
Definition: point.cpp:23
double has_loc_point(void *v)
Definition: point.cpp:234
static Datum * cppp_datum
Definition: point.cpp:25
Prop * nrn_point_prop_
Definition: point.cpp:29
double get_loc_point_process(void *v)
Definition: point.cpp:217
void * create_point_process(int pointtype, Object *ho)
Definition: point.cpp:33
void(* nrnpy_o2loc2_p_)(Object *, Section **, double *)
Definition: point.cpp:31
void nrn_seg_or_x_arg2(int iarg, Section **psec, double *px)
Definition: point.cpp:186
void nrn_relocate_old_points(Section *oldsec, Node *oldnode, Section *sec, Node *node)
Definition: point.cpp:153
neuron::container::data_handle< double > point_process_pointer(Point_process *pnt, Symbol *sym, int index)
Definition: point.cpp:239
void nrn_cppp(void)
Definition: point.cpp:295
void(* nrnpy_o2loc_p_)(Object *, Section **, double *)
Definition: point.cpp:30
Object * nrn_new_pointprocess(Symbol *sym)
Definition: point.cpp:46
Prop * prop_alloc(Prop **, int, Node *)
Definition: treeset.cpp:671
static void create_artcell_prop(Point_process *pnt, short type)
Definition: point.cpp:137
void clear_point_process_struct(Prop *p)
Definition: point.cpp:347
void connect_point_process_pointer(void)
Definition: point.cpp:299
char * pnt_map
Definition: init.cpp:150
void nrn_seg_or_x_arg(int iarg, Section **psec, double *px)
Definition: point.cpp:170
Symbol ** pointsym
Definition: init.cpp:148
static int cppp_semaphore
Definition: point.cpp:24
void nrn_loc_point_process(int pointtype, Point_process *pnt, Section *sec, Node *node)
Definition: point.cpp:76
int is_point_process(Object *ob)
Definition: point.cpp:370
void destroy_point_process(void *v)
Definition: point.cpp:67
void steer_point_process(void *v)
Definition: point.cpp:288
static void free_one_point(Point_process *pnt)
Definition: point.cpp:310
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:28
Definition: section.h:105
auto area_handle()
Definition: section.h:126
Prop * prop
Definition: section.h:190
Definition: hocdec.h:173
Objectdata * dataspace
Definition: hocdec.h:177
void * observers
Definition: hocdec.h:185
cTemplate * ctemplate
Definition: hocdec.h:180
union Object::@47 u
A point process is computed just like regular mechanisms.
Definition: section_fwd.hpp:77
Section * sec
Definition: section_fwd.hpp:78
Definition: section.h:231
Datum * dparam
Definition: section.h:247
short _type
Definition: section.h:244
Object * ob
Definition: section.h:252
auto param_handle_legacy(int legacy_index)
Definition: section.h:355
Prop * next
Definition: section.h:243
Definition: model.h:47
union Symbol::@28 u
struct Symbol::@45::@46 rng
short type
Definition: model.h:48
long subtype
Definition: model.h:49
char * name
Definition: model.h:61
Definition: hocdec.h:75
void * observers
Definition: hocdec.h:157
int is_point_
Definition: hocdec.h:150
void(* steer)(void *)
Definition: hocdec.h:160
Non-template stable handle to a generic value.
Section * nrn_pnt_sec_for_need_
Definition: treeset.cpp:617
Prop * prop_alloc_disallow(Prop **pp, short type, Node *nd)
Definition: treeset.cpp:702
double * pval
Definition: hocdec.h:164