Coverage Report

Created: 2025-07-23 06:38

/src/dng_sdk/source/dng_mutex.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2006-2008 Adobe Systems Incorporated
3
// All Rights Reserved.
4
//
5
// NOTICE:  Adobe permits you to use, modify, and distribute this file in
6
// accordance with the terms of the Adobe license agreement accompanying it.
7
/*****************************************************************************/
8
9
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_mutex.cpp#3 $ */ 
10
/* $DateTime: 2012/09/05 12:31:51 $ */
11
/* $Change: 847652 $ */
12
/* $Author: tknoll $ */
13
14
#include "dng_mutex.h"
15
16
#include "dng_assertions.h"
17
#include "dng_exceptions.h"
18
19
#include <stdlib.h>
20
21
/*****************************************************************************/
22
23
#if qDNGThreadSafe
24
25
namespace
26
  {
27
28
  class InnermostMutexHolder
29
    {
30
    
31
    private:
32
33
      pthread_key_t fInnermostMutexKey;
34
35
    public:
36
37
      InnermostMutexHolder ()
38
      
39
        : fInnermostMutexKey ()
40
        
41
10
        {
42
43
10
        int result = pthread_key_create (&fInnermostMutexKey, NULL);
44
45
10
        DNG_ASSERT (result == 0, "pthread_key_create failed.");
46
47
10
        if (result != 0)
48
0
          ThrowProgramError ();
49
50
10
        }
51
52
      ~InnermostMutexHolder ()
53
0
        {
54
        
55
0
        pthread_key_delete (fInnermostMutexKey);
56
        
57
0
        }
58
59
      void SetInnermostMutex (dng_mutex *mutex)
60
16.1M
        {
61
62
16.1M
        int result;
63
64
16.1M
        result = pthread_setspecific (fInnermostMutexKey, (void *)mutex);
65
66
16.1M
        DNG_ASSERT (result == 0, "pthread_setspecific failed.");
67
68
        #if 0   // Hard failure here was causing crash on quit.
69
        
70
        if (result != 0)
71
          ThrowProgramError ();
72
          
73
        #endif
74
75
16.1M
        }
76
77
      dng_mutex *GetInnermostMutex ()
78
8.08M
        {
79
80
8.08M
        void *result = pthread_getspecific (fInnermostMutexKey);
81
82
8.08M
        return reinterpret_cast<dng_mutex *> (result);
83
84
8.08M
        }
85
86
    };
87
88
  InnermostMutexHolder gInnermostMutexHolder;
89
  
90
  }
91
92
#endif
93
94
/*****************************************************************************/
95
96
dng_mutex::dng_mutex (const char *mutexName, uint32 mutexLevel)
97
98
  #if qDNGThreadSafe
99
  
100
19.7k
  : fPthreadMutex   ()
101
19.7k
  , fMutexLevel     (mutexLevel)
102
19.7k
  , fRecursiveLockCount (0)
103
  , fPrevHeldMutex    (NULL)
104
19.7k
  , fMutexName      (mutexName)
105
  
106
  #endif
107
  
108
19.7k
  {
109
  
110
19.7k
  #if qDNGThreadSafe
111
112
19.7k
  if (pthread_mutex_init (&fPthreadMutex, NULL) != 0)
113
0
    {
114
0
    ThrowMemoryFull ();
115
0
    }
116
  
117
19.7k
  #endif
118
  
119
19.7k
  }
120
121
/*****************************************************************************/
122
123
dng_mutex::~dng_mutex ()
124
19.7k
  {
125
  
126
19.7k
  #if qDNGThreadSafe
127
128
19.7k
  pthread_mutex_destroy (&fPthreadMutex);
129
130
19.7k
  #endif
131
  
132
19.7k
  }
133
134
/*****************************************************************************/
135
136
void dng_mutex::Lock ()
137
8.08M
  {
138
  
139
8.08M
  #if qDNGThreadSafe
140
141
8.08M
  dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
142
143
8.08M
  if (innermostMutex != NULL)
144
0
    {
145
146
0
    if (innermostMutex == this)
147
0
      {
148
149
0
      fRecursiveLockCount++;
150
151
0
      return;
152
153
0
      }
154
155
0
    bool lockOrderPreserved = fMutexLevel > innermostMutex->fMutexLevel /* ||
156
0
                  (fMutexLevel == innermostMutex->fMutexLevel && innermostMutex < this) */;
157
158
0
    if (!lockOrderPreserved)
159
0
      {
160
      
161
0
      DNG_REPORT ("Lock ordering violation.");
162
      
163
      #if qDNGDebug
164
      
165
      dng_show_message_f ("This mutex: %s v Innermost mutex: %s",
166
                this->MutexName (),
167
                innermostMutex->MutexName ());
168
      
169
      #endif
170
171
0
      }
172
173
0
    }
174
175
8.08M
  pthread_mutex_lock (&fPthreadMutex);
176
177
8.08M
  fPrevHeldMutex = innermostMutex;
178
179
8.08M
  gInnermostMutexHolder.SetInnermostMutex (this);
180
181
8.08M
  #endif
182
  
183
8.08M
  }
184
185
/*****************************************************************************/
186
187
void dng_mutex::Unlock ()
188
8.08M
  {
189
  
190
8.08M
  #if qDNGThreadSafe
191
  
192
8.08M
  DNG_ASSERT (gInnermostMutexHolder.GetInnermostMutex () == this, "Mutexes unlocked out of order!!!");
193
194
8.08M
  if (fRecursiveLockCount > 0)
195
0
    {
196
197
0
    fRecursiveLockCount--;
198
199
0
    return;
200
201
0
    }
202
203
8.08M
  gInnermostMutexHolder.SetInnermostMutex (fPrevHeldMutex);
204
205
8.08M
  fPrevHeldMutex = NULL;
206
207
8.08M
  pthread_mutex_unlock (&fPthreadMutex);
208
  
209
8.08M
  #endif
210
  
211
8.08M
  }
212
213
/*****************************************************************************/
214
215
const char *dng_mutex::MutexName () const
216
0
  {
217
  
218
0
  #if qDNGThreadSafe
219
  
220
0
  if (fMutexName)
221
0
    return fMutexName;
222
  
223
0
  #endif
224
  
225
0
  return "< unknown >";
226
  
227
0
  }
228
229
/*****************************************************************************/
230
231
dng_lock_mutex::dng_lock_mutex (dng_mutex *mutex)
232
233
8.08M
  : fMutex (mutex)
234
  
235
8.08M
  {
236
  
237
8.08M
  if (fMutex)
238
8.08M
    fMutex->Lock ();
239
    
240
8.08M
  }
241
242
/*****************************************************************************/
243
244
dng_lock_mutex::~dng_lock_mutex ()
245
8.08M
  {
246
  
247
8.08M
  if (fMutex)
248
8.08M
    fMutex->Unlock ();
249
    
250
8.08M
  }
251
252
/*****************************************************************************/
253
254
dng_unlock_mutex::dng_unlock_mutex (dng_mutex *mutex)
255
256
0
  : fMutex (mutex)
257
  
258
0
  {
259
  
260
0
  if (fMutex)
261
0
    fMutex->Unlock ();
262
    
263
0
  }
264
265
/*****************************************************************************/
266
267
dng_unlock_mutex::~dng_unlock_mutex ()
268
0
  {
269
  
270
0
  if (fMutex)
271
0
    fMutex->Lock ();
272
    
273
0
  }
274
275
/*****************************************************************************/
276
277
#if qDNGThreadSafe
278
279
/*****************************************************************************/
280
281
dng_condition::dng_condition ()
282
283
10
  : fPthreadCondition ()
284
285
10
  {
286
287
10
  int result;
288
289
10
  result = pthread_cond_init (&fPthreadCondition, NULL);
290
291
10
  DNG_ASSERT (result == 0, "pthread_cond_init failed.");
292
293
10
  if (result != 0)
294
0
    {
295
0
    ThrowProgramError ();
296
0
    }
297
298
10
  }
299
300
/*****************************************************************************/
301
302
dng_condition::~dng_condition ()
303
0
  {
304
  
305
0
  pthread_cond_destroy (&fPthreadCondition);
306
  
307
0
  }
308
309
/*****************************************************************************/
310
311
bool dng_condition::Wait (dng_mutex &mutex, double timeoutSecs)
312
0
  {
313
314
0
  bool timedOut = false;
315
316
0
  dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
317
318
0
  DNG_ASSERT (innermostMutex == &mutex, "Attempt to wait on non-innermost mutex.");
319
320
0
  innermostMutex = mutex.fPrevHeldMutex;
321
322
0
  gInnermostMutexHolder.SetInnermostMutex (innermostMutex);
323
324
0
  mutex.fPrevHeldMutex = NULL;
325
326
0
  if (timeoutSecs < 0)
327
0
    {
328
    
329
0
    pthread_cond_wait (&fPthreadCondition, &mutex.fPthreadMutex);
330
    
331
0
    }
332
    
333
0
  else
334
0
    {
335
    
336
0
    struct timespec now;
337
338
0
    dng_pthread_now (&now);
339
340
0
    timeoutSecs += now.tv_sec;
341
0
    timeoutSecs += now.tv_nsec / 1000000000.0;
342
343
0
    now.tv_sec  = (long) timeoutSecs;
344
0
    now.tv_nsec = (long) ((timeoutSecs - now.tv_sec) * 1000000000);
345
346
0
    timedOut = (pthread_cond_timedwait (&fPthreadCondition, &mutex.fPthreadMutex, &now) == ETIMEDOUT);
347
    
348
0
    }
349
350
0
  mutex.fPrevHeldMutex = innermostMutex;
351
352
0
  gInnermostMutexHolder.SetInnermostMutex (&mutex);
353
354
0
  return !timedOut;
355
356
0
  }
357
358
/*****************************************************************************/
359
360
void dng_condition::Signal ()
361
0
  {
362
363
0
  int result;
364
365
0
  result = pthread_cond_signal (&fPthreadCondition);
366
367
0
  DNG_ASSERT (result == 0, "pthread_cond_signal failed.");
368
369
0
  if (result != 0)
370
0
    ThrowProgramError ();
371
372
0
  }
373
374
/*****************************************************************************/
375
376
void dng_condition::Broadcast ()
377
0
  {
378
379
0
  int result;
380
381
0
  result = pthread_cond_broadcast (&fPthreadCondition);
382
383
0
  DNG_ASSERT (result == 0, "pthread_cond_broadcast failed.");
384
385
0
  if (result != 0)
386
0
    ThrowProgramError ();
387
388
0
  }
389
390
/*****************************************************************************/
391
392
#endif // qDNGThreadSafe
393
394
/*****************************************************************************/