Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libde265/libde265/threads.h
Line
Count
Source
1
/*
2
 * H.265 video codec.
3
 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
4
 *
5
 * This file is part of libde265.
6
 *
7
 * libde265 is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libde265 is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libde265.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#ifndef DE265_THREADS_H
22
#define DE265_THREADS_H
23
24
#include "libde265/de265.h"
25
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
#endif
29
30
#include <deque>
31
#include <string>
32
#include <atomic>
33
34
#ifdef _WIN32
35
#if !defined(NOMINMAX)
36
#define NOMINMAX
37
#endif
38
#include <windows.h>
39
#include "../extra/win32cond.h"
40
#if _MSC_VER > 1310
41
#include <intrin.h>
42
#endif
43
#endif  // _WIN32
44
45
#include <atomic>
46
#include <mutex>
47
#include <condition_variable>
48
#include <thread>
49
50
class de265_progress_lock
51
{
52
public:
53
  de265_progress_lock();
54
  ~de265_progress_lock();
55
56
  void wait_for_progress(int progress);
57
  void set_progress(int progress);
58
  void increase_progress(int progress);
59
  int  get_progress() const;
60
1.11M
  void reset(int value=0) { mProgress.store(value, std::memory_order_release); }
61
62
private:
63
  // Read lock-free on the fast paths of wait_for_progress()/get_progress()
64
  // while written under 'mutex'. It must be atomic so those reads are not a
65
  // data race, and it carries acquire/release ordering so that the state a
66
  // producer wrote before signalling progress (e.g. the saved WPP row context)
67
  // is published to a consumer that observes the progress value without taking
68
  // the mutex (GHSA-xp3h-6f5r-8cxp).
69
  std::atomic<int> mProgress;
70
71
  // private data
72
73
  std::mutex mutex;
74
  std::condition_variable cond;
75
};
76
77
78
79
class thread_task
80
{
81
public:
82
217k
  thread_task() : state(Queued) { }
83
217k
  virtual ~thread_task() { }
84
85
  enum { Queued, Running, Blocked, Finished } state;
86
87
  virtual void work() = 0;
88
89
0
  virtual std::string name() const { return "noname"; }
90
};
91
92
93
constexpr int MAX_THREADS = 32;
94
95
/* TODO NOTE: When unblocking a task, we have to check first
96
   if there are threads waiting because of the run-count limit.
97
   If there are higher-priority tasks, those should be run instead
98
   of the just unblocked task.
99
 */
100
101
class thread_pool
102
{
103
 public:
104
  de265_error start(int num_threads);
105
  void        stop(); // do not process remaining tasks
106
  void        add_task(thread_task* task);
107
108
109
  bool stopped;
110
111
  std::deque<thread_task*> tasks;  // we are not the owner
112
113
  int num_threads_working;
114
115
  std::mutex  mutex;
116
  std::condition_variable  cond_var;
117
118
private:
119
  std::thread thread[MAX_THREADS];
120
  int num_threads;
121
122
  //int ctbx[MAX_THREADS]; // the CTB the thread is working on
123
  //int ctby[MAX_THREADS];
124
};
125
126
#endif