NEURON
ivoc.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #include <vector>
4 #include <ocnotify.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <nrnmutdec.h>
8 #include "oc2iv.h"
9 #include "ocfunc.h"
10 
11 extern Object** (*nrnpy_gui_helper_)(const char* name, Object* obj);
12 extern double (*nrnpy_object_to_double_)(Object*);
13 
14 #if HAVE_IV
15 #include "utility.h"
16 #include "ivoc.h"
17 #endif
18 
19 #include "bimap.hpp"
20 
21 #if USE_PTHREAD
22 static MUTDEC;
23 #endif
24 
25 using PF = void (*)(void*, int);
26 using FList = std::vector<PF>;
27 
28 static FList* f_list;
29 
32 
33 // fast insert, find, and remove of (double*, Observer*) using either as
34 // a key. Use pair of multimap since there can be many observers of the
35 // same double. And perhaps one Observer is watching several double*. Also
36 // the double* being watched is removed when the array (pd*, size) it is
37 // a part of is freed. So the upper_bound property is needed
38 
40 
41 
42 void* (*nrnpy_save_thread)();
44 
45 void nrn_notify_freed(PF pf) {
46  if (!f_list) {
47  f_list = new FList;
48  }
49  f_list->push_back(pf);
50 }
51 
53  MUTLOCK
54  if (!pvob) {
56  }
57  pvob->insert(p, ob);
58  MUTUNLOCK
59 }
60 
62  MUTLOCK
63  if (!pdob) {
65  }
66  pdob->insert(p, ob);
67  MUTUNLOCK
68 }
69 
71  MUTLOCK
72  if (pvob) {
73  pvob->obremove(ob);
74  }
75  if (pdob) {
76  pdob->obremove(ob);
77  }
78  MUTUNLOCK
79 }
80 
81 void notify_pointer_freed(void* pt) {
82  if (pvob) {
83  MUTLOCK
84  void* pv;
85  Observer* ob;
86  while (pvob->find(pt, pv, ob)) {
87  ob->update(NULL);
88  pvob->remove(pv, ob);
89  }
90  MUTUNLOCK
91  }
92 }
93 void notify_freed(void* p) {
94  if (f_list) {
95  for (PF f: *f_list) {
96  f(p, 1);
97  }
98  }
100 }
101 void notify_freed_val_array(double* p, size_t size) {
102  if (f_list) {
103  for (PF f: *f_list) {
104  f((void*) p, size);
105  }
106  }
107  if (pdob) {
108  double* pp;
109  Observer* ob;
110  while (pdob->find(p, size, pp, ob)) {
111  // printf("notify_freed_val_array %d %ld\n", size, j);
112  ob->update(NULL);
113  pdob->remove(pp, ob);
114  }
115  }
116 }
117 
118 char* cxx_char_alloc(size_t sz) {
119  char* cp = new char[sz];
120  return cp;
121 }
122 
123 
124 #ifndef MINGW // actual implementation in ivocwin.cpp
125 void nrniv_bind_thread(void);
127  hoc_pushx(1.);
128  hoc_ret();
129 }
130 #endif
131 
132 void nrn_err_dialog(const char* mes) {
133 #if HAVE_IV
134  IFGUI
135  if (nrn_err_dialog_active_ && !Session::instance()->done()) {
136  char m[1024];
137  sprintf(m, "%s (See terminal window)", mes);
138  continue_dialog(m);
139  }
140  ENDGUI
141 #endif
142 }
143 
144 #if HAVE_IV // to end of file
145 
146 #include <InterViews/event.h>
147 #include <InterViews/reqerr.h>
148 #include <InterViews/style.h>
149 #include <IV-look/kit.h>
150 
151 #include "xmenu.h"
152 
153 /*
154  * Interface between oc and interviews.
155  *
156  * The normal command driven oc can be simultaneously event driven if
157  * instead of blocking on a terminal read, run_til_stdin() is called.
158  * This runs the interviews event loop until something is typed in the
159  * window from which oc was run.
160  */
161 
162 extern void hoc_main1_init(const char* pname, const char** env);
163 extern int hoc_oc(const char*);
164 extern int hoc_interviews;
165 extern Symbol* hoc_parse_expr(const char*, Symlist**);
166 extern double hoc_run_expr(Symbol*);
167 extern int hoc_execerror_messages;
168 extern void hoc_ret();
169 extern void hoc_pushx(double);
170 extern FILE* hoc_fin;
171 extern void ivoc_cleanup();
172 extern "C" void nrn_shape_update();
173 extern int bbs_poll_;
174 extern void bbs_handle();
175 
176 int run_til_stdin();
177 void single_event_run();
178 void hoc_notify_iv();
179 
180 extern int hoc_print_first_instance;
181 void ivoc_style();
182 
183 // because NEURON can no longer maintain its own copy of dialogs.cpp
184 // we communicate with the InterViews version through a callback.
185 extern bool (*IVDialog_setAcceptInput)(bool);
186 bool setAcceptInputCallback(bool);
187 bool setAcceptInputCallback(bool b) {
188  Oc oc;
189  return oc.setAcceptInput(b);
190 }
191 
192 void ivoc_style() {
193  TRY_GUI_REDIRECT_DOUBLE("ivoc_style", NULL);
194  IFGUI
195  if (Session::instance()) {
196  Style* s = Session::instance()->style();
197  s->remove_attribute(gargstr(1));
198  s->attribute(gargstr(1), gargstr(2), -5);
199  }
200 #if 0
201 String s;
202 if (WidgetKit::instance()->style()->find_attribute(gargstr(1)+1, s)) {
203  printf("ivoc_style %s: %s\n", gargstr(1), s.string());
204 }else{
205  printf("couldn't find %s\n", gargstr(1));
206 }
207 #endif
208  ENDGUI
209  hoc_ret();
210  hoc_pushx(1.);
211 }
212 
213 #if !defined(MINGW) && !defined(MAC) && !defined(carbon)
214 /*static*/ class ReqErr1: public ReqErr {
215  public:
216  ReqErr1();
217  virtual void Error();
218  virtual int count() {
219  return count_;
220  }
221 
222  private:
223  int count_;
224  int r_;
225 };
226 
227 ReqErr1::ReqErr1() {
228  count_ = 0;
229  r_ = 0;
230 }
231 
232 void ReqErr1::Error() {
233  if (!count_ || code != r_) {
234  if (!r_) {
235  r_ = code;
236  }
237  fprintf(stderr, "X Error of failed request: %s\n", message);
238  if (r_ == code) {
239  fprintf(stderr, "Further messages for error code %d will not be shown\n", r_);
240  }
241  }
242  ++count_;
243 }
244 
245 static ReqErr1* reqerr1;
246 #endif
247 
248 #if MAC
249 static HandleStdin* hsd_;
250 #endif
251 
252 #ifdef MINGW
253 static HandleStdin* hsd_;
254 void winio_key_press() {
255  hsd_->inputReady(1);
256 }
257 
258 #endif
259 
260 Oc::Oc() {
261  MUTLOCK
262  ++refcnt_;
263  MUTUNLOCK
264 }
265 
266 bool Oc::helpmode_;
267 
268 Oc::Oc(Session* s, const char* pname, const char** env) {
269  if (session_)
270  return;
271  refcnt_++;
272  session_ = s;
273  IVDialog_setAcceptInput = setAcceptInputCallback;
274  notify_change_ = new Observable();
275  if (s) {
276  helpmode_ = false;
277 #if !defined(WIN32) && !defined(MAC) && !defined(carbon)
278  reqerr1 = new ReqErr1;
279  reqerr1->Install();
280 #endif
281 #if defined(MINGW) || defined(MAC)
282  hsd_ = handleStdin_ = new HandleStdin;
283 #else
285  Dispatcher::instance().link(0, Dispatcher::ReadMask, handleStdin_);
286  Dispatcher::instance().link(0, Dispatcher::ExceptMask, handleStdin_);
287 #endif
288  hoc_interviews = 1;
289 #if MAC
291 #endif
292  String str;
293  if (session_->style()->find_attribute("first_instance_message", str)) {
294  if (str == "on") {
296  } else {
298  }
299  }
300  }
301  MUTCONSTRUCT(1)
303 }
304 
305 Oc::~Oc() {
306  MUTLOCK
307  if (--refcnt_ == 0) {
308 #if !defined(MINGW) && !defined(MAC) && !defined(carbon)
309  if (reqerr1 && reqerr1->count()) {
310  fprintf(stderr, "total X Errors: %d\n", reqerr1->count());
311  }
312 #endif
313  }
314  MUTUNLOCK
315 }
316 
317 
319  return session_;
320 }
321 
322 int Oc::run(int argc, const char** argv) {
323  return hoc_main1(argc, argv, 0);
324 }
325 
326 int Oc::run(const char* buf, bool show_err_mes) {
327  hoc_execerror_messages = show_err_mes;
328  return hoc_oc(buf);
329 }
330 
331 Symbol* Oc::parseExpr(const char* expr, Symlist** ps) {
332  return hoc_parse_expr(expr, ps);
333 }
334 
335 double Oc::runExpr(Symbol* sym) {
336  return hoc_run_expr(sym);
337 }
338 
339 const char* Oc::name(Symbol* sym) {
340  return sym->name;
341 }
342 
343 bool Oc::setAcceptInput(bool b) {
344  bool old = handleStdin_->acceptInput_;
346  return old;
347 }
348 
349 void Oc::notify_freed(PF pf) {
350  nrn_notify_freed(pf);
351 }
352 
353 void Oc::notify_when_freed(void* p, Observer* ob) {
355 }
356 
357 void Oc::notify_when_freed(double* p, Observer* ob) {
359 }
360 
363 }
364 
366  stdinSeen_ = false;
367  acceptInput_ = true;
368 }
369 
370 int HandleStdin::inputReady(int fd) {
371  stdinSeen_ = 1;
372  if (fd) {
373  ;
374  }
375  if (acceptInput_) {
376  Oc::getSession()->quit();
377  }
378  return 0;
379 }
380 
381 int HandleStdin::exceptionRaised(int fd) {
382  hoc_interviews = 0;
383  if (fd) {
384  ;
385  }
386  stdinSeen_ = 1;
387  Oc::getSession()->quit();
388  return 0;
389 }
390 
391 void ivoc_cleanup() {}
392 
393 int run_til_stdin() {
394  Session* session = Oc::getSession();
395 #if defined(WIN32) || MAC
396  Oc oc;
397  oc.notify();
398 #endif
399 #ifndef WIN32
400  Oc::setStdinSeen(false);
401 #endif
402  session->run();
403  WinDismiss::dismiss_defer(); // in case window was dismissed
404 #if MAC && !defined(carbon)
405  extern Boolean IVOCGoodLine;
406  if (IVOCGoodLine) {
407  return 1;
408  } else {
409  return 0;
410  }
411 #endif
412 #ifdef WIN32
413  return 0;
414 #else
415  return Oc::getStdinSeen(); // MAC should not reach this point
416 #endif
417 }
418 
419 void single_event_run() {
420  Resource::flush();
421  Session* session = Oc::getSession();
422  Event e;
423  // actually run till no more events
424  Oc::setAcceptInput(false);
425 #if MAC
426  extern bool read_if_pending(Event&);
427  while (!session->done() && read_if_pending(e)) {
428  e.handle();
429  }
430 #else
431  bool dsav = session->done();
432  session->unquit();
433  while (session->pending() && !session->done()) {
434  session->read(e);
435  e.handle();
436  }
437  if (dsav) {
438  session->quit();
439  }
440 #endif
441  Oc::setAcceptInput(true);
442  ;
443  HocPanel::keep_updated();
444 #if MAC
445  Session::instance()->screen_update();
446 #endif
447  WinDismiss::dismiss_defer(); // in case window was dismissed
448 }
449 
450 #ifdef MINGW
451 extern void nrniv_bind_call(void);
452 #endif
453 
454 void hoc_notify_iv() {
455  IFGUI
456 #ifdef MINGW
457  if (!nrn_is_gui_thread()) {
458  // allow gui thread to run
459  nrnpy_pass();
460  hoc_pushx(0.);
461  hoc_ret();
462  return;
463  }
464  nrniv_bind_call();
465 #endif
466  Resource::flush();
467  Oc oc;
468  oc.notify();
470  ENDGUI
471  hoc_pushx(1.);
472  hoc_ret();
473 }
474 
476 
477 void Oc::notify() { // merely a possible change
479  notifyHocValue();
481  if (bbs_poll_ > 0)
482  bbs_handle();
483  WinDismiss::dismiss_defer(); // in case window was dismissed
484 }
487 }
490 }
491 #endif
#define ReqErr
Definition: _defines.h:223
#define Observable
Definition: _defines.h:190
#define Style
Definition: _defines.h:281
#define Event
Definition: _defines.h:107
bool acceptInput_
Definition: ivoc.h:30
virtual int exceptionRaised(int fd)
virtual int inputReady(int fd)
virtual void notify()
Definition: observe.cpp:75
virtual void attach(Observer *)
Definition: observe.cpp:54
virtual void detach(Observer *)
Definition: observe.cpp:63
virtual void update(Observable *)
Definition: observe.cpp:86
Definition: ivoc.h:36
double runExpr(Symbol *)
static void setStdinSeen(bool i)
Definition: ivoc.h:66
void notify_detach(Observer *)
void notify()
int run(int argc, const char **argv)
Oc()
static Observable * notify_change_
Definition: ivoc.h:87
void notify_attach(Observer *)
void notify_freed(void(*pf)(void *, int))
static Session * session_
Definition: ivoc.h:82
static int refcnt_
Definition: ivoc.h:81
void notify_when_freed(void *p, Observer *)
const char * name(Symbol *)
static bool helpmode_
Definition: ivoc.h:84
void notifyHocValue()
static bool setAcceptInput(bool)
Symbol * parseExpr(const char *, Symlist **=NULL)
void notify_pointer_disconnect(Observer *)
static int getStdinSeen()
Definition: ivoc.h:63
static HandleStdin * handleStdin_
Definition: ivoc.h:83
static Session * getSession()
static void flush()
Definition: resource.cpp:110
Definition: string.h:34
const char * string() const
Definition: string.h:139
static void dismiss_defer()
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
char buf[512]
Definition: init.cpp:13
void notify_freed_val_array(double *p, size_t size)
Definition: ivoc.cpp:101
void notify_pointer_freed(void *pt)
Definition: ivoc.cpp:81
Symbol * hoc_parse_expr(const char *str, Symlist **psymlist)
Definition: code2.cpp:659
void hoc_ret()
int hoc_oc(const char *buf)
Definition: hoc.cpp:1471
double hoc_run_expr(Symbol *sym)
Definition: code2.cpp:651
char * cxx_char_alloc(size_t sz)
Definition: ivoc.cpp:118
void nrnpy_pass()
Definition: fileio.cpp:853
void notify_freed(void *p)
Definition: ivoc.cpp:93
#define TRY_GUI_REDIRECT_DOUBLE(name, obj)
Definition: gui-redirect.h:58
int hoc_interviews
Definition: hoc.cpp:1649
#define IFGUI
Definition: hocdec.h:372
#define gargstr
Definition: hocdec.h:14
#define ENDGUI
Definition: hocdec.h:373
static char * env[]
Definition: inithoc.cpp:233
static int argc
Definition: inithoc.cpp:53
static char ** argv
Definition: inithoc.cpp:54
void
int bbs_poll_
Definition: datapath.cpp:31
void bbs_handle()
Definition: datapath.cpp:33
int hoc_execerror_messages
Definition: hoc.cpp:680
void nrn_err_dialog(const char *mes)
Definition: ivoc.cpp:132
static nrn::tool::bimap< double *, Observer * > * pdob
Definition: ivoc.cpp:31
void nrn_notify_freed(PF pf)
Definition: ivoc.cpp:45
static nrn::tool::bimap< void *, Observer * > * pvob
Definition: ivoc.cpp:30
double(* nrnpy_object_to_double_)(Object *)
Definition: xmenu.cpp:14
int nrn_err_dialog_active_
Definition: ivoc.cpp:39
void(* nrnpy_restore_thread)(void *)
Definition: ivoc.cpp:43
void nrn_notify_when_void_freed(void *p, Observer *ob)
Definition: ivoc.cpp:52
void nrn_notify_when_double_freed(double *p, Observer *ob)
Definition: ivoc.cpp:61
std::vector< PF > FList
Definition: ivoc.cpp:26
void nrniv_bind_thread(void)
Definition: ivoc.cpp:126
static FList * f_list
Definition: ivoc.cpp:28
void nrn_notify_pointer_disconnect(Observer *ob)
Definition: ivoc.cpp:70
void(*)(void *, int) PF
Definition: ivoc.cpp:25
void ivoc_cleanup()
Definition: ocnoiv1.cpp:17
#define Session
Definition: ivocmain.cpp:7
int hoc_print_first_instance
Definition: hoc_oop.cpp:38
void hoc_main1_init(const char *, const char **)
Definition: hoc.cpp:887
int hoc_main1(int, const char **, const char **)
Definition: hoc.cpp:983
void hoc_pushx(double)
int run_til_stdin()
Definition: ivocmain.cpp:889
char * name
Definition: init.cpp:16
#define printf
Definition: mwprefix.h:26
#define fprintf
Definition: mwprefix.h:30
void single_event_run()
size_t p
#define MUTCONSTRUCT(mkmut)
Definition: nrnmutdec.h:70
#define MUTDEC
Definition: nrnmutdec.h:68
#define MUTLOCK
Definition: nrnmutdec.h:72
#define MUTUNLOCK
Definition: nrnmutdec.h:73
FILE * hoc_fin
void hoc_notify_iv()
Definition: ocnoiv1.cpp:22
void ivoc_style()
Definition: ocnoiv1.cpp:171
void nrn_shape_update()
Definition: treeset.cpp:945
static const char ** pname(void *v)
Definition: ocpointer.cpp:70
static double done(void *v)
Definition: ocbbs.cpp:282
static Symbol * pv[4]
Definition: partial.cpp:80
#define e
Definition: passive0.cpp:22
o
Definition: seclist.cpp:175
#define NULL
Definition: sptree.h:16
Definition: hocdec.h:227
Definition: model.h:57
char * name
Definition: model.h:72
Definition: hocdec.h:84
void continue_dialog(const char *label, Window *w=NULL, Coord x=400., Coord y=400.)