Make WvStreams compile with gcc 4.4.
[wvstreams.git] / include / wvsubprocqueue.h
blobc06f4835ec052bbb8422d7ebb68707970db99343
1 /* -*- Mode: C++ -*-
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * A class for running a series or set of processes, one at a time.
6 */
7 #ifndef __WVSUBPROCQUEUE_H
8 #define __WVSUBPROCQUEUE_H
10 #include "wvsubproc.h"
12 /**
13 * An ordered queue of WvSubProc instances.
15 * You can enqueue any number of subprocesses to run sequentially, with
16 * a specified maximum number of processes running at a time. The processes
17 * run in the order they are added to the queue, except that (of course)
18 * running more than one process at a time may cause processes to overlap
19 * in an undefined way.
21 * You can define "sync point" subprocesses using the "cookie" parameter to
22 * add(). A sync point is guaranteed to be started:
23 * - alone, not in parallel with anything else
24 * - at least once after you enqueue it
25 * - at least once after every already-enqueued process has finished
26 * - immediately after every already-enqueued process has finished, *unless*
27 * an earlier sync point is still waiting.
28 * - no more than twice after the final time it is enqueued.
30 * That sounds complicated, but it lets you easily implement a common
31 * type of "delayed event" queuing: "Some time after each of these
32 * things S, I need to run X, but I don't need to run it for *every*
33 * element of S, but I don't want it to wait forever because I keep adding
34 * to S."
36 * For example, imagine you have one type of operation, add() that
37 * creates a new file in a directory, and another type of operation
38 * that regenerates the directory index. You need to generate the
39 * index after any create operation before it will really be done,
40 * but there is no need to generate the index more than once when
41 * doing a lot of create operations. You could do a sequence like
42 * this:
44 * for (i = 0; i < 10; i++)
45 * { add_file(i); }
47 * Where "add" can trivially just do q.add(NULL, whatever1) and then
48 * q.add(&reindex_cookie, whatever2). WvSubProcQueue
49 * will ensure that "whatever2" runs as soon as possible (to prevent
50 * arbitrary delays because of nonstop add_file() calls) and also exactly
51 * once at the very end, but not every single time.
53 * In case it wasn't obvious, if you create more than one
54 * WvSubProcQueue, they operate totally independently of each other. That
55 * means if you have two queues with a max of 10 processes, you might have
56 * up to 20 processes running at a time.
58 class WvSubProcQueue
60 public:
61 /**
62 * Create a WvSubProcQueue. _maxrunning is the maximum number of
63 * processes to have running in parallel. 1 is usually a good choice.
65 WvSubProcQueue(unsigned _maxrunning);
67 virtual ~WvSubProcQueue();
69 /**
70 * Enqueue a process. If cookie is NULL, the process will simply
71 * be added at the end of the queue. If cookie is non-NULL, it will
72 * be treated as a "sync point" as described above.
74 * WARNING! Do not start_again() the proc before passing it to the
75 * WvSubProcQueue. This is done automatically in some WvSubProc
76 * constructors. Use WvSubProc::prepare() or preparev() instead.
78 void add(void *cookie, WvSubProc *proc);
80 /**
81 * Like add(cookie, proc) but you don't have to build the WvSubProc
82 * yourself for simple cases.
84 void add(void *cookie, const char *cmd, const char * const *argv);
86 /**
87 * Clean up after any running processes in the queue, and start running
88 * additional processes if any are waiting. Never blocks.
90 * Returns the number of new processes which were started on this run.
92 * WARNING: you must call this rather often in order to keep your
93 * queue moving.
95 int go();
97 /**
98 * Wait synchronously for all processes in the entire queue to finish.
99 * This might block forever!! You should probably only call it in
100 * test programs or if you really know what you're doing. Otherwise
101 * just call go() occasionally.
103 void finish();
105 /// Return the number of currently running processes.
106 unsigned running() const;
108 /// Return the number of unfinished (ie. running or waiting) processes.
109 unsigned remaining() const;
111 /// True if there are no unfinished (ie. running *or* waiting) processes.
112 bool isempty() const;
114 private:
115 struct Ent
117 Ent(void *_cookie, WvSubProc *_proc)
119 cookie = _cookie;
120 proc = _proc;
121 redo = false;
124 ~Ent()
126 if (proc) delete proc;
129 void *cookie;
130 WvSubProc *proc;
131 bool redo;
133 DeclareWvList(Ent);
135 unsigned maxrunning;
136 EntList runq, waitq;
138 bool cookie_running();
142 #endif // __WVSUBPROCQUEUE_H