|
|
1.1 root 1: #include "task.h"
2:
3: /* a qhead's qh_queue has its pointer q_ptr pointing the last
4: element of a circular list, so that q_ptr->o_next is the
5: first element of that list.
6:
7: STRUCTURE:
8: qhead <--> oqueue <--> qtail (qhead and qtail are independent)
9: oqueue --> circular queue of objects
10:
11: "pen and paper is recommended when trying to understand
12: the list manipulations."
13: */
14:
15: /* construct qhead <--> (possible)oqueue --> 0 */
16: qhead::qhead(int mode, int max)
17: {
18: if (0 < max) {
19: qh_queue = new oqueue(max);
20: qh_queue->q_head = this;
21: };
22: qh_mode = mode;
23: }
24:
25:
26: /* destroy q if not pointed to by a qtail */
27: qhead::~qhead()
28: {
29: oqueue* q = qh_queue;
30:
31: if (q->q_tail)
32: q->q_head = 0;
33: else
34: delete q;
35:
36: }
37:
38:
39: /* remove and return object from head of q */
40: object*
41: qhead::get()
42: {
43: register oqueue* q = qh_queue;
44: ll:
45: if (q->q_count) {
46: register object* oo = q->q_ptr;
47: register object* p = oo->o_next;
48: oo->o_next = p->o_next;
49: p->o_next = 0;
50: if (q->q_count-- == q->q_max) {
51: qtail* t = q->q_tail;
52: if (t) t->alert();
53: };
54: return p;
55: }
56:
57: switch (qh_mode) {
58: case WMODE:
59: this_task()->sleep(this);
60: goto ll;
61: case EMODE:
62: task_error(E_GETEMPTY);
63: goto ll;
64: case ZMODE:
65: return 0;
66: }
67: }
68:
69: /* create a tail for this queue */
70: qtail*
71: qhead::tail()
72: {
73: oqueue* q = qh_queue;
74: register qtail* t = q->q_tail;
75:
76: if (t == 0) {
77: t = new qtail(qh_mode,0);
78: q->q_tail = t;
79: t->qt_queue = q;
80: }
81:
82: return t;
83: }
84:
85:
86: /* make room for a filter upstream from this qhead */
87: /* result: (this)qhead<-->newq (new)qhead<-->oldq ?<-->qtail? */
88: qhead*
89: qhead::cut()
90: {
91: oqueue* oldq = qh_queue;
92: qhead* h = new qhead(qh_mode,oldq->q_max);
93: oqueue* newq = h->qh_queue;
94:
95: oldq->q_head = h;
96: h->qh_queue = oldq;
97:
98: qh_queue = newq;
99: newq->q_head = this;
100:
101: return h;
102: }
103:
104:
105: /* this qhead is supposed to be upstream to the qtail t
106: add the contents of this's queue to t's queue
107: destroy this, t, and this's queue
108: alert the spliced qhead and qtail if a significant state change happened
109: */
110: void
111: qhead::splice(qtail* t)
112: {
113: oqueue* qt = t->qt_queue;
114: oqueue* qh = qh_queue;
115:
116: int qtcount = qt->q_count;
117: int qhcount = qh->q_count;
118: int halert = (qtcount==0 && qhcount); /* becomes non-empty */
119: int talert = (qh->q_max <= qhcount && qhcount+qtcount<qt->q_max);
120: /* becomes non-full */
121: if (qhcount) {
122: object* ooh = qh->q_ptr;
123: object* oot = qt->q_ptr;
124: qt->q_ptr = ooh;
125: if (qtcount) { /* add the contents of qh to qt */
126: object* tf = oot->o_next;
127: oot->o_next = ooh->o_next;
128: ooh->o_next = tf;
129: }
130: qt->q_count = qhcount + qtcount;
131: qh->q_count = 0;
132: }
133:
134: (qh->q_tail)->qt_queue = qt;
135: qt->q_tail = qh->q_tail;
136: qh->q_tail = 0;
137:
138: delete t;
139: delete this;
140:
141: if (halert) qt->q_head->alert();
142: if (talert) qt->q_tail->alert();
143: }
144:
145:
146: /* insert new object at head of queue (after queue->q_ptr) */
147: int
148: qhead::putback(object* p)
149: {
150: oqueue* q = qh_queue;
151:
152: if (p->o_next) task_error(E_BACKOBJ);
153: ll:
154: if (q->q_count++ < q->q_max) {
155: if (q->q_count == 1) {
156: q->q_ptr = p;
157: p->o_next = p;
158: }
159: else {
160: object* oo = q->q_ptr;
161: p->o_next = oo->o_next;
162: oo->o_next = p;
163: }
164: return 1;
165: }
166:
167: switch (qh_mode) {
168: case WMODE:
169: case EMODE:
170: task_error(E_BACKFULL);
171: goto ll;
172: case ZMODE:
173: return 0;
174: }
175: }
176:
177: int
178: qhead::pending()
179: {
180: return rdcount() == 0;
181: }
182:
183: void
184: qhead::print(int n, int baseClass)
185: {
186: if (!baseClass)
187: printf("qhead ");
188:
189: oqueue* q = qh_queue;
190:
191: printf("mode=%d, max=%d, count=%d, tail=%d\n",
192: qh_mode, q->q_max, q->q_count, q->q_tail);
193:
194: if (n&VERBOSE) {
195: int m = n & ~(CHAIN|VERBOSE);
196: if (q->q_tail) {
197: printf("\ttail of queue:\n");
198: q->q_tail->print(m);
199: } else printf("\tno tail\n");
200: q->print(m);
201: }
202:
203: object::print(n, 1);
204: }
205:
206:
207: void
208: oqueue::print(int n)
209: {
210: object* p = q_ptr;
211:
212: if (q_count == 0) return;
213:
214: printf("\tobjectects on queue:\n");
215:
216: do {
217: p->print(n);
218: p = p->o_next;
219: } while (p != q_ptr);
220:
221: printf("\n");
222: }
223:
224: int qhead::o_type()
225: {
226: return QHEAD;
227: }
228:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.