NEURON
bbslsrv.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include "bbslsrv.hpp"
5 #include "oc_ansi.h"
6 
7 #define INT 1
8 #define DOUBLE 2
9 #define STRING 3
10 #define VECTOR 4
11 #define PICKLE 5
12 
13 #include <map>
14 #include <set>
15 #include <string>
16 
17 // debug is 0 1 or 2
18 #define debug 0
19 
20 class WorkItem {
21  public:
22  WorkItem(int id, MessageValue*);
23  virtual ~WorkItem();
25  int id_;
27  bool todo_less_than(const WorkItem*) const;
28 };
29 
30 struct ltstr {
31  bool operator()(const char* s1, const char* s2) const {
32  return strcmp(s1, s2) < 0;
33  }
34 };
35 
36 struct ltWorkItem {
37  bool operator()(const WorkItem* w1, const WorkItem* w2) const {
38  return w1->todo_less_than(w2);
39  }
40 };
41 
42 static char* newstr(const char* s) {
43  char* s1 = new char[strlen(s) + 1];
44  strcpy(s1, s);
45  return s1;
46 }
47 
48 
50 #if debug == 2
51  printf("WorkItem %d\n", id);
52 #endif
53  id_ = id;
54  val_ = m;
55  val_->ref();
56  parent_ = nullptr;
57 }
58 
60 #if debug
61  printf("~WorkItem %d\n", id_);
62 #endif
63  val_->unref();
64 }
65 
66 bool WorkItem::todo_less_than(const WorkItem* w) const {
67  WorkItem* w1 = (WorkItem*) this;
68  WorkItem* w2 = (WorkItem*) w;
69  while (w1->parent_ != w2->parent_) {
70  if (w1->id_ < w2->id_) {
71  w2 = w2->parent_;
72  } else {
73  w1 = w1->parent_;
74  }
75  }
76 #if debug
77  printf("todo_less_than %d < %d return %d\n", this->id_, w->id_, w1->id_ < w2->id_);
78 #endif
79  return w1->id_ < w2->id_;
80 }
81 
82 class MessageList: public std::multimap<const char*, const MessageValue*, ltstr> {};
83 class WorkList: public std::map<int, const WorkItem*> {};
84 class ReadyList: public std::set<WorkItem*, ltWorkItem> {};
85 class ResultList: public std::multimap<int, const WorkItem*> {};
86 
88  index_ = 0;
89 }
90 
92  args_.emplace_back(i);
93  return 0;
94 }
95 
96 int MessageValue::pkdouble(double x) {
97  args_.emplace_back(x);
98  return 0;
99 }
100 
101 int MessageValue::pkvec(int n, double* x) {
102  args_.emplace_back(std::vector<double>(x, x + n));
103  return 0;
104 }
105 
106 int MessageValue::pkstr(const char* str) {
107  args_.emplace_back(std::string(str));
108  return 0;
109 }
110 
111 int MessageValue::pkpickle(const std::vector<char>& s) {
112  args_.emplace_back(std::vector<char>(s));
113  return 0;
114 }
115 
117  if (index_ > args_.size()) {
118  return -1;
119  }
120  if (const auto* val = std::get_if<int>(args_.data() + index_)) {
121  *i = *val;
122  ++index_;
123  return 0;
124  }
125  return -1;
126 }
127 
128 int MessageValue::upkdouble(double* d) {
129  if (const auto* val = std::get_if<double>(args_.data() + index_)) {
130  *d = *val;
131  ++index_;
132  return 0;
133  }
134  return -1;
135 }
136 
137 int MessageValue::upkvec(int n, double* d) {
138  if (const auto* val = std::get_if<std::vector<double>>(args_.data() + index_)) {
139  for (std::size_t i = 0; i < n; ++i) {
140  d[i] = val->at(i);
141  }
142  ++index_;
143  return 0;
144  }
145  return -1;
146 }
147 
149  if (const auto* val = std::get_if<std::string>(args_.data() + index_)) {
150  for (std::size_t i = 0; i < val->size(); ++i) {
151  s[i] = val->at(i);
152  }
153  s[val->size()] = '\0';
154  ++index_;
155  return 0;
156  }
157  return -1;
158 }
159 
160 int MessageValue::upkpickle(std::vector<char>& s) {
161  if (const auto* val = std::get_if<std::vector<char>>(args_.data() + index_)) {
162  s = *val;
163  ++index_;
164  return 0;
165  }
166  return -1;
167 }
168 
170  messages_ = new MessageList();
171  work_ = new WorkList();
172  todo_ = new ReadyList();
173  results_ = new ResultList();
174  next_id_ = 1;
175 }
176 
178  delete todo_;
179  delete results_;
180 
181  printf("~BBSLocalServer not deleting everything\n");
182  // need to unref MessageValue in messages_ and delete WorkItem in work_
183  delete messages_;
184  delete work_;
185 }
186 
187 bool BBSLocalServer::look_take(const char* key, MessageValue** val) {
188  MessageList::iterator m = messages_->find(key);
189  if (m != messages_->end()) {
190  *val = const_cast<MessageValue*>((*m).second);
191  char* s = (char*) ((*m).first);
192  messages_->erase(m);
193  delete[] s;
194 #if debug
195  printf("srvr_look_take |%s|\n", key);
196 #endif
197  return true;
198  }
199 #if debug
200  printf("fail srvr_look_take |%s|\n", key);
201 #endif
202  return false;
203 }
204 
205 bool BBSLocalServer::look(const char* key, MessageValue** val) {
206  MessageList::iterator m = messages_->find(key);
207  if (m != messages_->end()) {
208  *val = const_cast<MessageValue*>((*m).second);
209  Resource::ref(*val);
210 #if debug
211  printf("srvr_look true |%s|\n", key);
212 #endif
213  return true;
214  } else {
215  val = nullptr;
216  }
217 #if debug
218  printf("srvr_look false |%s|\n", key);
219 #endif
220  return false;
221 }
222 
223 void BBSLocalServer::post(const char* key, MessageValue* val) {
224  messages_->emplace(newstr(key), val);
225  Resource::ref(val);
226 #if debug
227  printf("srvr_post |%s|\n", key);
228 #endif
229 }
230 
231 void BBSLocalServer::post_todo(int parentid, MessageValue* val) {
232  WorkItem* w = new WorkItem(next_id_++, val);
233  WorkList::iterator p = work_->find(parentid);
234  if (p != work_->end()) {
235  w->parent_ = (WorkItem*) ((*p).second);
236  }
237  work_->emplace(w->id_, w);
238  todo_->emplace(w);
239 #if debug
240  printf("srvr_post_todo id=%d pid=%d\n", w->id_, parentid);
241 #endif
242 }
243 
245  WorkList::iterator i = work_->find(id);
246  WorkItem* w = (WorkItem*) ((*i).second);
247  val->ref();
248  w->val_->unref();
249  w->val_ = val;
250  results_->emplace(w->parent_ ? w->parent_->id_ : 0, w);
251 #if debug
252  printf("srvr_post_done id=%d pid=%d\n", id, w->parent_ ? w->parent_->id_ : 0);
253 #endif
254 }
255 
257  ReadyList::iterator i = todo_->begin();
258  if (i != todo_->end()) {
259  WorkItem* w = (*i);
260  todo_->erase(i);
261  *m = w->val_;
262 #if debug
263  printf("srvr look_take_todo %d\n", w->id_);
264 #endif
265  w->val_->ref();
266  return w->id_;
267  } else {
268 #if debug
269  printf("srvr look_take_todo failed\n");
270 #endif
271  return 0;
272  }
273 }
274 
276  ResultList::iterator i = results_->find(pid);
277  if (i != results_->end()) {
278  WorkItem* w = (WorkItem*) ((*i).second);
279  results_->erase(i);
280  *m = w->val_;
281  w->val_->ref();
282  int id = w->id_;
283  WorkList::iterator j = work_->find(id);
284  work_->erase(j);
285 #if debug
286  printf("srvr look_take_result %d for parent %d\n", w->id_, pid);
287 #endif
288  delete w;
289  return id;
290  } else {
291 #if debug
292  printf("srvr look_take_result failed for parent %d\n", pid);
293 #endif
294  return 0;
295  }
296 }
static char * newstr(const char *s)
Definition: bbslsrv.cpp:42
bool look(const char *key, MessageValue **)
Definition: bbslsrv.cpp:205
ResultList * results_
Definition: bbslsrv.hpp:55
MessageList * messages_
Definition: bbslsrv.hpp:52
WorkList * work_
Definition: bbslsrv.hpp:53
ReadyList * todo_
Definition: bbslsrv.hpp:54
void post_result(int id, MessageValue *)
Definition: bbslsrv.cpp:244
void post_todo(int parentid, MessageValue *)
Definition: bbslsrv.cpp:231
virtual ~BBSLocalServer()
Definition: bbslsrv.cpp:177
int look_take_result(int pid, MessageValue **)
Definition: bbslsrv.cpp:275
void post(const char *key, MessageValue *)
Definition: bbslsrv.cpp:223
bool look_take(const char *key, MessageValue **)
Definition: bbslsrv.cpp:187
int look_take_todo(MessageValue **)
Definition: bbslsrv.cpp:256
std::size_t index_
Definition: bbslsrv.hpp:34
int pkdouble(double)
Definition: bbslsrv.cpp:96
int upkdouble(double *)
Definition: bbslsrv.cpp:128
int pkpickle(const std::vector< char > &)
Definition: bbslsrv.cpp:111
int pkint(int)
Definition: bbslsrv.cpp:91
int upkstr(char *)
Definition: bbslsrv.cpp:148
int upkint(int *)
Definition: bbslsrv.cpp:116
int upkvec(int, double *)
Definition: bbslsrv.cpp:137
int upkpickle(std::vector< char > &)
Definition: bbslsrv.cpp:160
std::vector< MessageItem > args_
Definition: bbslsrv.hpp:33
int pkstr(const char *)
Definition: bbslsrv.cpp:106
int pkvec(int, double *)
Definition: bbslsrv.cpp:101
void init_unpack()
Definition: bbslsrv.cpp:87
virtual void ref() const
Definition: resource.cpp:42
virtual void unref() const
Definition: resource.cpp:47
bool todo_less_than(const WorkItem *) const
Definition: bbslsrv.cpp:66
MessageValue * val_
Definition: bbslsrv.cpp:26
int id_
Definition: bbslsrv.cpp:25
WorkItem * parent_
Definition: bbslsrv.cpp:24
WorkItem(int id, MessageValue *)
Definition: bbslsrv.cpp:49
virtual ~WorkItem()
Definition: bbslsrv.cpp:59
#define key
Definition: tqueue.hpp:45
#define id
Definition: md1redef.h:41
#define i
Definition: md1redef.h:19
static double map(void *v)
Definition: mlinedit.cpp:43
printf
Definition: extdef.h:5
int const size_t const size_t n
Definition: nrngsl.h:10
size_t p
size_t j
w2
Definition: multisend.cpp:498
w1
Definition: multisend.cpp:497
s
Definition: multisend.cpp:521
HOC interpreter function declarations (included by hocdec.h)
bool operator()(const WorkItem *w1, const WorkItem *w2) const
Definition: bbslsrv.cpp:37
bool operator()(const char *s1, const char *s2) const
Definition: bbslsrv.cpp:31