]>
Commit | Line | Data |
---|---|---|
282113ba | 1 | /* process.h |
56797078 | 2 | |
56797078 CV |
3 | Written by Robert Collins <rbtcollins@hotmail.com> |
4 | ||
5 | This file is part of Cygwin. | |
6 | ||
7 | This software is a copyrighted work licensed under the terms of the | |
8 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
9 | details. */ | |
10 | ||
282113ba CV |
11 | #ifndef _PROCESS_H |
12 | #define _PROCESS_H | |
56797078 CV |
13 | |
14 | #include <assert.h> | |
15 | ||
16 | #include "threaded_queue.h" | |
17 | ||
18 | class process_cleanup : public queue_request | |
19 | { | |
20 | public: | |
21 | process_cleanup (class process *const theprocess) | |
22 | : _process (theprocess) | |
23 | { | |
24 | assert (_process); | |
25 | } | |
26 | ||
27 | virtual ~process_cleanup (); | |
28 | ||
29 | virtual void process (); | |
30 | ||
31 | private: | |
32 | class process *const _process; | |
33 | }; | |
34 | ||
35 | class process; | |
36 | ||
37 | class cleanup_routine | |
38 | { | |
39 | friend class process; | |
40 | ||
41 | public: | |
42 | cleanup_routine (void *const key) | |
43 | : _key (key), | |
44 | _next (NULL) | |
45 | {} | |
46 | ||
8e701438 | 47 | virtual ~cleanup_routine () = 0; |
56797078 CV |
48 | |
49 | bool operator== (const cleanup_routine &rhs) const | |
50 | { | |
51 | return _key == rhs._key; | |
52 | } | |
53 | ||
54 | void *key () const { return _key; } | |
55 | ||
56 | /* MUST BE SYNCHRONOUS */ | |
57 | virtual void cleanup (class process *) = 0; | |
58 | ||
59 | private: | |
60 | void *const _key; | |
61 | cleanup_routine *_next; | |
62 | }; | |
63 | ||
64 | class process_cache; | |
65 | ||
1f8b3049 CV |
66 | #define hold() _hold(__FILE__,__LINE__) |
67 | #define release() _release(__FILE__,__LINE__) | |
68 | ||
56797078 CV |
69 | class process |
70 | { | |
71 | friend class process_cache; | |
72 | friend class process_cleanup; | |
73 | ||
74 | public: | |
8d8f4036 | 75 | process (pid_t cygpid, DWORD winpid); |
56797078 CV |
76 | ~process (); |
77 | ||
78 | pid_t cygpid () const { return _cygpid; } | |
79 | DWORD winpid () const { return _winpid; } | |
80 | HANDLE handle () const { return _hProcess; } | |
81 | ||
82 | bool is_active () const { return _exit_status == STILL_ACTIVE; } | |
83 | ||
1f8b3049 | 84 | void _hold (const char *file, int line) { |
663b4ab8 | 85 | _debug (file, line, "Try hold(%lu)", _cygpid); |
1f8b3049 | 86 | EnterCriticalSection (&_access); |
663b4ab8 | 87 | _debug (file, line, "holding (%lu)", _cygpid); |
1f8b3049 CV |
88 | } |
89 | void _release (const char *file, int line) { | |
663b4ab8 | 90 | _debug (file, line, "leaving (%lu)", _cygpid); |
1f8b3049 CV |
91 | LeaveCriticalSection (&_access); |
92 | } | |
56797078 CV |
93 | |
94 | bool add (cleanup_routine *); | |
95 | bool remove (const cleanup_routine *); | |
96 | ||
97 | private: | |
98 | const pid_t _cygpid; | |
99 | const DWORD _winpid; | |
100 | HANDLE _hProcess; | |
61522196 | 101 | LONG _cleaning_up; |
56797078 CV |
102 | DWORD _exit_status; // Set in the constructor and in exit_code (). |
103 | cleanup_routine *_routines_head; | |
104 | /* used to prevent races-on-delete */ | |
105 | CRITICAL_SECTION _access; | |
106 | class process *_next; | |
107 | ||
108 | DWORD check_exit_code (); | |
109 | void cleanup (); | |
110 | }; | |
111 | ||
112 | class process_cache | |
113 | { | |
114 | // Number of special (i.e., non-process) handles in _wait_array. | |
115 | // See wait_for_processes () and sync_wait_array () for details. | |
116 | enum { | |
117 | SPECIALS_COUNT = 2 | |
118 | }; | |
119 | ||
120 | class submission_loop : public queue_submission_loop | |
121 | { | |
122 | public: | |
123 | submission_loop (process_cache *const cache, threaded_queue *const queue) | |
124 | : queue_submission_loop (queue, true), | |
125 | _cache (cache) | |
126 | { | |
127 | assert (_cache); | |
128 | } | |
129 | ||
130 | private: | |
131 | process_cache *const _cache; | |
132 | ||
133 | virtual void request_loop (); | |
134 | }; | |
135 | ||
136 | friend class submission_loop; | |
137 | ||
138 | public: | |
2d015bd6 | 139 | process_cache (const size_t max_procs, const unsigned int initial_workers); |
56797078 CV |
140 | ~process_cache (); |
141 | ||
8d8f4036 | 142 | class process *process (pid_t cygpid, DWORD winpid); |
56797078 CV |
143 | |
144 | bool running () const { return _queue.running (); } | |
145 | ||
146 | bool start () { return _queue.start (); } | |
147 | bool stop () { return _queue.stop (); } | |
148 | ||
149 | private: | |
150 | threaded_queue _queue; | |
151 | submission_loop _submitter; | |
152 | ||
153 | size_t _processes_count; | |
2d015bd6 | 154 | size_t _max_process_count; |
56797078 CV |
155 | class process *_processes_head; // A list sorted by winpid. |
156 | ||
157 | // Access to the _wait_array and related fields is not thread-safe, | |
158 | // since they are used solely by wait_for_processes () and its callees. | |
159 | ||
2d015bd6 CV |
160 | HANDLE _wait_array[5 * MAXIMUM_WAIT_OBJECTS]; |
161 | class process *_process_array[5 * MAXIMUM_WAIT_OBJECTS]; | |
56797078 CV |
162 | |
163 | HANDLE _cache_add_trigger; // Actually both add and remove. | |
164 | CRITICAL_SECTION _cache_write_access; // Actually both read and write access. | |
165 | ||
166 | void wait_for_processes (HANDLE interrupt); | |
167 | size_t sync_wait_array (HANDLE interrupt); | |
168 | void check_and_remove_process (const size_t index); | |
169 | ||
170 | class process *find (DWORD winpid, class process **previous = NULL); | |
171 | }; | |
172 | ||
282113ba | 173 | #endif /* _PROCESS_H */ |