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 
29 TQItem::~TQItem() {}
30 
31 static void deleteitem(TQItem* i) { // only one, semantics changed
32  assert(i);
33  tpool_->hpfree(i);
34 }
35 
36 bool TQItem::check() {
37 #if DOCHECK
38 #endif
39  return true;
40 }
41 
42 static void prnt(const TQItem* b, int level) {
43  int i;
44  for (i = 0; i < level; ++i) {
45  Printf(" ");
46  }
47  Printf("%g %c %d Q=%p D=%p\n", b->t_, b->data_ ? 'x' : 'o', b->cnt_, b, b->data_);
48 }
49 
50 static void chk(TQItem* b, int level) {
51  if (!b->check()) {
52  hoc_execerror("chk failed", errmess_);
53  }
54 }
55 
57  if (!tpool_) {
58  tpool_ = new TQItemPool(1000);
59  }
60  sptree_ = new SPTREE;
61  spinit(sptree_);
62  fifo_ = new FifoQ;
63  least_ = 0;
64 
65 #if COLLECT_TQueue_STATISTICS
66  nmove = ninsert = nrem = nleast = nbal = ncmplxrem = 0;
68 #endif
69 }
70 
72  TQItem* q;
73  while ((q = spdeq(&sptree_->root)) != nil) {
74  deleteitem(q);
75  }
76  delete sptree_;
77  while ((q = fifo_->dequeue()) != nil) {
78  deleteitem(q);
79  }
80  delete fifo_;
81 }
82 
83 void TQueue::print() {
84 #if FAST_LEAST
85  if (least_) {
86  prnt(least_, 0);
87  }
88 #endif
90  for (TQItem* q = fifo_->first(); q; q = fifo_->next(q)) {
91  prnt(q, 0);
92  }
93 }
94 
95 void TQueue::forall_callback(void (*f)(const TQItem*, int)) {
96 #if FAST_LEAST
97  if (least_) {
98  f(least_, 0);
99  }
100 #endif
101  spscan(f, nil, sptree_);
102  for (TQItem* q = fifo_->first(); q; q = fifo_->next(q)) {
103  f(q, 0);
104  }
105 }
106 
107 void TQueue::check(const char* mes) {}
108 
109 void TQueue::move_least(double tnew) {
110  TQItem* b = least();
111  if (b) {
112  b->t_ = tnew;
113  TQItem* nl = sphead(sptree_);
114  if (nl) {
115  if (tnew <= nl->t_ && tnew <= fifo_->least_t()) {
116  ;
117  } else if (nl->t_ <= fifo_->least_t()) {
118  least_ = spdeq(&sptree_->root);
119  spenq(b, sptree_);
120  } else {
121  least_ = fifo_->dequeue();
122  spenq(b, sptree_);
123  }
124  } else if (tnew > fifo_->least_t()) {
125  least_ = fifo_->dequeue();
126  spenq(b, sptree_);
127  }
128  }
129 }
130 
131 void TQueue::move(TQItem* i, double tnew) {
132  STAT(nmove)
133  if (i == least_) {
134  move_least(tnew);
135  } else if (tnew < least_->t_) {
136  spdelete(i, sptree_);
137  i->t_ = tnew;
138  spenq(least_, sptree_);
139  least_ = i;
140  } else {
141  spdelete(i, sptree_);
142  i->t_ = tnew;
143  spenq(i, sptree_);
144  }
145 }
146 
147 void TQueue::statistics() {
148 #if COLLECT_TQueue_STATISTICS
149  Printf("insertions=%lu moves=%lu removals=%lu calls to least=%lu\n",
150  ninsert,
151  nmove,
152  nrem,
153  nleast);
154  Printf("calls to find=%lu\n", nfind);
155  Printf("comparisons=%lu\n", sptree_->enqcmps);
156 #else
157  Printf("Turn on COLLECT_TQueue_STATISTICS_ in tqueue.h\n");
158 #endif
159 }
160 
161 void TQueue::spike_stat(double* d) {
162 #if COLLECT_TQueue_STATISTICS
163  d[0] = ninsert;
164  d[1] = nmove;
165  d[2] = nrem;
166 // printf("FifoQ spikestat nfenq=%lu nfdeq=%lu nfrem=%lu\n", fifo_->nfenq, fifo_->nfdeq,
167 // 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_) {
254  return head_->t_;
255  }
256  return 1e50; // must be larger than any possible t
257 }
259  if (tail_) {
260  assert(tail_->t_ <= q->t_);
261  }
262  q->cnt_ = -1;
263  q->left_ = tail_;
264  q->right_ = 0;
265  tail_ = q;
266  if (head_) {
267  tail_->left_->right_ = q;
268  } else {
269  head_ = tail_;
270  }
271 #if COLLECT_TQueue_STATISTICS
272  ++nfenq;
273 #endif
274 }
276  TQItem* q = head_;
277  if (head_ == tail_) {
278  head_ = tail_ = 0;
279  } else {
280  head_ = head_->right_;
281  head_->left_ = 0;
282  }
283  if (q) {
284  q->left_ = q->right_ = 0;
285  q->cnt_ = 0;
286  }
287 #if COLLECT_TQueue_STATISTICS
288  ++nfdeq;
289 #endif
290  return q;
291 }
293  Printf("FifoQ remove %p\n", q);
294  if (head_ == q) {
295  head_ = q->right_;
296  }
297  if (tail_ == q) {
298  tail_ = q->left_;
299  }
300  if (q->left_) {
301  q->left_->right_ = q->right_;
302  }
303  if (q->right_) {
304  q->right_->left_ = q->left_;
305  }
306  q->left_ = q->right_ = 0;
307  q->cnt_ = 0;
308 #if COLLECT_TQueue_STATISTICS
309  ++nfrem;
310 #endif
311 }
312 
314  return head_;
315 }
317  return q->right_;
318 }
#define nil
Definition: enter-scope.h:36
Definition: sptfifoq.h:30
void enqueue(TQItem *)
Definition: sptfifoq.cpp:258
int nfrem
Definition: sptfifoq.h:43
TQItem * head_
Definition: sptfifoq.h:46
TQItem * dequeue()
Definition: sptfifoq.cpp:275
FifoQ()
Definition: sptfifoq.cpp:241
int nfdeq
Definition: sptfifoq.h:43
virtual ~FifoQ()
Definition: sptfifoq.cpp:248
TQItem * tail_
Definition: sptfifoq.h:47
int nfenq
Definition: sptfifoq.h:43
TQItem * first()
Definition: sptfifoq.cpp:313
double least_t()
Definition: sptfifoq.cpp:252
TQItem * next(TQItem *)
Definition: sptfifoq.cpp:316
void remove(TQItem *)
Definition: sptfifoq.cpp:292
Definition: bbtqueue.h:6
virtual ~TQItem()
Definition: bbtqueue.cpp:9
double t_
Definition: bbtqueue.h:23
bool check()
Definition: bbtqueue.cpp:30
TQItem * right_
Definition: bbtqueue.h:25
int cnt_
Definition: spt2queue.h:24
TQItem()
Definition: bbtqueue.cpp:3
TQItem * parent_
Definition: bbtqueue.h:26
TQItem * left_
Definition: bbtqueue.h:24
void * data_
Definition: bbtqueue.h:22
unsigned long nbal
Definition: bbtqueue.h:58
void statistics()
Definition: bbtqueue.cpp:477
unsigned long nleastsrch
Definition: bbtqueue.h:59
void remove(TQItem *)
Definition: bbtqueue.cpp:236
double least_t()
Definition: bbtqueue.cpp:131
void deleteitem(TQItem *)
Definition: sptbinq.cpp:87
TQItem * least()
Definition: bbtqueue.cpp:140
void check(const char *errmess)
Definition: bbtqueue.cpp:121
TQItemPool * tpool_
Definition: sptbinq.h:153
void move(TQItem *, double tnew)
Definition: bbtqueue.cpp:185
unsigned long nmove
Definition: bbtqueue.h:59
TQItem * least_
Definition: bbtqueue.h:54
TQueue()
Definition: bbtqueue.cpp:90
TQItem * insert_fifo(double t, void *data_)
Definition: spt2queue.cpp:216
unsigned long ninsert
Definition: bbtqueue.h:58
void print()
Definition: bbtqueue.cpp:109
unsigned long nrem
Definition: bbtqueue.h:58
FifoQ * fifo_
Definition: sptfifoq.h:84
unsigned long nfastmove
Definition: bbtqueue.h:59
SPTREE * sptree_
Definition: spt2queue.h:61
TQItem * find(double t)
Definition: bbtqueue.cpp:217
unsigned long nfindsrch
Definition: bbtqueue.h:59
unsigned long ncompare
Definition: bbtqueue.h:59
unsigned long nleast
Definition: bbtqueue.h:58
unsigned long nfind
Definition: bbtqueue.h:59
unsigned long ncmplxrem
Definition: bbtqueue.h:58
virtual ~TQueue()
Definition: bbtqueue.cpp:103
void forall_callback(void(*)(const TQItem *, int))
Definition: bbtqueue.cpp:115
TQItem * insert(double t, void *data_)
Definition: bbtqueue.cpp:394
void move_least(double tnew)
Definition: bbtqueue.cpp:178
void spike_stat(double *)
Definition: spt2queue.cpp:189
double t
Definition: cvodeobj.cpp:59
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
#define assert(ex)
Definition: hocassrt.h:32
#define i
Definition: md1redef.h:12
#define STAT
Definition: model.h:117
#define Printf
Definition: model.h:237
size_t q
static void deleteitem(TQItem *i)
Definition: sptfifoq.cpp:31
static void prnt(const TQItem *b, int level)
Definition: sptfifoq.cpp:42
static void chk(TQItem *b, int level)
Definition: sptfifoq.cpp:50
void spscan(void(*f)(const SPBLK *, int), SPBLK *n, SPTREE< SPBLK > *q)
Definition: sptree.h:1035
SPBLK * spdeq(SPBLK **np)
Definition: sptree.h:304
SPBLK * sphead(SPTREE< SPBLK > *q)
Definition: sptree.h:693
SPBLK * spenq(SPBLK *n, SPTREE< SPBLK > *q)
Definition: sptree.h:169
SPBLK * splookup(double key, SPTREE< SPBLK > *q)
Definition: sptree.h:918
void spdelete(SPBLK *n, SPTREE< SPBLK > *q)
Definition: sptree.h:730
void spinit(SPTREE< SPBLK > *q)
Definition: sptree.h:136
Definition: sptree.h:40
int enqcmps
Definition: sptree.h:49
SPBLK * root
Definition: sptree.h:41
static const char * errmess_
Definition: tqueue.cpp:20