NEURON
sptfifoq.cpp
Go to the documentation of this file.
1 // splay tree + fifofor event-sets or priority queues
2 // this starts from the sptqueue.cpp file and adds a fifo
3 
4 /* Derived from David Brower's c translation of pascal code by
5 Douglas Jones.
6 */
7 /* The original c code is included from this file but note that instead
8 of struct _spblk, we are really using TQItem
9 */
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdarg.h>
15 
16 #define leftlink left_
17 #define rightlink right_
18 #define uplink parent_
19 #define cnt cnt_
20 #define key t_
21 #include <sptree.h>
22 
24  left_ = 0;
25  right_ = 0;
26  parent_ = 0;
27 }
28 
30 }
31 
32 static void deleteitem(TQItem* i) { // only one, semantics changed
33  assert(i);
34  tpool_->hpfree(i);
35 }
36 
37 bool TQItem::check() {
38 #if DOCHECK
39 #endif
40  return true;
41 }
42 
43 static void prnt(const TQItem* b, int level) {
44  int i;
45  for (i=0; i < level; ++i) {
46  Printf(" ");
47  }
48  Printf("%g %c %d Q=%p D=%p\n", b->t_, b->data_?'x':'o', b->cnt_, b, b->data_);
49 }
50 
51 static void chk(TQItem* b, int level) {
52  if (!b->check()) {
53  hoc_execerror("chk failed", errmess_);
54  }
55 }
56 
58  if (!tpool_) {
59  tpool_ = new TQItemPool(1000);
60  }
61  sptree_ = new SPTREE;
62  spinit(sptree_);
63  fifo_ = new FifoQ;
64  least_ = 0;
65 
66 #if COLLECT_TQueue_STATISTICS
67  nmove = ninsert = nrem = nleast = nbal = ncmplxrem = 0;
68  nfastmove = ncompare = nleastsrch = nfind = nfindsrch = 0;
69 #endif
70 }
71 
73  TQItem* q;
74  while((q = spdeq(&sptree_->root)) != nil) {
75  deleteitem(q);
76  }
77  delete sptree_;
78  while((q = fifo_->dequeue()) != nil) {
79  deleteitem(q);
80  }
81  delete fifo_;
82 }
83 
84 void TQueue::print() {
85 #if FAST_LEAST
86  if (least_) {
87  prnt(least_, 0);
88  }
89 #endif
90  spscan(prnt, nil, sptree_);
91  for (TQItem* q = fifo_->first(); q; q = fifo_->next(q)) {
92  prnt(q, 0);
93  }
94 }
95 
96 void TQueue::forall_callback(void(*f)(const TQItem*, int)) {
97 #if FAST_LEAST
98  if (least_) {
99  f(least_, 0);
100  }
101 #endif
102  spscan(f, nil, sptree_);
103  for (TQItem* q = fifo_->first(); q; q = fifo_->next(q)) {
104  f(q, 0);
105  }
106 }
107 
108 void TQueue::check(const char* mes) {
109 }
110 
111 void TQueue::move_least(double tnew) {
112  TQItem* b = least();
113  if (b) {
114  b->t_ = tnew;
115  TQItem* nl = sphead(sptree_);
116  if (nl) {
117  if (tnew <= nl->t_ && tnew <= fifo_->least_t()) {
118  ;
119  }else if (nl->t_ <= fifo_->least_t()) {
120  least_ = spdeq(&sptree_->root);
121  spenq(b, sptree_);
122  }else{
123  least_ = fifo_->dequeue();
124  spenq(b, sptree_);
125  }
126  }else if (tnew > fifo_->least_t()) {
127  least_ = fifo_->dequeue();
128  spenq(b, sptree_);
129  }
130  }
131 }
132 
133 void TQueue::move(TQItem* i, double tnew) {
134  STAT(nmove)
135  if (i == least_) {
136  move_least(tnew);
137  }else if (tnew < least_->t_) {
138  spdelete(i, sptree_);
139  i->t_ = tnew;
140  spenq(least_, sptree_);
141  least_ = i;
142  }else{
143  spdelete(i, sptree_);
144  i->t_ = tnew;
145  spenq(i, sptree_);
146  }
147 }
148 
149 void TQueue::statistics() {
150 #if COLLECT_TQueue_STATISTICS
151  Printf("insertions=%lu moves=%lu removals=%lu calls to least=%lu\n",
152  ninsert, nmove, nrem, nleast);
153  Printf("calls to find=%lu\n",
154  nfind);
155  Printf("comparisons=%lu\n",
156  sptree_->enqcmps);
157 #else
158  Printf("Turn on COLLECT_TQueue_STATISTICS_ in tqueue.h\n");
159 #endif
160 }
161 
162 void TQueue::spike_stat(double* d) {
163 #if COLLECT_TQueue_STATISTICS
164  d[0] = ninsert;
165  d[1] = nmove;
166  d[2] = nrem;
167 //printf("FifoQ spikestat nfenq=%lu nfdeq=%lu nfrem=%lu\n", fifo_->nfenq, fifo_->nfdeq, fifo_->nfrem);
168 #endif
169 }
170 
171 TQItem* TQueue::insert(double t, void* d) {
172  STAT(ninsert);
173  TQItem* i = tpool_->alloc();
174  i->data_ = d;
175  i->t_ = t;
176  i->cnt_ = 0;
177  if (t < least_t()) {
178  if (least()) {
179  spenq(least(), sptree_);
180  }
181  least_ = i;
182  }else{
183  spenq(i, sptree_);
184  }
185  return i;
186 }
187 
188 TQItem* TQueue::insert_fifo(double t, void* d) {
189  STAT(ninsert);
190  TQItem* i = tpool_->alloc();
191  i->data_ = d;
192  i->t_ = t;
193  i->cnt_ = 0;
194  if (t < least_t()) {
195  if (least()) {
196  spenq(least(), sptree_);
197  }
198  least_ = i;
199  }else{
200  fifo_->enqueue(i);
201  }
202  return i;
203 }
204 
205 void TQueue::remove(TQItem* q) {
206  STAT(nrem);
207  if (q) {
208  if (q == least_) {
209  if (sptree_->root) {
210  TQItem* nl = sphead(sptree_);
211  if (nl->t_ <= fifo_->least_t()) {
212  least_ = spdeq(&sptree_->root);
213  }else{
214  least_ = fifo_->dequeue();
215  }
216  }else{
217  least_ = fifo_->dequeue();
218  }
219  }else{
220  if (q->cnt_ == -1) {
221  fifo_->remove(q);
222  }else{
223  spdelete(q, sptree_);
224  }
225  }
226  tpool_->hpfree(q);
227  }
228 }
229 
230 TQItem* TQueue::find(double t) {
231  // search only in the splay tree. if this is a bug then fix it.
232  STAT(nfind)
233  if (t == least_t()) {
234  return least();
235  }
236  TQItem* q;
237  q = splookup(t, sptree_);
238  return(q);
239 }
240 
242  head_ = tail_ = 0;
243 #if COLLECT_TQueue_STATISTICS
244  nfenq = nfdeq = nfrem = 0;
245 #endif
246 }
247 
249  assert (head_ == 0 && tail_ == 0);
250 }
251 
252 double FifoQ::least_t() {
253  if (head_) { return head_->t_; }
254  return 1e50; // must be larger than any possible t
255 }
257  if (tail_) { assert(tail_->t_ <= q->t_); }
258  q->cnt_ = -1;
259  q->left_ = tail_;
260  q->right_ = 0;
261  tail_ = q;
262  if (head_) { tail_->left_->right_ = q;} else { head_ = tail_; }
263 #if COLLECT_TQueue_STATISTICS
264  ++nfenq;
265 #endif
266 }
268  TQItem* q = head_;
269  if (head_ == tail_) {
270  head_ = tail_ = 0;
271  }else{
272  head_ = head_->right_;
273  head_->left_ = 0;
274  }
275  if (q) {
276  q->left_ = q->right_ = 0;
277  q->cnt_ = 0;
278  }
279 #if COLLECT_TQueue_STATISTICS
280  ++nfdeq;
281 #endif
282  return q;
283 }
285  Printf("FifoQ remove %p\n", q);
286  if (head_ == q) { head_ = q->right_; }
287  if (tail_ == q) { tail_ = q->left_; }
288  if (q->left_) { q->left_->right_ = q->right_; }
289  if (q->right_) { q->right_->left_ = q->left_; }
290  q->left_ = q->right_ = 0;
291  q->cnt_ = 0;
292 #if COLLECT_TQueue_STATISTICS
293  ++nfrem;
294 #endif
295 }
296 
298  return head_;
299 }
301  return q->right_;
302 }
TQItem * next(TQItem *)
Definition: sptfifoq.cpp:300
#define Printf
Definition: model.h:252
#define assert(ex)
Definition: hocassrt.h:26
SPBLK * spdeq(SPBLK **np)
Definition: sptree.h:320
void spdelete(SPBLK *n, SPTREE< SPBLK > *q)
Definition: sptree.h:772
void print()
Definition: bbtqueue.cpp:114
TQItem * find(double t)
Definition: bbtqueue.cpp:220
TQItem()
Definition: bbtqueue.cpp:3
virtual ~FifoQ()
Definition: sptfifoq.cpp:248
SPBLK * sphead(SPTREE< SPBLK > *q)
Definition: sptree.h:731
static void deleteitem(TQItem *i)
Definition: sptfifoq.cpp:32
double t_
Definition: bbtqueue.h:18
Definition: bbtqueue.h:6
void spinit(SPTREE< SPBLK > *q)
Definition: sptree.h:139
double least_t()
Definition: sptfifoq.cpp:252
bool check()
Definition: bbtqueue.cpp:30
void statistics()
Definition: bbtqueue.cpp:474
void forall_callback(void(*)(const TQItem *, int))
Definition: bbtqueue.cpp:120
virtual ~TQItem()
Definition: bbtqueue.cpp:9
void remove(TQItem *)
Definition: sptfifoq.cpp:284
void spike_stat(double *)
Definition: spt2queue.cpp:170
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
TQItem * dequeue()
Definition: sptfifoq.cpp:267
TQItem * insert(double t, void *data_)
Definition: bbtqueue.cpp:391
TQItem * first()
Definition: sptfifoq.cpp:297
#define nil
Definition: enter-scope.h:36
static void chk(TQItem *b, int level)
Definition: sptfifoq.cpp:51
TQItem * insert_fifo(double t, void *data_)
Definition: spt2queue.cpp:197
TQItem * left_
Definition: bbtqueue.h:19
Definition: sptbinq.h:17
static void prnt(const TQItem *b, int level)
Definition: sptfifoq.cpp:43
SPBLK * splookup(double key, SPTREE< SPBLK > *q)
Definition: sptree.h:975
void move_least(double tnew)
Definition: bbtqueue.cpp:181
void spscan(void(*f)(const SPBLK *, int), SPBLK *n, SPTREE< SPBLK > *q)
Definition: sptree.h:1102
static const char * errmess_
Definition: tqueue.cpp:20
void enqueue(TQItem *)
Definition: sptfifoq.cpp:256
TQItem * parent_
Definition: bbtqueue.h:21
virtual ~TQueue()
Definition: bbtqueue.cpp:107
#define i
Definition: md1redef.h:12
FifoQ()
Definition: sptfifoq.cpp:241
Definition: sptfifoq.h:29
#define STAT
Definition: model.h:117
static double least(void *v)
Definition: tqueue.cpp:33
SPBLK * spenq(SPBLK *n, SPTREE< SPBLK > *q)
Definition: sptree.h:176
void * data_
Definition: bbtqueue.h:17
void check(const char *errmess)
Definition: bbtqueue.cpp:126
void remove(TQItem *)
Definition: bbtqueue.cpp:239
double t
Definition: init.cpp:123
size_t q
int cnt_
Definition: spt2queue.h:23
TQueue()
Definition: bbtqueue.cpp:94
void move(TQItem *, double tnew)
Definition: bbtqueue.cpp:188
TQItem * right_
Definition: bbtqueue.h:20