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 | |
22 | struct BLThreadPool; |
23 | struct BLThreadPoolVirt; |
24 | |
25 | // ============================================================================ |
26 | // [Constants] |
27 | // ============================================================================ |
28 | |
29 | enum 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 | |
52 | struct 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 | |
63 | struct 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 | |
131 | BL_HIDDEN BLThreadPool* blThreadPoolGlobal() noexcept; |
132 | BL_HIDDEN BLThreadPool* blThreadPoolCreate() noexcept; |
133 | |
134 | //! \} |
135 | //! \endcond |
136 | |
137 | #endif // BLEND2D_BLTHREADPOOL_P_H |
138 | |