Coverage Report

Created: 2026-03-08 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/x265/source/common/threading.h
Line
Count
Source
1
/*****************************************************************************
2
 * Copyright (C) 2013-2020 MulticoreWare, Inc
3
 *
4
 * Authors: Steve Borho <steve@borho.org>
5
 *          Min Chen <chenm003@163.com>
6
            liwei <liwei@multicorewareinc.com>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
21
 *
22
 * This program is also available under a commercial proprietary license.
23
 * For more information, contact us at license @ x265.com
24
 *****************************************************************************/
25
26
#ifndef X265_THREADING_H
27
#define X265_THREADING_H
28
29
#include "common.h"
30
#include "x265.h"
31
32
#ifdef _WIN32
33
#include <windows.h>
34
#include "winxp.h"  // XP workarounds for CONDITION_VARIABLE and ATOMIC_OR
35
#else
36
#include <pthread.h>
37
#include <semaphore.h>
38
#include <errno.h>
39
#include <fcntl.h>
40
#endif
41
42
#if MACOS
43
#include <sys/param.h>
44
#include <sys/sysctl.h>
45
#endif
46
47
#if NO_ATOMICS
48
49
#include <sys/time.h>
50
#include <unistd.h>
51
52
namespace X265_NS {
53
// x265 private namespace
54
int no_atomic_or(int* ptr, int mask);
55
int no_atomic_and(int* ptr, int mask);
56
int no_atomic_inc(int* ptr);
57
int no_atomic_dec(int* ptr);
58
int no_atomic_add(int* ptr, int val);
59
int64_t no_atomic_add64(int64_t* ptr, int64_t val);
60
}
61
62
#define BSR(id, x)            (id) = ((unsigned long)__builtin_clz(x) ^ 31)
63
#define BSF(id, x)            (id) = ((unsigned long)__builtin_ctz(x))
64
#define BSR64(id, x)          (id) = ((unsigned long)__builtin_clzll(x) ^ 63)
65
#define BSF64(id, x)          (id) = ((unsigned long)__builtin_ctzll(x))
66
#define ATOMIC_OR(ptr, mask)  no_atomic_or((int*)ptr, mask)
67
#define ATOMIC_AND(ptr, mask) no_atomic_and((int*)ptr, mask)
68
#define ATOMIC_INC(ptr)       no_atomic_inc((int*)ptr)
69
#define ATOMIC_DEC(ptr)       no_atomic_dec((int*)ptr)
70
#define ATOMIC_ADD(ptr, val)  (sizeof(*(ptr)) == 8 ? \
71
                               no_atomic_add64((int64_t*)ptr, (int64_t)(val)) : \
72
                               no_atomic_add((int*)ptr, (int)(val)))
73
#define GIVE_UP_TIME()        usleep(0)
74
75
#elif __GNUC__               /* GCCs builtin atomics */
76
77
#include <sys/time.h>
78
#include <unistd.h>
79
80
2.28M
#define BSR(id, x)            (id) = ((unsigned long)__builtin_clz(x) ^ 31)
81
166k
#define BSF(id, x)            (id) = ((unsigned long)__builtin_ctz(x))
82
#define BSR64(id, x)          (id) = ((unsigned long)__builtin_clzll(x) ^ 63)
83
#define BSF64(id, x)          (id) = ((unsigned long)__builtin_ctzll(x))
84
12.1k
#define ATOMIC_OR(ptr, mask)  __sync_fetch_and_or(ptr, mask)
85
6.42k
#define ATOMIC_AND(ptr, mask) __sync_fetch_and_and(ptr, mask)
86
28.0k
#define ATOMIC_INC(ptr)       __sync_add_and_fetch((volatile int32_t*)ptr, 1)
87
7.07k
#define ATOMIC_DEC(ptr)       __sync_add_and_fetch((volatile int32_t*)ptr, -1)
88
13.7k
#define ATOMIC_ADD(ptr, val)  __sync_fetch_and_add((volatile __typeof__(*(ptr))*)ptr, (__typeof__(*(ptr) + 0))(val))
89
0
#define GIVE_UP_TIME()        usleep(0)
90
91
#elif defined(_MSC_VER)       /* Windows atomic intrinsics */
92
93
#include <intrin.h>
94
95
#define BSR(id, x)            _BitScanReverse(&id, x)
96
#define BSF(id, x)            _BitScanForward(&id, x)
97
#define BSR64(id, x)          _BitScanReverse64(&id, x)
98
#define BSF64(id, x)          _BitScanForward64(&id, x)
99
#define ATOMIC_INC(ptr)       InterlockedIncrement((volatile LONG*)ptr)
100
#define ATOMIC_DEC(ptr)       InterlockedDecrement((volatile LONG*)ptr)
101
#define ATOMIC_ADD(ptr, val)  (sizeof(*(ptr)) == 8 ? \
102
                               InterlockedExchangeAdd64((volatile LONGLONG*)ptr, (LONGLONG)(val)) : \
103
                               InterlockedExchangeAdd((volatile LONG*)ptr, (LONG)(val)))
104
#define ATOMIC_OR(ptr, mask)  _InterlockedOr((volatile LONG*)ptr, (LONG)mask)
105
#define ATOMIC_AND(ptr, mask) _InterlockedAnd((volatile LONG*)ptr, (LONG)mask)
106
#define GIVE_UP_TIME()        Sleep(0)
107
108
#endif // ifdef __GNUC__
109
110
namespace X265_NS {
111
// x265 private namespace
112
113
#ifdef _WIN32
114
115
typedef HANDLE ThreadHandle;
116
117
class Lock
118
{
119
public:
120
121
    Lock()
122
    {
123
        InitializeCriticalSection(&this->handle);
124
    }
125
126
    ~Lock()
127
    {
128
        DeleteCriticalSection(&this->handle);
129
    }
130
131
    void acquire()
132
    {
133
        EnterCriticalSection(&this->handle);
134
    }
135
136
    void release()
137
    {
138
        LeaveCriticalSection(&this->handle);
139
    }
140
141
protected:
142
143
    CRITICAL_SECTION handle;
144
};
145
146
class Event
147
{
148
public:
149
150
    Event()
151
    {
152
        this->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
153
    }
154
155
    ~Event()
156
    {
157
        CloseHandle(this->handle);
158
    }
159
160
    void wait()
161
    {
162
        WaitForSingleObject(this->handle, INFINITE);
163
    }
164
165
    bool timedWait(uint32_t milliseconds)
166
    {
167
        /* returns true if the wait timed out */
168
        return WaitForSingleObject(this->handle, milliseconds) == WAIT_TIMEOUT;
169
    }
170
171
    void trigger()
172
    {
173
        SetEvent(this->handle);
174
    }
175
176
protected:
177
178
    HANDLE handle;
179
};
180
181
/* This class is intended for use in signaling state changes safely between CPU
182
 * cores. One thread should be a writer and multiple threads may be readers. The
183
 * mutex's main purpose is to serve as a memory fence to ensure writes made by
184
 * the writer thread are visible prior to readers seeing the m_val change. Its
185
 * secondary purpose is for use with the condition variable for blocking waits */
186
class ThreadSafeInteger
187
{
188
public:
189
190
    ThreadSafeInteger()
191
    {
192
        m_val = 0;
193
        InitializeCriticalSection(&m_cs);
194
        InitializeConditionVariable(&m_cv);
195
    }
196
197
    ~ThreadSafeInteger()
198
    {
199
        DeleteCriticalSection(&m_cs);
200
        XP_CONDITION_VAR_FREE(&m_cv);
201
    }
202
203
    int waitForChange(int prev)
204
    {
205
        EnterCriticalSection(&m_cs);
206
        if (m_val == prev)
207
            SleepConditionVariableCS(&m_cv, &m_cs, INFINITE);
208
        LeaveCriticalSection(&m_cs);
209
        return m_val;
210
    }
211
212
    int get()
213
    {
214
        EnterCriticalSection(&m_cs);
215
        int ret = m_val;
216
        LeaveCriticalSection(&m_cs);
217
        return ret;
218
    }
219
220
    int getIncr(int n = 1)
221
    {
222
        EnterCriticalSection(&m_cs);
223
        int ret = m_val;
224
        m_val += n;
225
        LeaveCriticalSection(&m_cs);
226
        return ret;
227
    }
228
229
    void set(int newval)
230
    {
231
        EnterCriticalSection(&m_cs);
232
        m_val = newval;
233
        WakeAllConditionVariable(&m_cv);
234
        LeaveCriticalSection(&m_cs);
235
    }
236
237
    void poke(void)
238
    {
239
        /* awaken all waiting threads, but make no change */
240
        EnterCriticalSection(&m_cs);
241
        WakeAllConditionVariable(&m_cv);
242
        LeaveCriticalSection(&m_cs);
243
    }
244
245
    void incr()
246
    {
247
        EnterCriticalSection(&m_cs);
248
        m_val++;
249
        WakeAllConditionVariable(&m_cv);
250
        LeaveCriticalSection(&m_cs);
251
    }
252
253
    void decr()
254
    {
255
        EnterCriticalSection(&m_cs);
256
        m_val--;
257
        WakeAllConditionVariable(&m_cv);
258
        LeaveCriticalSection(&m_cs);
259
    }
260
261
protected:
262
263
    CRITICAL_SECTION   m_cs;
264
    CONDITION_VARIABLE m_cv;
265
    int                m_val;
266
};
267
268
class NamedSemaphore
269
{
270
public:
271
    NamedSemaphore() : m_sem(NULL)
272
    {
273
    }
274
275
    ~NamedSemaphore()
276
    {
277
    }
278
279
    bool create(const char* name, const int initcnt, const int maxcnt)
280
    {
281
        if(!m_sem)
282
        {
283
            m_sem = CreateSemaphoreA(NULL, initcnt, maxcnt, name);
284
        }
285
        return m_sem != NULL;
286
    }
287
288
    bool give(const int32_t cnt)
289
    {
290
        return ReleaseSemaphore(m_sem, (LONG)cnt, NULL) != FALSE;
291
    }
292
293
    bool take(const uint32_t time_out = INFINITE)
294
    {
295
        int32_t rt = WaitForSingleObject(m_sem, time_out);
296
        return rt != WAIT_TIMEOUT && rt != WAIT_FAILED;
297
    }
298
299
    void release()
300
    {
301
        CloseHandle(m_sem);
302
        m_sem = NULL;
303
    }
304
305
private:
306
    HANDLE m_sem;
307
};
308
309
#else /* POSIX / pthreads */
310
311
typedef pthread_t ThreadHandle;
312
313
class Lock
314
{
315
public:
316
317
    Lock()
318
90.3k
    {
319
90.3k
        pthread_mutex_init(&this->handle, NULL);
320
90.3k
    }
321
322
    ~Lock()
323
90.3k
    {
324
90.3k
        pthread_mutex_destroy(&this->handle);
325
90.3k
    }
326
327
    void acquire()
328
200k
    {
329
200k
        pthread_mutex_lock(&this->handle);
330
200k
    }
331
332
    void release()
333
200k
    {
334
200k
        pthread_mutex_unlock(&this->handle);
335
200k
    }
336
337
protected:
338
339
    pthread_mutex_t handle;
340
};
341
342
class Event
343
{
344
public:
345
346
    Event()
347
31.5k
    {
348
31.5k
        m_counter = 0;
349
31.5k
        if (pthread_mutex_init(&m_mutex, NULL) ||
350
31.5k
            pthread_cond_init(&m_cond, NULL))
351
0
        {
352
0
            x265_log(NULL, X265_LOG_ERROR, "fatal: unable to initialize conditional variable\n");
353
0
        }
354
31.5k
    }
355
356
    ~Event()
357
31.5k
    {
358
31.5k
        pthread_cond_destroy(&m_cond);
359
31.5k
        pthread_mutex_destroy(&m_mutex);
360
31.5k
    }
361
362
    void wait()
363
37.9k
    {
364
37.9k
        pthread_mutex_lock(&m_mutex);
365
366
        /* blocking wait on conditional variable, mutex is atomically released
367
         * while blocked. When condition is signaled, mutex is re-acquired */
368
75.8k
        while (!m_counter)
369
37.9k
            pthread_cond_wait(&m_cond, &m_mutex);
370
371
37.9k
        m_counter--;
372
37.9k
        pthread_mutex_unlock(&m_mutex);
373
37.9k
    }
374
375
    bool timedWait(uint32_t waitms)
376
531
    {
377
531
        bool bTimedOut = false;
378
379
531
        pthread_mutex_lock(&m_mutex);
380
531
        if (!m_counter)
381
531
        {
382
531
            struct timeval tv;
383
531
            struct timespec ts;
384
531
            gettimeofday(&tv, NULL);
385
            /* convert current time from (sec, usec) to (sec, nsec) */
386
531
            ts.tv_sec = tv.tv_sec;
387
531
            ts.tv_nsec = tv.tv_usec * 1000;
388
389
531
            ts.tv_nsec += 1000 * 1000 * (waitms % 1000);    /* add ms to tv_nsec */
390
531
            ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000); /* overflow tv_nsec */
391
531
            ts.tv_nsec %= (1000 * 1000 * 1000);             /* clamp tv_nsec */
392
531
            ts.tv_sec += waitms / 1000;                     /* add seconds */
393
394
            /* blocking wait on conditional variable, mutex is atomically released
395
             * while blocked. When condition is signaled, mutex is re-acquired.
396
             * ts is absolute time to stop waiting */
397
531
            bTimedOut = pthread_cond_timedwait(&m_cond, &m_mutex, &ts) == ETIMEDOUT;
398
531
        }
399
531
        if (m_counter > 0)
400
531
        {
401
531
            m_counter--;
402
531
            bTimedOut = false;
403
531
        }
404
531
        pthread_mutex_unlock(&m_mutex);
405
531
        return bTimedOut;
406
531
    }
407
408
    void trigger()
409
38.6k
    {
410
38.6k
        pthread_mutex_lock(&m_mutex);
411
38.6k
        if (m_counter < UINT_MAX)
412
38.6k
            m_counter++;
413
        /* Signal a single blocking thread */
414
38.6k
        pthread_cond_signal(&m_cond);
415
38.6k
        pthread_mutex_unlock(&m_mutex);
416
38.6k
    }
417
418
protected:
419
420
    pthread_mutex_t m_mutex;
421
    pthread_cond_t  m_cond;
422
    uint32_t        m_counter;
423
};
424
425
/* This class is intended for use in signaling state changes safely between CPU
426
 * cores. One thread should be a writer and multiple threads may be readers. The
427
 * mutex's main purpose is to serve as a memory fence to ensure writes made by
428
 * the writer thread are visible prior to readers seeing the m_val change. Its
429
 * secondary purpose is for use with the condition variable for blocking waits */
430
class ThreadSafeInteger
431
{
432
public:
433
434
    ThreadSafeInteger()
435
70.8k
    {
436
70.8k
        m_val = 0;
437
70.8k
        if (pthread_mutex_init(&m_mutex, NULL) ||
438
70.8k
            pthread_cond_init(&m_cond, NULL))
439
0
        {
440
0
            x265_log(NULL, X265_LOG_ERROR, "fatal: unable to initialize conditional variable\n");
441
0
        }
442
70.8k
    }
443
444
    ~ThreadSafeInteger()
445
70.8k
    {
446
70.8k
        pthread_cond_destroy(&m_cond);
447
70.8k
        pthread_mutex_destroy(&m_mutex);
448
70.8k
    }
449
450
    int waitForChange(int prev)
451
0
    {
452
0
        pthread_mutex_lock(&m_mutex);
453
0
        if (m_val == prev)
454
0
            pthread_cond_wait(&m_cond, &m_mutex);
455
0
        pthread_mutex_unlock(&m_mutex);
456
0
        return m_val;
457
0
    }
458
459
    int get()
460
48.8k
    {
461
48.8k
        pthread_mutex_lock(&m_mutex);
462
48.8k
        int ret = m_val;
463
48.8k
        pthread_mutex_unlock(&m_mutex);
464
48.8k
        return ret;
465
48.8k
    }
466
467
    int getIncr(int n = 1)
468
0
    {
469
0
        pthread_mutex_lock(&m_mutex);
470
0
        int ret = m_val;
471
0
        m_val += n;
472
0
        pthread_mutex_unlock(&m_mutex);
473
0
        return ret;
474
0
    }
475
476
    void set(int newval)
477
65.6k
    {
478
65.6k
        pthread_mutex_lock(&m_mutex);
479
65.6k
        m_val = newval;
480
65.6k
        pthread_cond_broadcast(&m_cond);
481
65.6k
        pthread_mutex_unlock(&m_mutex);
482
65.6k
    }
483
484
    void poke(void)
485
3.64k
    {
486
        /* awaken all waiting threads, but make no change */
487
3.64k
        pthread_mutex_lock(&m_mutex);
488
3.64k
        pthread_cond_broadcast(&m_cond);
489
3.64k
        pthread_mutex_unlock(&m_mutex);
490
3.64k
    }
491
492
    void incr()
493
16.2k
    {
494
16.2k
        pthread_mutex_lock(&m_mutex);
495
16.2k
        m_val++;
496
16.2k
        pthread_cond_broadcast(&m_cond);
497
16.2k
        pthread_mutex_unlock(&m_mutex);
498
16.2k
    }
499
500
    void decr()
501
0
    {
502
0
        pthread_mutex_lock(&m_mutex);
503
0
        m_val--;
504
0
        pthread_cond_broadcast(&m_cond);
505
0
        pthread_mutex_unlock(&m_mutex);
506
0
    }
507
508
protected:
509
510
    pthread_mutex_t m_mutex;
511
    pthread_cond_t  m_cond;
512
    int             m_val;
513
};
514
515
0
#define TIMEOUT_INFINITE 0xFFFFFFFF
516
517
class NamedSemaphore
518
{
519
public:
520
    NamedSemaphore() 
521
0
        : m_sem(NULL)
522
0
#ifndef __APPLE__
523
0
        , m_name(NULL)
524
0
#endif //__APPLE__
525
0
    {
526
0
    }
527
528
    ~NamedSemaphore()
529
0
    {
530
0
    }
531
532
    bool create(const char* name, const int initcnt, const int maxcnt)
533
0
    {
534
0
        bool ret = false;
535
536
0
        if (initcnt >= maxcnt)
537
0
        {
538
0
            return false;
539
0
        }
540
541
#ifdef __APPLE__
542
        do
543
        {
544
            int32_t pshared = name != NULL ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE;
545
546
            m_sem = (mac_sem_t *)malloc(sizeof(mac_sem_t));
547
            if (!m_sem)
548
            {
549
                break;
550
            }
551
552
            if (pthread_mutexattr_init(&m_sem->mutexAttr))
553
            {
554
                break;
555
            }
556
557
            if (pthread_mutexattr_setpshared(&m_sem->mutexAttr, pshared))
558
            {
559
                break;
560
            }
561
562
            if (pthread_condattr_init(&m_sem->condAttr))
563
            {
564
                break;
565
            }
566
567
            if (pthread_condattr_setpshared(&m_sem->condAttr, pshared))
568
            {
569
                break;
570
            }
571
572
            if (pthread_mutex_init(&m_sem->mutex, &m_sem->mutexAttr))
573
            {
574
                break;
575
            }
576
577
            if (pthread_cond_init(&m_sem->cond, &m_sem->condAttr))
578
            {
579
                break;
580
            }
581
582
            m_sem->curCnt = initcnt;
583
            m_sem->maxCnt = maxcnt;
584
585
            ret = true;
586
        } while (0);
587
        
588
        if (!ret)
589
        {
590
            release();
591
        }
592
593
#else  //__APPLE__
594
0
        m_sem = sem_open(name, O_CREAT | O_EXCL, 0666, initcnt);
595
0
        if (m_sem != SEM_FAILED) 
596
0
        {
597
0
            m_name = strdup(name);
598
0
            ret = true;
599
0
        }
600
0
        else 
601
0
        {
602
0
            if (EEXIST == errno) 
603
0
            {
604
0
                m_sem = sem_open(name, 0);
605
0
                if (m_sem != SEM_FAILED) 
606
0
                {
607
0
                    m_name = strdup(name);
608
0
                    ret = true;
609
0
                }
610
0
            }
611
0
        }
612
0
#endif //__APPLE__
613
614
0
        return ret;
615
0
    }
616
617
    bool give(const int32_t cnt)
618
0
    {
619
0
        if (!m_sem)
620
0
        {
621
0
            return false;
622
0
        }
623
624
#ifdef __APPLE__
625
        if (pthread_mutex_lock(&m_sem->mutex))
626
        {
627
            return false;
628
        }
629
630
        int oldCnt = m_sem->curCnt;
631
        m_sem->curCnt += cnt;
632
        if (m_sem->curCnt > m_sem->maxCnt)
633
        {
634
            m_sem->curCnt = m_sem->maxCnt;
635
        }
636
637
        bool ret = true;
638
        if (!oldCnt)
639
        {
640
            ret = 0 == pthread_cond_broadcast(&m_sem->cond);
641
        }
642
643
        if (pthread_mutex_unlock(&m_sem->mutex))
644
        {
645
            return false;
646
        }
647
648
        return ret;
649
#else //__APPLE__
650
0
        int ret = 0;
651
0
        int32_t curCnt = cnt;
652
0
        while (curCnt-- && !ret) {
653
0
            ret = sem_post(m_sem);
654
0
        }
655
656
0
        return 0 == ret;
657
0
#endif //_APPLE__
658
0
    }
659
660
    bool take(const uint32_t time_out = TIMEOUT_INFINITE)
661
0
    {
662
0
        if (!m_sem)
663
0
        {
664
0
            return false;
665
0
        }
666
667
#ifdef __APPLE__
668
669
        if (pthread_mutex_lock(&m_sem->mutex))
670
        {
671
            return false;
672
        }
673
674
        bool ret = true;
675
        if (TIMEOUT_INFINITE == time_out) 
676
        {
677
            if (!m_sem->curCnt)
678
            {
679
                if (pthread_cond_wait(&m_sem->cond, &m_sem->mutex))
680
                {
681
                    ret = false;
682
                } 
683
            }
684
685
            if (m_sem->curCnt && ret)
686
            {
687
                m_sem->curCnt--;
688
            }
689
        }
690
        else
691
        {
692
            if (0 == time_out)
693
            {
694
                if (m_sem->curCnt)
695
                {
696
                    m_sem->curCnt--;
697
                }
698
                else
699
                {
700
                    ret = false;
701
                }
702
            }
703
            else
704
            {
705
                if (!m_sem->curCnt)
706
                {
707
                    struct timespec ts;
708
                    ts.tv_sec = time_out / 1000L;
709
                    ts.tv_nsec = (time_out * 1000000L) - ts.tv_sec * 1000 * 1000 * 1000;
710
711
                    if (pthread_cond_timedwait(&m_sem->cond, &m_sem->mutex, &ts))
712
                    {
713
                        ret = false;
714
                    }
715
                }
716
717
                if (m_sem->curCnt && ret)
718
                {
719
                    m_sem->curCnt--;
720
                }
721
            }
722
        }
723
724
        if (pthread_mutex_unlock(&m_sem->mutex))
725
        {
726
            return false;
727
        }
728
729
        return ret;
730
#else //__APPLE__
731
0
        if (TIMEOUT_INFINITE == time_out) 
732
0
        {
733
0
            return 0 == sem_wait(m_sem);
734
0
        }
735
0
        else 
736
0
        {
737
0
            if (0 == time_out)
738
0
            {
739
0
                return 0 == sem_trywait(m_sem);
740
0
            }
741
0
            else
742
0
            {
743
0
                struct timespec ts;
744
0
                ts.tv_sec = time_out / 1000L;
745
0
                ts.tv_nsec = (time_out * 1000000L) - ts.tv_sec * 1000 * 1000 * 1000;
746
0
                return 0 == sem_timedwait(m_sem, &ts);
747
0
            }
748
0
        }
749
0
#endif //_APPLE__
750
0
    }
751
752
    void release()
753
0
    {
754
0
        if (m_sem)
755
0
        {
756
#ifdef __APPLE__
757
            pthread_condattr_destroy(&m_sem->condAttr);
758
            pthread_mutexattr_destroy(&m_sem->mutexAttr);
759
            pthread_mutex_destroy(&m_sem->mutex);
760
            pthread_cond_destroy(&m_sem->cond);
761
            free(m_sem);
762
            m_sem = NULL;
763
#else //__APPLE__
764
0
            sem_close(m_sem);
765
0
            sem_unlink(m_name);
766
0
            m_sem = NULL;
767
0
            free(m_name);
768
0
            m_name = NULL;
769
0
#endif //__APPLE__
770
0
        }
771
0
    }
772
773
private:
774
#ifdef __APPLE__
775
    typedef struct
776
    {
777
        pthread_mutex_t     mutex;
778
        pthread_cond_t      cond;
779
        pthread_mutexattr_t mutexAttr;
780
        pthread_condattr_t  condAttr;
781
        uint32_t            curCnt;
782
        uint32_t            maxCnt;
783
    }mac_sem_t;
784
    mac_sem_t *m_sem;
785
#else // __APPLE__
786
    sem_t *m_sem;
787
    char  *m_name;
788
#endif // __APPLE_
789
};
790
791
#endif // ifdef _WIN32
792
793
class ScopedLock
794
{
795
public:
796
797
183k
    ScopedLock(Lock &instance) : inst(instance)
798
183k
    {
799
183k
        this->inst.acquire();
800
183k
    }
801
802
    ~ScopedLock()
803
183k
    {
804
183k
        this->inst.release();
805
183k
    }
806
807
protected:
808
809
    // do not allow assignments
810
    ScopedLock &operator =(const ScopedLock &);
811
812
    Lock &inst;
813
};
814
815
// Utility class which adds elapsed time of the scope of the object into the
816
// accumulator provided to the constructor
817
struct ScopedElapsedTime
818
{
819
0
    ScopedElapsedTime(int64_t& accum) : accumlatedTime(accum) { startTime = x265_mdate(); }
820
821
0
    ~ScopedElapsedTime() { accumlatedTime += x265_mdate() - startTime; }
822
823
protected:
824
825
    int64_t  startTime;
826
    int64_t& accumlatedTime;
827
828
    // do not allow assignments
829
    ScopedElapsedTime &operator =(const ScopedElapsedTime &);
830
};
831
832
//< Simplistic portable thread class.  Shutdown signalling left to derived class
833
class Thread
834
{
835
private:
836
837
    ThreadHandle thread;
838
839
public:
840
841
    Thread();
842
843
    virtual ~Thread();
844
845
    //< Derived class must implement ThreadMain.
846
    virtual void threadMain() = 0;
847
848
    //< Returns true if thread was successfully created
849
    bool start();
850
851
    void stop();
852
};
853
} // end namespace X265_NS
854
855
#endif // ifndef X265_THREADING_H