/src/libjxl/lib/threads/thread_parallel_runner.cc
Line | Count | Source (jump to first uncovered line) |
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 | 11.7k | void* ThreadMemoryManagerDefaultAlloc(void* opaque, size_t size) { |
25 | 11.7k | return malloc(size); |
26 | 11.7k | } |
27 | | |
28 | 11.7k | void ThreadMemoryManagerDefaultFree(void* opaque, void* address) { |
29 | 11.7k | free(address); |
30 | 11.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 | 11.7k | const JxlMemoryManager* memory_manager) { |
39 | 11.7k | if (memory_manager) { |
40 | 0 | *self = *memory_manager; |
41 | 11.7k | } else { |
42 | 11.7k | memset(self, 0, sizeof(*self)); |
43 | 11.7k | } |
44 | 11.7k | bool is_default_alloc = (self->alloc == nullptr); |
45 | 11.7k | bool is_default_free = (self->free == nullptr); |
46 | 11.7k | if (is_default_alloc != is_default_free) { |
47 | 0 | return false; |
48 | 0 | } |
49 | 11.7k | if (is_default_alloc) self->alloc = ThreadMemoryManagerDefaultAlloc; |
50 | 11.7k | if (is_default_free) self->free = ThreadMemoryManagerDefaultFree; |
51 | | |
52 | 11.7k | return true; |
53 | 11.7k | } |
54 | | |
55 | | void* ThreadMemoryManagerAlloc(const JxlMemoryManager* memory_manager, |
56 | 11.7k | size_t size) { |
57 | 11.7k | return memory_manager->alloc(memory_manager->opaque, size); |
58 | 11.7k | } |
59 | | |
60 | | void ThreadMemoryManagerFree(const JxlMemoryManager* memory_manager, |
61 | 11.7k | void* address) { |
62 | 11.7k | memory_manager->free(memory_manager->opaque, address); |
63 | 11.7k | } |
64 | | |
65 | | } // namespace |
66 | | |
67 | | JxlParallelRetCode JxlThreadParallelRunner( |
68 | | void* runner_opaque, void* jpegxl_opaque, JxlParallelRunInit init, |
69 | 65.5k | JxlParallelRunFunction func, uint32_t start_range, uint32_t end_range) { |
70 | 65.5k | return jpegxl::ThreadParallelRunner::Runner( |
71 | 65.5k | runner_opaque, jpegxl_opaque, init, func, start_range, end_range); |
72 | 65.5k | } |
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 | 11.7k | size_t num_worker_threads) { |
79 | 11.7k | JxlMemoryManager local_memory_manager; |
80 | 11.7k | if (!ThreadMemoryManagerInit(&local_memory_manager, memory_manager)) |
81 | 0 | return nullptr; |
82 | | |
83 | 11.7k | void* alloc = ThreadMemoryManagerAlloc(&local_memory_manager, |
84 | 11.7k | sizeof(jpegxl::ThreadParallelRunner)); |
85 | 11.7k | if (!alloc) return nullptr; |
86 | | // Placement new constructor on allocated memory |
87 | 11.7k | jpegxl::ThreadParallelRunner* runner = |
88 | 11.7k | new (alloc) jpegxl::ThreadParallelRunner(num_worker_threads); |
89 | 11.7k | runner->memory_manager = local_memory_manager; |
90 | | |
91 | 11.7k | return runner; |
92 | 11.7k | } |
93 | | |
94 | 11.7k | void JxlThreadParallelRunnerDestroy(void* runner_opaque) { |
95 | 11.7k | jpegxl::ThreadParallelRunner* runner = |
96 | 11.7k | reinterpret_cast<jpegxl::ThreadParallelRunner*>(runner_opaque); |
97 | 11.7k | if (runner) { |
98 | 11.7k | JxlMemoryManager local_memory_manager = runner->memory_manager; |
99 | | // Call destructor directly since custom free function is used. |
100 | 11.7k | runner->~ThreadParallelRunner(); |
101 | 11.7k | ThreadMemoryManagerFree(&local_memory_manager, runner); |
102 | 11.7k | } |
103 | 11.7k | } |
104 | | |
105 | | // Get default value for num_worker_threads parameter of |
106 | | // InitJxlThreadParallelRunner. |
107 | 0 | size_t JxlThreadParallelRunnerDefaultNumWorkerThreads() { |
108 | 0 | return std::thread::hardware_concurrency(); |
109 | 0 | } |