/src/graphicsmagick/magick/monitor.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2003-2026 GraphicsMagick Group |
3 | | % Copyright (C) 2002 ImageMagick Studio |
4 | | % Copyright 1991-1999 E. I. du Pont de Nemours and Company |
5 | | % SPDX-License-Identifier: MIT |
6 | | % |
7 | | % This program is covered by multiple licenses, which are described in |
8 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
9 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
10 | | % |
11 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
12 | | % % |
13 | | % % |
14 | | % % |
15 | | % M M OOO N N IIIII TTTTT OOO RRRR % |
16 | | % MM MM O O NN N I T O O R R % |
17 | | % M M M O O N N N I T O O RRRR % |
18 | | % M M O O N NN I T O O R R % |
19 | | % M M OOO N N IIIII T OOO R R % |
20 | | % % |
21 | | % % |
22 | | % GraphicsMagick Progress Monitor Methods % |
23 | | % % |
24 | | % % |
25 | | % Software Design % |
26 | | % John Cristy % |
27 | | % December 1995 % |
28 | | % % |
29 | | % % |
30 | | % % |
31 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
32 | | % |
33 | | % |
34 | | % |
35 | | */ |
36 | | |
37 | | /* |
38 | | Include declarations. |
39 | | */ |
40 | | #include "magick/studio.h" |
41 | | #include "magick/monitor.h" |
42 | | #include "magick/semaphore.h" |
43 | | #include "magick/utility.h" |
44 | | |
45 | | /* |
46 | | Global declarations. |
47 | | */ |
48 | | static MonitorHandler |
49 | | monitor_handler = (MonitorHandler) NULL; |
50 | | |
51 | | static SemaphoreInfo |
52 | | *monitor_semaphore = 0; |
53 | | |
54 | | /* |
55 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
56 | | % % |
57 | | % % |
58 | | % % |
59 | | + D e s t r o y M a g i c k M o n i t o r % |
60 | | % % |
61 | | % % |
62 | | % % |
63 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
64 | | % |
65 | | % DestroyMagickMonitor() destroys the monitor environment. |
66 | | % |
67 | | % The format of the DestroyMagickMonitor() method is: |
68 | | % |
69 | | % DestroyMagickMonitor(void) |
70 | | % |
71 | | % |
72 | | */ |
73 | | void |
74 | | DestroyMagickMonitor(void) |
75 | 0 | { |
76 | 0 | DestroySemaphoreInfo(&monitor_semaphore); |
77 | 0 | } |
78 | | |
79 | | /* |
80 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
81 | | % % |
82 | | % % |
83 | | % % |
84 | | + I n i t i a l i z e M a g i c k M o n i t o r % |
85 | | % % |
86 | | % % |
87 | | % % |
88 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
89 | | % |
90 | | % InitializeMagickMonitor() initializes the module loader. |
91 | | % |
92 | | % The format of the InitializeMagickMonitor() method is: |
93 | | % |
94 | | % MagickPassFail InitializeMagickMonitor(void) |
95 | | % |
96 | | % |
97 | | */ |
98 | | MagickPassFail |
99 | | InitializeMagickMonitor(void) |
100 | 254 | { |
101 | 254 | assert(monitor_semaphore == (SemaphoreInfo *) NULL); |
102 | 254 | monitor_semaphore=AllocateSemaphoreInfo(); |
103 | 254 | return MagickPass; |
104 | 254 | } |
105 | | |
106 | | /* |
107 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
108 | | % % |
109 | | % % |
110 | | % % |
111 | | % M a g i c k M o n i t o r % |
112 | | % % |
113 | | % % |
114 | | % % |
115 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
116 | | % |
117 | | % MagickMonitor() calls the monitor handler method with a text string that |
118 | | % describes the task and a measure of completion. The method returns True |
119 | | % on success otherwise False if an error is encountered, e.g. if there was a |
120 | | % user interrupt. |
121 | | % |
122 | | % This function is deprecated. Please use MagickMonitorFormatted() instead. |
123 | | % |
124 | | % The format of the MagickMonitor method is: |
125 | | % |
126 | | % MagickPassFail MagickMonitor(const char *text, |
127 | | % const magick_int64_t quantum,const magick_uint64_t span, |
128 | | % ExceptionInfo *exception) |
129 | | % |
130 | | % A description of each parameter follows: |
131 | | % |
132 | | % o text: Description of the task being performed. |
133 | | % |
134 | | % o quantum: The position relative to the span parameter which represents |
135 | | % how much progress has been made toward completing a task. |
136 | | % |
137 | | % o span: The span relative to completing a task. |
138 | | % |
139 | | % o exception: Return any errors or warnings in this structure. |
140 | | % |
141 | | */ |
142 | | MagickExport MagickPassFail |
143 | | MagickMonitor(const char *text, |
144 | | const magick_int64_t quantum, |
145 | | const magick_uint64_t span, |
146 | | ExceptionInfo *exception) |
147 | 0 | { |
148 | 0 | MagickPassFail |
149 | 0 | status = MagickPass; |
150 | |
|
151 | 0 | assert(text != (const char *) NULL); |
152 | 0 | ProcessPendingEvents(text); |
153 | 0 | if (monitor_handler != (MonitorHandler) NULL) |
154 | 0 | { |
155 | 0 | LockSemaphoreInfo(monitor_semaphore); |
156 | 0 | status=(*monitor_handler)(text,quantum,span,exception); |
157 | 0 | UnlockSemaphoreInfo(monitor_semaphore); |
158 | 0 | } |
159 | 0 | return(status); |
160 | 0 | } |
161 | | |
162 | | /* |
163 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
164 | | % % |
165 | | % % |
166 | | % % |
167 | | + M a g i c k M o n i t o r A c t i v e % |
168 | | % % |
169 | | % % |
170 | | % % |
171 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
172 | | % |
173 | | % MagickMonitorAtive() returns MagickTrue if a progress monitor callback |
174 | | % has been registered, or MagickFalse if no progress monitor is active. |
175 | | % |
176 | | % The format of the MagickMonitorActive method is: |
177 | | % |
178 | | % MagickBool MagickMonitor(void) |
179 | | % |
180 | | */ |
181 | | MagickExport MagickBool |
182 | | MagickMonitorActive(void) |
183 | 700k | { |
184 | 700k | return monitor_handler != (MonitorHandler) NULL ? MagickTrue : MagickFalse; |
185 | 700k | } |
186 | | |
187 | | /* |
188 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
189 | | % % |
190 | | % % |
191 | | % % |
192 | | % M a g i c k M o n i t o r F o r m a t t e d % |
193 | | % % |
194 | | % % |
195 | | % % |
196 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
197 | | % |
198 | | % MagickMonitorFormatted() calls the monitor handler method with a |
199 | | % printf type format specification and variable argument list. Also |
200 | | % passed are quantum and span values which provide a measure of |
201 | | % completion. The method returns MagickPass on success otherwise |
202 | | % MagickFail if an error is encountered, e.g. if there was a user |
203 | | % interrupt. If MagickFail is returned, the calling code is expected |
204 | | % to terminate whatever is being monitored as soon as possible. |
205 | | % |
206 | | % Most callers of this function will use the QuantumTick() macro to |
207 | | % decide when it should be called. The QuantumTick() macro is designed |
208 | | % to deliver no more than 100 events in a span (representing 1-100%) |
209 | | % and to distribute events as evenly as possible over the span so that |
210 | | % events are reported for every 1% of progress when possible. |
211 | | % |
212 | | % The format of the MagickMonitorFormatted method is: |
213 | | % |
214 | | % MagickPassFail MagickMonitorFormatted(const magick_int64_t quantum, |
215 | | % const magick_uint64_t span,ExceptionInfo *exception, |
216 | | % const char *format,...) |
217 | | % |
218 | | % A description of each parameter follows: |
219 | | % |
220 | | % o quantum: The position relative to the span parameter which represents |
221 | | % how much progress has been made toward completing a task. |
222 | | % |
223 | | % o span: The span relative to completing a task. |
224 | | % |
225 | | % o exception: Return any errors or warnings in this structure. |
226 | | % |
227 | | % o format: A string describing the format to use to write the remaining |
228 | | % arguments. |
229 | | % |
230 | | */ |
231 | | MagickExport MagickPassFail |
232 | | MagickMonitorFormatted(const magick_int64_t quantum, |
233 | | const magick_uint64_t span, |
234 | | ExceptionInfo *exception, |
235 | | const char *format,...) |
236 | 12.6M | { |
237 | 12.6M | MagickPassFail |
238 | 12.6M | status = MagickPass; |
239 | | |
240 | 12.6M | if (monitor_handler != (MonitorHandler) NULL) |
241 | 0 | { |
242 | 0 | va_list |
243 | 0 | operands; |
244 | |
|
245 | 0 | char |
246 | 0 | text[MaxTextExtent]; |
247 | |
|
248 | 0 | va_start(operands,format); |
249 | 0 | MagickFormatStringList(text,sizeof(text),format,operands); |
250 | 0 | va_end(operands); |
251 | | /* |
252 | | Serialize calls to the handler so that it will |
253 | | never be invoked by more than one thread at a time. |
254 | | |
255 | | When OpenMP is used, many different threads may invoke the |
256 | | handler, but the implementation of the handler might not be |
257 | | prepared for that. |
258 | | |
259 | | It is theoretically possible for events to be delivered out of |
260 | | order if the handler takes so much time to complete that |
261 | | another thread is already delivering an event. If the OS does |
262 | | not provide any lock ordering semantics (first come, first |
263 | | served) then behavior is indeterminate. FIXME: if the |
264 | | progress monitor is called by a thread while the lock is still |
265 | | held, maybe just cache the latest progress and deliver it once |
266 | | the monitor handler returns so the most recent progress is |
267 | | delivered. The current semaphore design does not provide "try |
268 | | lock" behavior. |
269 | | */ |
270 | 0 | LockSemaphoreInfo(monitor_semaphore); |
271 | 0 | status=(*monitor_handler)(text,quantum,span,exception); |
272 | 0 | UnlockSemaphoreInfo(monitor_semaphore); |
273 | 0 | } |
274 | 12.6M | return status; |
275 | 12.6M | } |
276 | | |
277 | | /* |
278 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
279 | | % % |
280 | | % % |
281 | | % % |
282 | | % S e t M o n i t o r H a n d l e r % |
283 | | % % |
284 | | % % |
285 | | % % |
286 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
287 | | % |
288 | | % SetMonitorHandler() sets the monitor handler to the specified method |
289 | | % and returns the previous monitor handler. |
290 | | % |
291 | | % The format of the SetMonitorHandler method is: |
292 | | % |
293 | | % MonitorHandler SetMonitorHandler(MonitorHandler handler) |
294 | | % |
295 | | % A description of each parameter follows: |
296 | | % |
297 | | % o handler: Specifies a pointer to a method to handle monitors. |
298 | | % |
299 | | % |
300 | | */ |
301 | | MagickExport MonitorHandler |
302 | | SetMonitorHandler(MonitorHandler handler) |
303 | 373k | { |
304 | 373k | MonitorHandler |
305 | 373k | previous_handler; |
306 | | |
307 | 373k | previous_handler=monitor_handler; |
308 | 373k | monitor_handler=handler; |
309 | 373k | return(previous_handler); |
310 | 373k | } |