Make WvStreams compile with gcc 4.4.
[wvstreams.git] / utils / wvsubprocqueue.cc
blob8d08496c545eacdb396d15981d99e0664327c8bb
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * A way to enqueue a series of WvSubProc objects. See wvsubprocqueue.h.
6 */
7 #include "wvsubprocqueue.h"
8 #include <unistd.h>
9 #include <assert.h>
12 WvSubProcQueue::WvSubProcQueue(unsigned _maxrunning)
14 maxrunning = _maxrunning;
18 WvSubProcQueue::~WvSubProcQueue()
23 void WvSubProcQueue::add(void *cookie, WvSubProc *proc)
25 assert(proc);
26 assert(!proc->running);
27 if (cookie)
29 // search for other enqueued objects with this cookie
30 EntList::Iter i(waitq);
31 for (i.rewind(); i.next(); )
33 if (i->cookie == cookie)
35 // already enqueued; mark it as "redo" unless it's already
36 // the last one. That way we guarantee it'll still run
37 // in the future from now, and it'll come later than anything
38 // else in the queue, but it won't pointlessly run twice at
39 // the end.
40 Ent *e = i.ptr();
41 if (i.next())
42 e->redo = true;
43 delete proc;
44 return;
49 waitq.append(new Ent(cookie, proc), true);
53 void WvSubProcQueue::add(void *cookie,
54 const char *cmd, const char * const *argv)
56 WvSubProc *p = new WvSubProc;
57 p->preparev(cmd, argv);
58 add(cookie, p);
62 bool WvSubProcQueue::cookie_running()
64 EntList::Iter i(runq);
65 for (i.rewind(); i.next(); )
66 if (i->cookie)
67 return true;
68 return false;
72 int WvSubProcQueue::go()
74 int started = 0;
76 //fprintf(stderr, "go: %d waiting, %d running\n",
77 // waitq.count(), runq.count());
79 // first we need to clean up any finished processes
81 EntList::Iter i(runq);
82 for (i.rewind(); i.next(); )
84 Ent *e = i.ptr();
86 e->proc->wait(0, true);
87 if (!e->proc->running)
89 if (e->redo)
91 // someone re-enqueued this task while it was
92 // waiting/running
93 e->redo = false;
94 i.xunlink(false);
95 waitq.append(e, true);
97 else
98 i.xunlink();
103 while (!waitq.isempty() && runq.count() < maxrunning)
105 EntList::Iter i(waitq);
106 for (i.rewind(); i.next(); )
108 // elements with cookies are "sync points" in the queue;
109 // they guarantee that everything before that point has
110 // finished running before they run, and don't let anything
111 // after them run until they've finished.
112 if (i->cookie && !runq.isempty())
113 goto out;
114 if (cookie_running())
115 goto out;
117 // jump it into the running queue, but be careful not to
118 // delete the object when removing!
119 Ent *e = i.ptr();
120 i.xunlink(false);
121 runq.append(e, true);
122 e->proc->start_again();
123 started++;
124 break;
128 out:
129 assert(runq.count() <= maxrunning);
130 return started;
134 unsigned WvSubProcQueue::running() const
136 return runq.count();
140 unsigned WvSubProcQueue::remaining() const
142 return runq.count() + waitq.count();
146 bool WvSubProcQueue::isempty() const
148 return runq.isempty() && waitq.isempty();
152 void WvSubProcQueue::finish()
154 while (!isempty())
156 go();
157 if (!isempty())
158 usleep(100*1000);