Line data Source code
1 : /**********************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: Global thread pool
5 : * Author: Even Rouault, <even dot rouault at spatialys dot com>
6 : *
7 : **********************************************************************
8 : * Copyright (c) 2020, Even Rouault, <even dot rouault at spatialys dot com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "cpl_conv.h"
14 : #include "cpl_multiproc.h"
15 : #include "cpl_string.h"
16 : #include "cpl_worker_thread_pool.h"
17 : #include "gdal_thread_pool.h"
18 :
19 : #include <algorithm>
20 : #include <mutex>
21 :
22 : // For unclear reasons, attempts at making this a std::unique_ptr<>, even
23 : // through a GetCompressThreadPool() method like GetMutexThreadPool(), lead
24 : // to "ctest -R autotest_alg" (and other autotest components as well)
25 : // to hang forever once the tests have terminated.
26 : static CPLWorkerThreadPool *gpoCompressThreadPool = nullptr;
27 :
28 1383 : static std::mutex &GetMutexThreadPool()
29 : {
30 : static std::mutex gMutexThreadPool;
31 1383 : return gMutexThreadPool;
32 : }
33 :
34 254 : CPLWorkerThreadPool *GDALGetGlobalThreadPool(int nThreads)
35 : {
36 254 : std::lock_guard oGuard(GetMutexThreadPool());
37 254 : if (gpoCompressThreadPool == nullptr)
38 : {
39 5 : gpoCompressThreadPool = new CPLWorkerThreadPool();
40 5 : if (!gpoCompressThreadPool->Setup(nThreads, nullptr, nullptr, false))
41 : {
42 0 : delete gpoCompressThreadPool;
43 0 : gpoCompressThreadPool = nullptr;
44 : }
45 : }
46 249 : else if (nThreads > gpoCompressThreadPool->GetThreadCount())
47 : {
48 : // Increase size of thread pool
49 3 : gpoCompressThreadPool->Setup(nThreads, nullptr, nullptr, false);
50 : }
51 508 : return gpoCompressThreadPool;
52 : }
53 :
54 1129 : void GDALDestroyGlobalThreadPool()
55 : {
56 1129 : std::lock_guard oGuard(GetMutexThreadPool());
57 1129 : delete gpoCompressThreadPool;
58 1129 : gpoCompressThreadPool = nullptr;
59 1129 : }
60 :
61 : /************************************************************************/
62 : /* GDALGetNumThreads() */
63 : /************************************************************************/
64 :
65 : /** Return the number of threads to use, taking into account the
66 : * GDAL_NUM_THREADS configuration option.
67 : *
68 : * @param nMaxVal Maximum number of threads, or -1 if none
69 : * @param bDefaultAllCPUs Whether the default value should be CPLGetNumCPUs()
70 : * @param[out] ppszValue Pointer to a string to set the string value used, or
71 : * nullptr if not needed.
72 : * @param[out] pbOK Pointer to a boolean indicating if the option value was
73 : * correct, or nullptr if not needed.
74 : *
75 : * @return value between 1 and std::max(1, nMaxVal)
76 : *
77 : * @since 3.13
78 : */
79 9864 : int GDALGetNumThreads(int nMaxVal, bool bDefaultAllCPUs, const char **ppszValue,
80 : bool *pbOK)
81 : {
82 9864 : return GDALGetNumThreads(nullptr, nullptr, nMaxVal, bDefaultAllCPUs,
83 9864 : ppszValue, pbOK);
84 : }
85 :
86 : /************************************************************************/
87 : /* GDALGetNumThreads() */
88 : /************************************************************************/
89 :
90 : /** Return the number of threads to use, taking into account first the
91 : * specified item in a list of options, and falling back to the
92 : * GDAL_NUM_THREADS configuration option.
93 : *
94 : * @param papszOptions null terminated list of options (or nullptr)
95 : * @param pszItemName item name in papszOptions (or nullptr)
96 : * @param nMaxVal Maximum number of threads, or -1 if none
97 : * @param bDefaultAllCPUs Whether the default value should be CPLGetNumCPUs()
98 : * @param[out] ppszValue Pointer to a string to set the string value used, or
99 : * nullptr if not needed.
100 : * @param[out] pbOK Pointer to a boolean indicating if the option value was
101 : * correct, or nullptr if not needed.
102 : *
103 : * @return value between 1 and std::max(1, nMaxVal)
104 : *
105 : * @since 3.13
106 : */
107 21292 : int GDALGetNumThreads(CSLConstList papszOptions, const char *pszItemName,
108 : int nMaxVal, bool bDefaultAllCPUs, const char **ppszValue,
109 : bool *pbOK)
110 : {
111 21292 : const char *pszNumThreads = nullptr;
112 21292 : if (papszOptions && pszItemName)
113 3905 : pszNumThreads = CSLFetchNameValue(papszOptions, pszItemName);
114 21292 : return GDALGetNumThreads(pszNumThreads, nMaxVal, bDefaultAllCPUs, ppszValue,
115 21292 : pbOK);
116 : }
117 :
118 : /************************************************************************/
119 : /* GDALGetNumThreads() */
120 : /************************************************************************/
121 :
122 : /** Return the number of threads to use, taking into account first the
123 : * specified value, and if null, falling back to the
124 : * GDAL_NUM_THREADS configuration option.
125 : *
126 : * @param pszNumThreads Value to parse to get the number of threads. If null,
127 : * the GDAL_NUM_THREADS configuration option is used.
128 : * @param nMaxVal Maximum number of threads, or -1 if none
129 : * @param bDefaultAllCPUs Whether the default value should be CPLGetNumCPUs()
130 : * @param[out] ppszValue Pointer to a string to set the string value used, or
131 : * nullptr if not needed.
132 : * @param[out] pbOK Pointer to a boolean indicating if the option value was
133 : * correct, or nullptr if not needed.
134 : *
135 : * @return value between 1 and std::max(1, nMaxVal)
136 : *
137 : * @since 3.13
138 : */
139 23948 : int GDALGetNumThreads(const char *pszNumThreads, int nMaxVal,
140 : bool bDefaultAllCPUs, const char **ppszValue, bool *pbOK)
141 : {
142 23948 : if (!pszNumThreads)
143 : {
144 23136 : pszNumThreads = CPLGetConfigOption("GDAL_NUM_THREADS",
145 : bDefaultAllCPUs ? "ALL_CPUS" : "1");
146 : }
147 23948 : if (ppszValue)
148 10746 : *ppszValue = pszNumThreads;
149 23948 : int nThreads = EQUAL(pszNumThreads, "ALL_CPUS") ? CPLGetNumCPUs()
150 21338 : : atoi(pszNumThreads);
151 23948 : if (pbOK)
152 17969 : *pbOK = EQUAL(pszNumThreads, "ALL_CPUS") ||
153 8771 : CPLGetValueType(pszNumThreads) == CPL_VALUE_INTEGER;
154 23948 : if (nMaxVal > 0)
155 17523 : nThreads = std::min(nThreads, nMaxVal);
156 23948 : return std::max(nThreads, 1);
157 : }
|