NEURON
spt2queue.cpp
Go to the documentation of this file.
1 // splay tree + 2nd splay tree for event-sets or priority queues
2 // this starts from the sptqueue.cpp file and adds a 2ne splay tree
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 
23 #if 0
24 #define sp1enq(i) { i->cnt_ = 0; spenq(i, sptree_); }
25 #define sp2enq(i) { i->cnt_ = -1; spenq(i, sptree2_); }
26 #else
27 #define sp1enq(i) { i->cnt_ = 0; ++nenq1; spenq(i, sptree_); }
28 #define sp2enq(i) { i->cnt_ = -1; ++nenq2; spenq(i, sptree2_); }
29 #endif
30 
32  left_ = 0;
33  right_ = 0;
34  parent_ = 0;
35 }
36 
38 }
39 
40 static void deleteitem(TQItem* i) { // only one, semantics changed
41  assert(i);
42  tpool_->hpfree(i);
43 }
44 
45 bool TQItem::check() {
46 #if DOCHECK
47 #endif
48  return true;
49 }
50 
51 static void prnt(const TQItem* b, int level) {
52  int i;
53  for (i=0; i < level; ++i) {
54  Printf(" ");
55  }
56  Printf("%g %c %d Q=%p D=%p\n", b->t_, b->data_?'x':'o', b->cnt_, b, b->data_);
57 }
58 
59 static void chk(TQItem* b, int level) {
60  if (!b->check()) {
61  hoc_execerror("chk failed", errmess_);
62  }
63 }
64 
66  if (!tpool_) {
67  tpool_ = new TQItemPool(1000);
68  }
69  sptree_ = new SPTREE;
70  spinit(sptree_);
71  sptree2_ = new SPTREE;
72  spinit(sptree2_);
73  least_ = 0;
74 
75 #if COLLECT_TQueue_STATISTICS
76  nmove = ninsert = nrem = nleast = nbal = ncmplxrem = 0;
77  nfastmove = ncompare = nleastsrch = nfind = nfindsrch = 0;
78  nenq1 = nenq2 = 0;
79 #endif
80 }
81 
83  TQItem* q;
84  if (least_) { deleteitem(least_); }
85  while((q = spdeq(&sptree_->root)) != nil) {
86  deleteitem(q);
87  }
88  delete sptree_;
89  while((q = spdeq(&sptree2_->root)) != nil) {
90  deleteitem(q);
91  }
92  delete sptree2_;
93 }
94 
95 void TQueue::print() {
96 #if FAST_LEAST
97  if (least_) {
98  prnt(least_, 0);
99  }
100 #endif
101  spscan(prnt, nil, sptree_);
102  spscan(prnt, nil, sptree2_);
103 }
104 
105 void TQueue::forall_callback(void(*f)(const TQItem*, int)) {
106 #if FAST_LEAST
107  if (least_) {
108  f(least_, 0);
109  }
110 #endif
111  spscan(f, nil, sptree_);
112  spscan(f, nil, sptree2_);
113 }
114 
115 void TQueue::check(const char* mes) {
116 }
117 
118 void TQueue::move_least(double tnew) {
119  TQItem* b = least();
120  if (b) {
121  b->t_ = tnew;
122  TQItem* nl = sphead(sptree_);
123  if (nl) {
124  if (tnew <= nl->t_ && tnew <= q2least_t()) {
125  ;
126  }else if (nl->t_ <= q2least_t()) {
127  least_ = spdeq(&sptree_->root);
128  sp1enq(b);
129  }else{
130  least_ = spdeq(&sptree2_->root);
131  sp1enq(b);
132  }
133  }else if (tnew > q2least_t()) {
134  least_ = spdeq(&sptree2_->root);
135  sp1enq(b);
136  }
137  }
138 }
139 
140 void TQueue::move(TQItem* i, double tnew) {
141  STAT(nmove)
142  if (i == least_) {
143  move_least(tnew);
144  }else if (tnew < least_->t_) {
145  spdelete(i, sptree_);
146  i->t_ = tnew;
147  sp1enq(least_);
148  least_ = i;
149  }else{
150  spdelete(i, sptree_);
151  i->t_ = tnew;
152  sp1enq(i);
153  }
154 }
155 
156 void TQueue::statistics() {
157 #if COLLECT_TQueue_STATISTICS
158  Printf("insertions=%lu moves=%lu removals=%lu calls to least=%lu\n",
159  ninsert, nmove, nrem, nleast);
160  Printf("calls to find=%lu\n",
161  nfind);
162  Printf("comparisons=%lu\n",
163  sptree_->enqcmps);
164  Printf("neqn1=%lu nenq2=%lu\n", nenq1, nenq2);
165 #else
166  Printf("Turn on COLLECT_TQueue_STATISTICS_ in tqueue.h\n");
167 #endif
168 }
169 
170 void TQueue::spike_stat(double* d) {
171 #if COLLECT_TQueue_STATISTICS
172  d[0] = ninsert;
173  d[1] = nmove;
174  d[2] = nrem;
175  d[3] = nenq1;
176  d[4] = nenq2;
177 #endif
178 }
179 
180 TQItem* TQueue::insert(double t, void* d) {
181  STAT(ninsert);
182  TQItem* i = tpool_->alloc();
183  i->data_ = d;
184  i->t_ = t;
185  i->cnt_ = 0;
186  if (t < least_t()) {
187  if (least()) {
188  sp1enq(least());
189  }
190  least_ = i;
191  }else{
192  sp1enq(i);
193  }
194  return i;
195 }
196 
197 TQItem* TQueue::insert_fifo(double t, void* d) {
198  STAT(ninsert);
199  TQItem* i = tpool_->alloc();
200  i->data_ = d;
201  i->t_ = t;
202  i->cnt_ = 0;
203  if (t < least_t()) {
204  if (least()) {
205  sp1enq(least());
206  }
207  least_ = i;
208  }else{
209  sp2enq(i);
210  }
211  return i;
212 }
213 
214 void TQueue::remove(TQItem* q) {
215  STAT(nrem);
216  if (q) {
217  if (q == least_) {
218  if (sptree_->root) {
219  TQItem* nl = sphead(sptree_);
220  if (nl->t_ <= q2least_t()) {
221  least_ = spdeq(&sptree_->root);
222  }else{
223  least_ = spdeq(&sptree2_->root);
224  }
225  }else if (sptree2_->root){
226  least_ = spdeq(&sptree2_->root);
227  }else{
228  least_ = nil;
229  }
230  }else{
231  if (q->cnt_ == -1) {
232  spdelete(q, sptree2_);
233  }else{
234  spdelete(q, sptree_);
235  }
236  }
237  tpool_->hpfree(q);
238  }
239 }
240 
241 TQItem* TQueue::find(double t) {
242  // search only in the splay tree. if this is a bug then fix it.
243  STAT(nfind)
244  if (t == least_t()) {
245  return least();
246  }
247  TQItem* q;
248  q = splookup(t, sptree_);
249  return(q);
250 }
251 
253  if (sptree2_->root) { return sphead(sptree2_)->t_; }
254  return 1e50; // must be larger than any possible t
255 }
#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
static void deleteitem(TQItem *i)
Definition: spt2queue.cpp:40
#define sp1enq(i)
Definition: spt2queue.cpp:27
TQItem()
Definition: bbtqueue.cpp:3
SPBLK * sphead(SPTREE< SPBLK > *q)
Definition: sptree.h:731
double t_
Definition: bbtqueue.h:18
Definition: bbtqueue.h:6
void spinit(SPTREE< SPBLK > *q)
Definition: sptree.h:139
static void prnt(const TQItem *b, int level)
Definition: spt2queue.cpp:51
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 spike_stat(double *)
Definition: spt2queue.cpp:170
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
TQItem * insert(double t, void *data_)
Definition: bbtqueue.cpp:391
#define nil
Definition: enter-scope.h:36
static void chk(TQItem *b, int level)
Definition: spt2queue.cpp:59
double q2least_t()
Definition: spt2queue.cpp:252
TQItem * insert_fifo(double t, void *data_)
Definition: spt2queue.cpp:197
#define sp2enq(i)
Definition: spt2queue.cpp:28
TQItem * left_
Definition: bbtqueue.h:19
Definition: sptbinq.h:17
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
TQItem * parent_
Definition: bbtqueue.h:21
virtual ~TQueue()
Definition: bbtqueue.cpp:107
#define i
Definition: md1redef.h:12
#define STAT
Definition: model.h:117
static double least(void *v)
Definition: tqueue.cpp:33
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