Coverage Report

Created: 2026-03-31 07:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libjxl/lib/threads/thread_parallel_runner.cc
Line
Count
Source
1
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2
//
3
// Use of this source code is governed by a BSD-style
4
// license that can be found in the LICENSE file.
5
6
#include <jxl/memory_manager.h>
7
#include <jxl/parallel_runner.h>
8
#include <jxl/thread_parallel_runner.h>
9
#include <string.h>
10
11
#include <cstdint>
12
#include <cstdlib>
13
#include <thread>
14
15
#include "lib/threads/thread_parallel_runner_internal.h"
16
17
namespace {
18
19
// Default JxlMemoryManager using malloc and free for the jpegxl_threads
20
// library. Same as the default JxlMemoryManager for the jpegxl library
21
// itself.
22
23
// Default alloc and free functions.
24
21.7k
void* ThreadMemoryManagerDefaultAlloc(void* opaque, size_t size) {
25
21.7k
  return malloc(size);
26
21.7k
}
27
28
21.7k
void ThreadMemoryManagerDefaultFree(void* opaque, void* address) {
29
21.7k
  free(address);
30
21.7k
}
31
32
// Initializes the memory manager instance with the passed one. The
33
// MemoryManager passed in |memory_manager| may be NULL or contain NULL
34
// functions which will be initialized with the default ones. If either alloc
35
// or free are NULL, then both must be NULL, otherwise this function returns an
36
// error.
37
bool ThreadMemoryManagerInit(JxlMemoryManager* self,
38
43.9k
                             const JxlMemoryManager* memory_manager) {
39
43.9k
  if (memory_manager) {
40
22.2k
    *self = *memory_manager;
41
22.2k
  } else {
42
21.7k
    memset(self, 0, sizeof(*self));
43
21.7k
  }
44
43.9k
  bool is_default_alloc = (self->alloc == nullptr);
45
43.9k
  bool is_default_free = (self->free == nullptr);
46
43.9k
  if (is_default_alloc != is_default_free) {
47
0
    return false;
48
0
  }
49
43.9k
  if (is_default_alloc) self->alloc = ThreadMemoryManagerDefaultAlloc;
50
43.9k
  if (is_default_free) self->free = ThreadMemoryManagerDefaultFree;
51
52
43.9k
  return true;
53
43.9k
}
54
55
void* ThreadMemoryManagerAlloc(const JxlMemoryManager* memory_manager,
56
43.9k
                               size_t size) {
57
43.9k
  return memory_manager->alloc(memory_manager->opaque, size);
58
43.9k
}
59
60
void ThreadMemoryManagerFree(const JxlMemoryManager* memory_manager,
61
43.9k
                             void* address) {
62
43.9k
  memory_manager->free(memory_manager->opaque, address);
63
43.9k
}
64
65
}  // namespace
66
67
JxlParallelRetCode JxlThreadParallelRunner(
68
    void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init,
69
194k
    JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range) {
70
194k
  return jpegxl::ThreadParallelRunner::Runner(
71
194k
      runner_opaque, jpegxl_opaque, init, func, start_range, end_range);
72
194k
}
73
74
/// Starts the given number of worker threads and blocks until they are ready.
75
/// "num_worker_threads" defaults to one per hyperthread. If zero, all tasks
76
/// run on the main thread.
77
void* JxlThreadParallelRunnerCreate(const JxlMemoryManager* memory_manager,
78
43.9k
                                    size_t num_worker_threads) {
79
43.9k
  JxlMemoryManager local_memory_manager;
80
43.9k
  if (!ThreadMemoryManagerInit(&local_memory_manager, memory_manager))
81
0
    return nullptr;
82
83
43.9k
  void* alloc = ThreadMemoryManagerAlloc(&local_memory_manager,
84
43.9k
                                         sizeof(jpegxl::ThreadParallelRunner));
85
43.9k
  if (!alloc) return nullptr;
86
  // Placement new constructor on allocated memory
87
43.9k
  jpegxl::ThreadParallelRunner* runner =
88
43.9k
      new (alloc) jpegxl::ThreadParallelRunner(num_worker_threads);
89
43.9k
  runner->memory_manager = local_memory_manager;
90
91
43.9k
  return runner;
92
43.9k
}
93
94
43.9k
void JxlThreadParallelRunnerDestroy(void* runner_opaque) {
95
43.9k
  jpegxl::ThreadParallelRunner* runner =
96
43.9k
      reinterpret_cast<jpegxl::ThreadParallelRunner*>(runner_opaque);
97
43.9k
  if (runner) {
98
43.9k
    JxlMemoryManager local_memory_manager = runner->memory_manager;
99
    // Call destructor directly since custom free function is used.
100
43.9k
    runner->~ThreadParallelRunner();
101
43.9k
    ThreadMemoryManagerFree(&local_memory_manager, runner);
102
43.9k
  }
103
43.9k
}
104
105
// Get default value for num_worker_threads parameter of
106
// InitJxlThreadParallelRunner.
107
22.2k
size_t JxlThreadParallelRunnerDefaultNumWorkerThreads() {
108
22.2k
  return std::thread::hardware_concurrency();
109
22.2k
}