/*ident "@(#)cls4:lib/task/task/qhead.c 1.3" */ /******************************************************************************* C++ source for the C++ Language System, Release 3.0. This product is a new release of the original cfront developed in the computer science research center of AT&T Bell Laboratories. Copyright (c) 1993 UNIX System Laboratories, Inc. Copyright (c) 1991, 1992 AT&T and UNIX System Laboratories, Inc. Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System Laboratories, Inc. The copyright notice above does not evidence any actual or intended publication of such source code. *******************************************************************************/ #include /* a qhead's qh_queue has its pointer q_ptr pointing the last element of a circular list, so that q_ptr->o_next is the first element of that list. STRUCTURE: qhead <--> oqueue <--> qtail (qhead and qtail are independent) oqueue --> circular queue of objects "pen and paper is recommended when trying to understand the list manipulations." */ /* construct qhead <--> (possible)oqueue --> 0 */ qhead::qhead(qmodetype mode, int max) { if (0 < max) { qh_queue = new oqueue(max); qh_queue->q_head = this; }; qh_mode = mode; } /* destroy q if not pointed to by a qtail */ qhead::~qhead() { oqueue* q = qh_queue; if (q->q_tail) q->q_head = 0; else delete q; } /* remove and return object from head of q */ // q->q_ptr points to last object. last->o_next points to first object. // first->o_next points to the next object. object* qhead::get() { register oqueue* q = qh_queue; ll: if (q->q_count) { register object* oo = q->q_ptr; register object* p = oo->o_next; oo->o_next = p->o_next; p->o_next = 0; if (q->q_count-- == q->q_max) { qtail* t = q->q_tail; if (t) t->alert(); }; return p; } switch (qh_mode) { case WMODE: this_task()->sleep(this); goto ll; case EMODE: task_error(E_GETEMPTY, this); goto ll; case ZMODE: return 0; } } /* create a tail for this queue */ qtail* qhead::tail() { oqueue* q = qh_queue; register qtail* t = q->q_tail; if (t == 0) { t = new qtail(qh_mode,0); q->q_tail = t; t->qt_queue = q; } return t; } /* make room for a filter upstream from this qhead */ /* result: (this)qhead<-->newq (new)qhead<-->oldq ?<-->qtail? */ qhead* qhead::cut() { oqueue* oldq = qh_queue; qhead* h = new qhead(qh_mode,oldq->q_max); oqueue* newq = h->qh_queue; oldq->q_head = h; h->qh_queue = oldq; qh_queue = newq; newq->q_head = this; return h; } /* this qhead is supposed to be upstream to the qtail t add the contents of this's queue to t's queue destroy this, t, and this's queue alert the spliced qhead and qtail if a significant state change happened */ void qhead::splice(qtail* t) { oqueue* qt = t->qt_queue; oqueue* qh = qh_queue; int qtcount = qt->q_count; int qhcount = qh->q_count; int halert = (qtcount==0 && qhcount); /* becomes non-empty */ int talert = (qh->q_max <= qhcount && qhcount+qtcountq_max); /* becomes non-full */ if (qhcount) { object* ooh = qh->q_ptr; object* oot = qt->q_ptr; qt->q_ptr = ooh; if (qtcount) { /* add the contents of qh to qt */ object* tf = oot->o_next; // t's first object oot->o_next = ooh->o_next; ooh->o_next = tf; } qt->q_count = qhcount + qtcount; qh->q_count = 0; } (qh->q_tail)->qt_queue = qt; delete t; qt->q_tail = qh->q_tail; qh->q_tail = 0; delete this; if (halert) qt->q_head->alert(); if (talert) qt->q_tail->alert(); } /* insert new object at head of queue (after queue->q_ptr) */ int qhead::putback(object* p) { oqueue* q = qh_queue; if (p->o_next) task_error(E_BACKOBJ, this); ll: if (q->q_count++ < q->q_max) { if (q->q_count == 1) { q->q_ptr = p; p->o_next = p; } else { object* oo = q->q_ptr; p->o_next = oo->o_next; oo->o_next = p; } return 1; } switch (qh_mode) { case WMODE: case EMODE: task_error(E_BACKFULL, this); goto ll; case ZMODE: return 0; } } void qhead::print(int n, int baseClass) { if (!baseClass) printf("qhead "); oqueue* q = qh_queue; printf("mode=%d, max=%d, count=%d, tail=%d\n", qh_mode, q->q_max, q->q_count, q->q_tail); if (n&VERBOSE) { int m = n & ~(CHAIN|VERBOSE); if (q->q_tail) { printf("\ttail of queue:\n"); q->q_tail->print(m); } else printf("\tno tail\n"); q->print(m); } object::print(n, 1); } void oqueue::print(int n) { object* p = q_ptr; if (q_count == 0) return; printf("\tobject on queue:\n"); do { p->print(n); p = p->o_next; } while (p != q_ptr); printf("\n"); }