NEURON
bbslsrv.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include "bbsconf.h"
3 #include <stdio.h>
4 #include <string.h>
5 #include "bbslsrv.h"
6 
7 #define INT 1
8 #define DOUBLE 2
9 #define STRING 3
10 #define VECTOR 4
11 #define PICKLE 5
12 
13 #if defined(HAVE_STL)
14 #if defined(HAVE_SSTREAM) // the standard ...
15 #include <map>
16 #include <set>
17 #include <string>
18 #else
19 #include <pair.h>
20 #include <multimap.h>
21 #include <map.h>
22 #include <set.h>
23 #include <string.h>
24 #endif
25 
26 // debug is 0 1 or 2
27 #define debug 0
28 
29 class WorkItem {
30 public:
31  WorkItem(int id, MessageValue*);
32  virtual ~WorkItem();
33  WorkItem* parent_;
34  int id_;
35  MessageValue* val_;
36  bool todo_less_than(const WorkItem*)const;
37 };
38 
39 struct ltstr {
40  bool operator() (const char* s1, const char* s2) const {
41  return strcmp(s1, s2) < 0;
42  }
43 };
44 
45 struct ltint {
46  bool operator() (int i, int j) const {
47  return i < j;
48  }
49 };
50 
51 struct ltWorkItem {
52  bool operator() (const WorkItem* w1, const WorkItem* w2) const {
53  return w1->todo_less_than(w2);
54  }
55 };
56 
57 static char* newstr(const char* s) {
58  char* s1 = new char[strlen(s) + 1];
59  strcpy(s1, s);
60  return s1;
61 }
62 
63 
64 WorkItem::WorkItem(int id, MessageValue* m) {
65 #if debug == 2
66 printf("WorkItem %d\n", id);
67 #endif
68  id_ = id;
69  val_ = m;
70  val_->ref();
71  parent_ = nil;
72 }
73 
74 WorkItem::~WorkItem() {
75 #if debug
76 printf("~WorkItem %d\n", id_);
77 #endif
78  val_->unref();
79 }
80 
81 bool WorkItem::todo_less_than(const WorkItem* w) const {
82  WorkItem* w1 = (WorkItem*)this;
83  WorkItem* w2 = (WorkItem*)w;
84  while (w1->parent_ != w2->parent_) {
85  if (w1->id_ < w2->id_) {
86  w2 = w2->parent_;
87  }else{
88  w1 = w1->parent_;
89  }
90  }
91 #if debug
92 printf("todo_less_than %d < %d return %d\n", this->id_, w->id_, w1->id_ < w2->id_);
93 #endif
94  return w1->id_ < w2->id_;
95 }
96 
97 class MessageList : public std::multimap <const char*, const MessageValue*, ltstr>{};
98 class WorkList : public std::map <int, const WorkItem*, ltint>{};
99 class ReadyList : public std::set<WorkItem*, ltWorkItem>{};
100 class ResultList: public std::multimap<int, const WorkItem*, ltint>{};
101 #else
102 class MessageList {};
103 class WorkList {};
104 class ReadyList{};
105 class ResultList{};
106 extern "C" void hoc_execerror(const char*, const char*);
107 static void nostl() {
108 hoc_execerror("BBSLocalServer not working", "Compiled without STL");
109 }
110 #endif
111 
113  next_ = nil;
114  type_ = 0;
115 }
116 
118  switch (type_) {
119  case STRING:
120  delete [] u.s;
121  break;
122  case VECTOR:
123  delete [] u.pd;
124  break;
125  case PICKLE:
126  delete [] u.s;
127  break;
128  }
129 }
130 
132  first_ = nil;
133  last_ = nil;
134  unpack_ = nil;
135 }
136 
138  MessageItem* mi, *next;
139  for (mi = first_; mi; mi = next) {
140  next = mi->next_;
141  delete mi;
142  }
143 }
144 
146  MessageItem* mi = new MessageItem();
147  if (last_) {
148  last_->next_ = mi;
149  }else{
150  first_ = mi;
151  unpack_ = mi;
152  }
153  last_ = mi;
154  return mi;
155 }
156 
158  unpack_ = first_;
159 }
160 
162  MessageItem* m = link();
163  m->type_ = INT;
164  m->u.i = i;
165  return 0;
166 }
167 
168 int MessageValue::pkdouble(double x) {
169  MessageItem* m = link();
170  m->type_ = DOUBLE;
171  m->u.d = x;
172  return 0;
173 }
174 
175 int MessageValue::pkvec(int n, double* x) {
176  int i;
177  MessageItem* m = link();
178  m->type_ = VECTOR;
179  m->u.pd = new double[n];
180  for (i=0; i < n; ++i) {
181  m->u.pd[i] = x[i];
182  }
183  return 0;
184 }
185 
186 int MessageValue::pkstr(const char* str) {
187  MessageItem* m = link();
188  m->type_ = STRING;
189  m->u.s = new char[strlen(str)+1];
190  strcpy(m->u.s, str);
191  return 0;
192 }
193 
194 int MessageValue::pkpickle(const char* bytes, size_t n) {
195  MessageItem* m = link();
196  m->type_ = PICKLE;
197  m->u.s = new char[n];
198  m->size_ = n;
199  memcpy(m->u.s, bytes, n);
200  return 0;
201 }
202 
204  if (!unpack_ || unpack_->type_ != INT) {
205  return -1;
206  }
207  *i = unpack_->u.i;
208  unpack_ = unpack_->next_;
209  return 0;
210 }
211 
212 int MessageValue::upkdouble(double* d) {
213  if (!unpack_ || unpack_->type_ != DOUBLE) {
214  return -1;
215  }
216  *d = unpack_->u.d;
217  unpack_ = unpack_->next_;
218  return 0;
219 }
220 
221 int MessageValue::upkvec(int n, double* d) {
222  int i;
223  if (!unpack_ || unpack_->type_ != VECTOR) {
224  return -1;
225  }
226  for (i = 0; i < n; ++i) {
227  d[i] = unpack_->u.pd[i];
228  }
229  unpack_ = unpack_->next_;
230  return 0;
231 }
232 
234  if (!unpack_ || unpack_->type_ != STRING) {
235  return -1;
236  }
237  strcpy(s, unpack_->u.s);
238  unpack_ = unpack_->next_;
239  return 0;
240 }
241 
242 int MessageValue::upkpickle(char* s, size_t* n) {
243  if (!unpack_ || unpack_->type_ != PICKLE) {
244  return -1;
245  }
246  *n = unpack_->size_;
247  memcpy(s, unpack_->u.s, *n);
248  unpack_ = unpack_->next_;
249  return 0;
250 }
251 
253 #if defined(HAVE_STL)
254  messages_ = new MessageList();
255  work_ = new WorkList();
256  todo_ = new ReadyList();
257  results_ = new ResultList();
258  next_id_ = 1;
259 #endif
260 }
261 
263 #if defined(HAVE_STL)
264  delete todo_;
265  delete results_;
266 
267 printf("~BBSLocalServer not deleting everything\n");
268 // need to unref MessageValue in messages_ and delete WorkItem in work_
269  delete messages_;
270  delete work_;
271 #endif
272 }
273 
275 #if defined(HAVE_STL)
276  MessageList::iterator m = messages_->find(key);
277  if (m != messages_->end()) {
278  *val = (MessageValue*)((*m).second);
279  char* s = (char*)((*m).first);
280  messages_->erase(m);
281  delete [] s;
282 #if debug
283  printf("srvr_look_take |%s|\n", key);
284 #endif
285  return true;
286  }
287 #if debug
288  printf("fail srvr_look_take |%s|\n", key);
289 #endif
290 #else
291 nostl();
292 #endif
293  return false;
294 }
295 
296 bool BBSLocalServer::look(const char* key, MessageValue** val) {
297 #if defined(HAVE_STL)
298  MessageList::iterator m = messages_->find(key);
299  if (m != messages_->end()) {
300  *val = (MessageValue*)((*m).second);
301  Resource::ref(*val);
302 #if debug
303  printf("srvr_look true |%s|\n", key);
304 #endif
305  return true;
306  }else{
307  val = nil;
308  }
309 #if debug
310  printf("srvr_look false |%s|\n", key);
311 #endif
312 #else
313 nostl();
314 #endif
315  return false;
316 }
317 
319 #if defined(HAVE_STL)
320  MessageList::iterator m = messages_->insert(
321  std::pair<const char* const, const MessageValue*>(newstr(key),val)
322  );
323  Resource::ref(val);
324 #if debug
325  printf("srvr_post |%s|\n", key);
326 #endif
327 #else
328 nostl();
329 #endif
330 }
331 
333 #if defined(HAVE_STL)
334  WorkItem* w = new WorkItem(next_id_++, val);
335  WorkList::iterator p = work_->find(parentid);
336  if (p != work_->end()) {
337  w->parent_ = (WorkItem*)((*p).second);
338  }
339  work_->insert(std::pair<const int, const WorkItem*>(w->id_, w));
340  todo_->insert(w);
341 #if debug
342  printf("srvr_post_todo id=%d pid=%d\n", w->id_, parentid);
343 #endif
344 #else
345 nostl();
346 #endif
347 }
348 
350 #if defined(HAVE_STL)
351  WorkList::iterator i = work_->find(id);
352  WorkItem* w = (WorkItem*)((*i).second);
353  val->ref();
354  w->val_->unref();
355  w->val_ = val;
356  results_->insert(std::pair<const int, const WorkItem*>(w->parent_ ? w->parent_->id_ : 0, w));
357 #if debug
358  printf("srvr_post_done id=%d pid=%d\n", id, w->parent_ ? w->parent_->id_ : 0);
359 #endif
360 #endif
361 }
362 
364 #if defined(HAVE_STL)
365  ReadyList::iterator i = todo_->begin();
366  if (i != todo_->end()) {
367  WorkItem* w = (*i);
368  todo_->erase(i);
369  *m = w->val_;
370 #if debug
371 printf("srvr look_take_todo %d\n", w->id_);
372 #endif
373  w->val_->ref();
374  return w->id_;
375  }else{
376 #if debug
377 printf("srvr look_take_todo failed\n");
378 #endif
379  return 0;
380  }
381 #else
382 nostl();
383 return 0;
384 #endif
385 }
386 
388 #if defined(HAVE_STL)
389  ResultList::iterator i = results_->find(pid);
390  if (i != results_->end()) {
391  WorkItem* w = (WorkItem*)((*i).second);
392  results_->erase(i);
393  *m = w->val_;
394  w->val_->ref();
395  int id = w->id_;
396  WorkList::iterator j = work_->find(id);
397  work_->erase(j);
398 #if debug
399 printf("srvr look_take_result %d for parent %d\n", w->id_, pid);
400 #endif
401  delete w;
402  return id;
403  }else{
404 #if debug
405 printf("srvr look_take_result failed for parent %d\n", pid);
406 #endif
407  return 0;
408  }
409 #else
410 nostl();
411 return 0;
412 #endif
413 }
414 
#define INT
Definition: bbslsrv.cpp:7
int look_take_result(int pid, MessageValue **)
Definition: bbslsrv.cpp:387
void init_unpack()
Definition: bbslsrv.cpp:157
int look_take_todo(MessageValue **)
Definition: bbslsrv.cpp:363
size_t p
static void nostl()
Definition: bbslsrv.cpp:107
void post_todo(int parentid, MessageValue *)
Definition: bbslsrv.cpp:332
Item * next(Item *item)
Definition: list.cpp:95
MessageItem * link()
Definition: bbslsrv.cpp:145
virtual void ref() const
Definition: resource.cpp:47
virtual ~BBSLocalServer()
Definition: bbslsrv.cpp:262
int pkdouble(double)
Definition: bbslsrv.cpp:168
int upkdouble(double *)
Definition: bbslsrv.cpp:212
MessageItem * next_
Definition: bbslsrv.h:15
char * s
Definition: bbslsrv.h:22
static double map(void *v)
Definition: mlinedit.cpp:46
virtual ~MessageValue()
Definition: bbslsrv.cpp:137
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
int const size_t const size_t n
Definition: nrngsl.h:12
_CONST char * s
Definition: system.cpp:74
bool look(const char *key, MessageValue **)
Definition: bbslsrv.cpp:296
int val
Definition: dll.cpp:167
#define printf
Definition: mwprefix.h:26
bool look_take(const char *key, MessageValue **)
Definition: bbslsrv.cpp:274
size_t size_
Definition: bbslsrv.h:17
void post_result(int id, MessageValue *)
Definition: bbslsrv.cpp:349
#define STRING
Definition: bbslsrv.cpp:9
union MessageItem::@60 u
#define key
Definition: spt2queue.cpp:20
size_t j
#define PICKLE
Definition: bbslsrv.cpp:11
int pkpickle(const char *, size_t)
Definition: bbslsrv.cpp:194
#define nil
Definition: enter-scope.h:36
int pkvec(int, double *)
Definition: bbslsrv.cpp:175
virtual ~MessageItem()
Definition: bbslsrv.cpp:117
#define DOUBLE
Definition: bbslsrv.cpp:8
double * pd
Definition: bbslsrv.h:21
void post(const char *key, MessageValue *)
Definition: bbslsrv.cpp:318
int pkint(int)
Definition: bbslsrv.cpp:161
double d
Definition: bbslsrv.h:20
int upkint(int *)
Definition: bbslsrv.cpp:203
int upkpickle(char *, size_t *)
Definition: bbslsrv.cpp:242
#define i
Definition: md1redef.h:12
#define id
Definition: md1redef.h:33
int upkvec(int, double *)
Definition: bbslsrv.cpp:221
int type_
Definition: bbslsrv.h:16
int pkstr(const char *)
Definition: bbslsrv.cpp:186
#define VECTOR
Definition: bbslsrv.cpp:10
static N_Vector id_
int upkstr(char *)
Definition: bbslsrv.cpp:233