Coverage Report

Created: 2026-07-16 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/libde265/libde265/threads.cc
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
#include "threads.h"
22
#include <assert.h>
23
#include <string.h>
24
25
#if defined(_MSC_VER) || defined(__MINGW32__)
26
# include <malloc.h>
27
#elif defined(HAVE_ALLOCA_H)
28
# include <alloca.h>
29
#endif
30
31
32
de265_progress_lock::de265_progress_lock()
33
11.8M
{
34
11.8M
  mProgress = 0;
35
11.8M
}
36
37
de265_progress_lock::~de265_progress_lock()
38
11.8M
{
39
11.8M
}
40
41
void de265_progress_lock::wait_for_progress(int progress)
42
72
{
43
72
  if (mProgress >= progress) {
44
72
    return;
45
72
  }
46
47
0
  std::unique_lock<std::mutex> lock(mutex);
48
0
  while (mProgress < progress) {
49
0
    cond.wait(lock);
50
0
  }
51
0
}
52
53
void de265_progress_lock::set_progress(int progress)
54
12.9M
{
55
12.9M
  std::unique_lock<std::mutex> lock(mutex);
56
57
12.9M
  if (progress>mProgress) {
58
10.6M
    mProgress = progress;
59
60
10.6M
    cond.notify_all();
61
10.6M
  }
62
12.9M
}
63
64
void de265_progress_lock::increase_progress(int progress)
65
3.41k
{
66
3.41k
  std::unique_lock<std::mutex> lock(mutex);
67
68
3.41k
  mProgress += progress;
69
3.41k
  cond.notify_all();
70
3.41k
}
71
72
int  de265_progress_lock::get_progress() const
73
285k
{
74
285k
  return mProgress;
75
285k
}
76
77
78
79
80
#include "libde265/decctx.h"
81
82
#if 0
83
const char* line="--------------------------------------------------";
84
void printblks(const thread_pool* pool)
85
{
86
  int w = pool->tasks[0].data.task_ctb.ctx->current_sps->PicWidthInCtbsY;
87
  int h = pool->tasks[0].data.task_ctb.ctx->current_sps->PicHeightInCtbsY;
88
89
  printf("active threads: %d  queue len: %d\n",pool->num_threads_working,pool->num_tasks);
90
91
  char *const p = (char *)alloca(w * h * sizeof(char));
92
  assert(p != nullptr);
93
  memset(p,' ',w*h);
94
95
  for (int i=0;i<pool->num_tasks;i++) {
96
    int b = 0; //pool->tasks[i].num_blockers;
97
    int x = pool->tasks[i].data.task_ctb.ctb_x;
98
    int y = pool->tasks[i].data.task_ctb.ctb_y;
99
    p[y*w+x] = b+'0';
100
  }
101
102
  for (int i=0;i<pool->num_threads_working;i++) {
103
    int x = pool->ctbx[i];
104
    int y = pool->ctby[i];
105
    p[y*w+x] = '*';
106
  }
107
108
  printf("+%s+\n",line+50-w);
109
  for (int y=0;y<h;y++)
110
    {
111
      printf("|");
112
      for (int x=0;x<w;x++)
113
        {
114
          printf("%c",p[x+y*w]);
115
        }
116
      printf("|\n");
117
    }
118
  printf("+%s+\n",line+50-w);
119
}
120
#endif
121
122
123
static void worker_thread(thread_pool* pool)
124
19.6k
{
125
159k
  while(true) {
126
127
159k
    thread_task* task = nullptr;
128
129
159k
    {
130
159k
      std::unique_lock<std::mutex> lock(pool->mutex);
131
132
      // wait until we can pick a task or until the pool has been stopped
133
134
188k
      for (;;) {
135
        // end waiting if thread-pool has been stopped or we have a task to execute
136
137
188k
        if (pool->stopped || pool->tasks.size()>0) {
138
159k
          break;
139
159k
        }
140
141
        //printf("going idle\n");
142
28.8k
        pool->cond_var.wait(lock);
143
28.8k
      }
144
145
      // if the pool was shut down, end the execution
146
147
159k
      if (pool->stopped) {
148
19.6k
        return;
149
19.6k
      }
150
151
152
      // get a task
153
154
139k
      task = pool->tasks.front();
155
139k
      pool->tasks.pop_front();
156
157
139k
      pool->num_threads_working++;
158
159
      //printblks(pool);
160
139k
    }
161
162
    // execute the task
163
164
0
    task->work();
165
166
    // end processing and check if this was the last task to be processed
167
168
    // TODO: the num_threads_working can probably be an atomic integer
169
139k
    std::unique_lock<std::mutex> lock(pool->mutex);
170
171
139k
    pool->num_threads_working--;
172
139k
  }
173
19.6k
}
174
175
176
de265_error thread_pool::start(int num_threads_to_start)
177
19.6k
{
178
19.6k
  de265_error err = DE265_OK;
179
180
  // limit number of threads to maximum
181
182
19.6k
  if (num_threads_to_start > MAX_THREADS) {
183
0
    num_threads_to_start = MAX_THREADS;
184
0
    err = DE265_WARNING_NUMBER_OF_THREADS_LIMITED_TO_MAXIMUM;
185
0
  }
186
187
19.6k
  num_threads = 0; // will be increased below
188
189
19.6k
  {
190
19.6k
    std::unique_lock<std::mutex> lock(mutex);
191
192
19.6k
    num_threads_working = 0;
193
19.6k
    stopped = false;
194
19.6k
  }
195
196
  // start worker threads
197
198
39.3k
  for (int i=0; i<num_threads_to_start; i++) {
199
19.6k
    thread[i] = std::thread(worker_thread, this);
200
19.6k
    num_threads++;
201
19.6k
  }
202
203
19.6k
  return err;
204
19.6k
}
205
206
207
void thread_pool::stop()
208
19.6k
{
209
19.6k
  {
210
19.6k
    std::unique_lock<std::mutex> lock(mutex);
211
19.6k
    stopped = true;
212
19.6k
  }
213
214
19.6k
  cond_var.notify_all();
215
216
39.3k
  for (int i=0;i<num_threads;i++) {
217
19.6k
    thread[i].join();
218
19.6k
  }
219
19.6k
}
220
221
222
void thread_pool::add_task(thread_task* task)
223
139k
{
224
139k
  std::unique_lock<std::mutex> lock(mutex);
225
226
139k
  if (!stopped) {
227
228
139k
    tasks.push_back(task);
229
230
    // wake up one thread
231
232
139k
    cond_var.notify_one();
233
139k
  }
234
139k
}