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