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 
233 int MessageValue::upkstr(char* s) {
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 
274 bool BBSLocalServer::look_take(const char* key, MessageValue** val) {
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 
318 void BBSLocalServer::post(const char* key, MessageValue* val) {
319 #if defined(HAVE_STL)
320  MessageList::iterator m = messages_->insert(
321  std::pair<const char* const, const MessageValue*>(newstr(key), val));
322  Resource::ref(val);
323 #if debug
324  printf("srvr_post |%s|\n", key);
325 #endif
326 #else
327  nostl();
328 #endif
329 }
330 
331 void BBSLocalServer::post_todo(int parentid, MessageValue* val) {
332 #if defined(HAVE_STL)
333  WorkItem* w = new WorkItem(next_id_++, val);
334  WorkList::iterator p = work_->find(parentid);
335  if (p != work_->end()) {
336  w->parent_ = (WorkItem*) ((*p).second);
337  }
338  work_->insert(std::pair<const int, const WorkItem*>(w->id_, w));
339  todo_->insert(w);
340 #if debug
341  printf("srvr_post_todo id=%d pid=%d\n", w->id_, parentid);
342 #endif
343 #else
344  nostl();
345 #endif
346 }
347 
349 #if defined(HAVE_STL)
350  WorkList::iterator i = work_->find(id);
351  WorkItem* w = (WorkItem*) ((*i).second);
352  val->ref();
353  w->val_->unref();
354  w->val_ = val;
355  results_->insert(std::pair<const int, const WorkItem*>(w->parent_ ? w->parent_->id_ : 0, w));
356 #if debug
357  printf("srvr_post_done id=%d pid=%d\n", id, w->parent_ ? w->parent_->id_ : 0);
358 #endif
359 #endif
360 }
361 
363 #if defined(HAVE_STL)
364  ReadyList::iterator i = todo_->begin();
365  if (i != todo_->end()) {
366  WorkItem* w = (*i);
367  todo_->erase(i);
368  *m = w->val_;
369 #if debug
370  printf("srvr look_take_todo %d\n", w->id_);
371 #endif
372  w->val_->ref();
373  return w->id_;
374  } else {
375 #if debug
376  printf("srvr look_take_todo failed\n");
377 #endif
378  return 0;
379  }
380 #else
381  nostl();
382  return 0;
383 #endif
384 }
385 
387 #if defined(HAVE_STL)
388  ResultList::iterator i = results_->find(pid);
389  if (i != results_->end()) {
390  WorkItem* w = (WorkItem*) ((*i).second);
391  results_->erase(i);
392  *m = w->val_;
393  w->val_->ref();
394  int id = w->id_;
395  WorkList::iterator j = work_->find(id);
396  work_->erase(j);
397 #if debug
398  printf("srvr look_take_result %d for parent %d\n", w->id_, pid);
399 #endif
400  delete w;
401  return id;
402  } else {
403 #if debug
404  printf("srvr look_take_result failed for parent %d\n", pid);
405 #endif
406  return 0;
407  }
408 #else
409  nostl();
410  return 0;
411 #endif
412 }
#define nil
Definition: enter-scope.h:36
bool look(const char *key, MessageValue **)
Definition: bbslsrv.cpp:296
ResultList * results_
Definition: bbslsrv.h:72
MessageList * messages_
Definition: bbslsrv.h:69
WorkList * work_
Definition: bbslsrv.h:70
ReadyList * todo_
Definition: bbslsrv.h:71
void post_result(int id, MessageValue *)
Definition: bbslsrv.cpp:348
int next_id_
Definition: bbslsrv.h:73
void post_todo(int parentid, MessageValue *)
Definition: bbslsrv.cpp:331
virtual ~BBSLocalServer()
Definition: bbslsrv.cpp:262
int look_take_result(int pid, MessageValue **)
Definition: bbslsrv.cpp:386
void post(const char *key, MessageValue *)
Definition: bbslsrv.cpp:318
bool look_take(const char *key, MessageValue **)
Definition: bbslsrv.cpp:274
int look_take_todo(MessageValue **)
Definition: bbslsrv.cpp:362
size_t size_
Definition: bbslsrv.h:17
MessageItem * next_
Definition: bbslsrv.h:15
int type_
Definition: bbslsrv.h:16
virtual ~MessageItem()
Definition: bbslsrv.cpp:117
char * s
Definition: bbslsrv.h:22
double d
Definition: bbslsrv.h:20
double * pd
Definition: bbslsrv.h:21
union MessageItem::@45 u
int pkdouble(double)
Definition: bbslsrv.cpp:168
int upkdouble(double *)
Definition: bbslsrv.cpp:212
int pkint(int)
Definition: bbslsrv.cpp:161
int upkstr(char *)
Definition: bbslsrv.cpp:233
int upkint(int *)
Definition: bbslsrv.cpp:203
MessageItem * last_
Definition: bbslsrv.h:50
int upkvec(int, double *)
Definition: bbslsrv.cpp:221
MessageItem * first_
Definition: bbslsrv.h:49
MessageItem * link()
Definition: bbslsrv.cpp:145
MessageItem * unpack_
Definition: bbslsrv.h:51
int upkpickle(char *, size_t *)
Definition: bbslsrv.cpp:242
virtual ~MessageValue()
Definition: bbslsrv.cpp:137
int pkpickle(const char *, size_t)
Definition: bbslsrv.cpp:194
int pkstr(const char *)
Definition: bbslsrv.cpp:186
int pkvec(int, double *)
Definition: bbslsrv.cpp:175
void init_unpack()
Definition: bbslsrv.cpp:157
virtual void ref() const
Definition: resource.cpp:47
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
static double map(void *v)
Definition: mlinedit.cpp:47
Item * next(Item *item)
Definition: list.cpp:88
#define printf
Definition: mwprefix.h:26
int const size_t const size_t n
Definition: nrngsl.h:11
size_t p
size_t j
static N_Vector id_
#define STRING
Definition: bbslsrv.cpp:9
static void nostl()
Definition: bbslsrv.cpp:107
#define PICKLE
Definition: bbslsrv.cpp:11
#define DOUBLE
Definition: bbslsrv.cpp:8
#define VECTOR
Definition: bbslsrv.cpp:10
#define INT
Definition: bbslsrv.cpp:7
#define key
Definition: spt2queue.cpp:20