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