Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}