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