1// [Blend2D]
2// 2D Vector Graphics Powered by a JIT Compiler.
3//
4// [License]
5// Zlib - See LICENSE.md file in the package.
6
7#ifndef BLEND2D_BLTHREADPOOL_P_H
8#define BLEND2D_BLTHREADPOOL_P_H
9
10#include "./blapi-internal_p.h"
11#include "./blthreading_p.h"
12#include "./blbitarray_p.h"
13
14//! \cond INTERNAL
15//! \addtogroup blend2d_internal
16//! \{
17
18// ============================================================================
19// [Forward Declarations]
20// ============================================================================
21
22struct BLThreadPool;
23struct BLThreadPoolVirt;
24
25// ============================================================================
26// [Constants]
27// ============================================================================
28
29enum BLThreadPoolAcquireFlags : uint32_t {
30 //! Try to acquire the number of threads specified, if it's not possible then
31 //! don't acquire any threads and return.
32 //!
33 //! \note This flag has precedence over `BL_THREAD_POOL_ACQUIRE_FLAG_FORCE_ONE`
34 //! and `BL_THREAD_POOL_ACQUIRE_FLAG_FORCE_ALL`, so it doesn't matter if these
35 //! flags were specified or not when `BL_THREAD_POOL_ACQUIRE_FLAG_TRY` is used.
36 BL_THREAD_POOL_ACQUIRE_FLAG_TRY = 0x00000001u,
37
38 //! Force to acquire / create at least one thread.
39 BL_THREAD_POOL_ACQUIRE_FLAG_FORCE_ONE = 0x00000002u,
40
41 //! Force to acquire / create extra threads if the thread-pool is full, these
42 //! threads will be then destroyed upon release. This mode ensures that the
43 //! user gets the number of threads asked for, but with a possible overhead of
44 //! creating additional threads when necessary.
45 BL_THREAD_POOL_ACQUIRE_FLAG_FORCE_ALL = 0x00000004u
46};
47
48// ============================================================================
49// [BLThreadPool]
50// ============================================================================
51
52struct BLThreadPoolVirt {
53 BLThreadPool* (BL_CDECL* addRef)(BLThreadPool* self) BL_NOEXCEPT;
54 BLResult (BL_CDECL* release)(BLThreadPool* self) BL_NOEXCEPT;
55 uint32_t (BL_CDECL* maxThreadCount)(const BLThreadPool* self) BL_NOEXCEPT;
56 uint32_t (BL_CDECL* pooledThreadCount)(const BLThreadPool* self) BL_NOEXCEPT;
57 BLResult (BL_CDECL* setThreadAttributes)(BLThreadPool* self, const BLThreadAttributes* attributes) BL_NOEXCEPT;
58 uint32_t (BL_CDECL* cleanup)(BLThreadPool* self) BL_NOEXCEPT;
59 uint32_t (BL_CDECL* acquireThreads)(BLThreadPool* self, BLThread** threads, uint32_t n, uint32_t flags) BL_NOEXCEPT;
60 void (BL_CDECL* releaseThreads)(BLThreadPool* self, BLThread** threads, uint32_t n) BL_NOEXCEPT;
61};
62
63struct BLThreadPool {
64 const BLThreadPoolVirt* virt;
65
66 // --------------------------------------------------------------------------
67 #ifdef __cplusplus
68 BL_INLINE BLThreadPool* addRef() noexcept { return virt->addRef(this); }
69 BL_INLINE BLResult release() noexcept { return virt->release(this); }
70
71 //! Returns the number of threads that are pooled at the moment.
72 //!
73 //! \note This is mostly informative as it's not guaranteed that successive
74 //! calls to `pooledThreadCount()` would return the same result as some
75 //! threads may be acquired during the request by another thread.
76 //!
77 //! \threadsafe
78 BL_INLINE uint32_t pooledThreadCount() const noexcept {
79 return virt->pooledThreadCount(this);
80 }
81
82 //! Returns the maximum number of threads that would be allocated by the
83 //! thread-pool.
84 //!
85 //! \threadsafe
86 BL_INLINE uint32_t maxThreadCount() const noexcept {
87 return virt->maxThreadCount(this);
88 }
89
90 //! Sets attributes that will affect only new threads created by thread-pool.
91 //! It's only recommended to set attributes immediately after the thread-pool
92 //! has been created as having threads with various attributes in a single
93 //! thread-pool could lead into unpredictable behavior and hard to find bugs.
94 BL_INLINE BLResult setThreadAttributes(const BLThreadAttributes& attributes) noexcept {
95 return virt->setThreadAttributes(this, &attributes);
96 }
97
98 //! Cleans up all pooled threads at the moment.
99 //!
100 //! Cleaning up means to release all pooled threads to the operating system
101 //! to free all associated resources with such threads. This operation should
102 //! not be called often, it's ideal to call it when application was minimized,
103 //! for example, or when the application knows that it completed an expensive
104 //! task, etc...
105 BL_INLINE uint32_t cleanup() noexcept {
106 return virt->cleanup(this);
107 }
108
109 //! Acquire `n` threads and store `BLThread*` to the given `threads` array.
110 //!
111 //! If `exact` is `true` then only the exact number of threads will be acquired,
112 //! and if it's not possible then no threads will be acquired. If `exact` is
113 //! `false` then the number of acquired threads can be less than `n` in case
114 //! that acquiring `n` threads is not possible due to reaching `maxThreadCount()`.
115 BL_INLINE uint32_t acquireThreads(BLThread** threads, uint32_t n, uint32_t flags = 0) noexcept {
116 return virt->acquireThreads(this, threads, n, flags);
117 }
118
119 //! Release `n` threads that were previously acquired by `acquireThreads()`.
120 BL_INLINE void releaseThreads(BLThread** threads, uint32_t n) noexcept {
121 return virt->releaseThreads(this, threads, n);
122 }
123 #endif
124 // --------------------------------------------------------------------------
125};
126
127// ============================================================================
128// [BLInternalThreadPool]
129// ============================================================================
130
131BL_HIDDEN BLThreadPool* blThreadPoolGlobal() noexcept;
132BL_HIDDEN BLThreadPool* blThreadPoolCreate() noexcept;
133
134//! \}
135//! \endcond
136
137#endif // BLEND2D_BLTHREADPOOL_P_H
138