@@ -94,10 +94,8 @@ bool ProjectDownloader::downloadAssets(const std::vector<std::string> &assetIds)
94
94
m_cancelMutex.unlock ();
95
95
96
96
auto count = assetIds.size ();
97
- unsigned int threadCount = std::thread::hardware_concurrency ();
98
-
99
- // Thread count: number of assets / 5, limited to maximum number of threads
100
- threadCount = std::max (1u , std::min (threadCount, static_cast <unsigned int >(std::ceil (count / 5.0 ))));
97
+ // unsigned int threadCount = std::thread::hardware_concurrency();
98
+ unsigned int threadCount = 20 ;
101
99
102
100
m_assets.clear ();
103
101
m_assets.reserve (count);
@@ -120,48 +118,92 @@ bool ProjectDownloader::downloadAssets(const std::vector<std::string> &assetIds)
120
118
downloaders.push_back (m_downloaderFactory->create ());
121
119
122
120
// Download assets
123
- auto f = [this , &downloaders, &assetIds, count, threadCount](unsigned int thread) {
124
- auto downloader = downloaders[thread];
125
- unsigned int n = std::ceil (count / static_cast <double >(threadCount));
121
+ auto f = [this , count](std::shared_ptr<IDownloader> downloader, int index, const std::string &id) {
122
+ m_cancelMutex.lock ();
126
123
127
- for ( unsigned int i = 0 ; i < n; i++) {
128
- unsigned int index = thread * n + i ;
124
+ if (m_cancel)
125
+ return ;
129
126
130
- if (index < count) {
131
- m_cancelMutex.lock ();
127
+ m_cancelMutex.unlock ();
132
128
133
- if (m_cancel)
134
- return ;
129
+ bool ret = downloader->download (ASSET_PREFIX + id + ASSET_SUFFIX);
135
130
136
- m_cancelMutex.unlock ();
131
+ if (!ret) {
132
+ std::cerr << " Failed to download asset: " << id << std::endl;
133
+ m_cancelMutex.lock ();
134
+ m_cancel = true ;
135
+ m_cancelMutex.unlock ();
136
+ return ;
137
+ }
137
138
138
- bool ret = downloader->download (ASSET_PREFIX + assetIds[index] + ASSET_SUFFIX);
139
+ m_assetsMutex.lock ();
140
+ m_assets[index] = downloader->text ();
141
+ m_downloadedAssetCount++;
142
+ m_downloadProgressChanged (m_downloadedAssetCount, count);
143
+ m_assetsMutex.unlock ();
144
+ };
139
145
140
- if (!ret) {
141
- std::cerr << " Failed to download asset: " << assetIds[index] << std::endl;
142
- m_cancelMutex.lock ();
143
- m_cancel = true ;
144
- m_cancelMutex.unlock ();
145
- return ;
146
- }
146
+ std::unordered_map<int , std::pair<std::thread, std::shared_ptr<IDownloader>>> threads;
147
+ bool done = false ;
148
+ unsigned int lastCount = 0 , i = 0 ;
147
149
148
- m_assetsMutex.lock ();
149
- m_assets[index] = downloader->text ();
150
- m_downloadedAssetCount++;
151
- std::cout << " Downloaded assets: " << m_downloadedAssetCount << " of " << count << std::endl;
152
- m_downloadProgressChanged (m_downloadedAssetCount, count);
153
- m_assetsMutex.unlock ();
150
+ while (true ) {
151
+ int addCount = threadCount - threads.size ();
152
+
153
+ for (int j = 0 ; j < addCount; j++) {
154
+ if (i >= count) {
155
+ done = true ;
156
+ break ;
154
157
}
158
+
159
+ std::shared_ptr<IDownloader> freeDownloader = nullptr ;
160
+
161
+ for (auto downloader : downloaders) {
162
+ auto it = std::find_if (threads.begin (), threads.end (), [&downloader](std::pair<const int , std::pair<std::thread, std::shared_ptr<IDownloader>>> &pair) {
163
+ return pair.second .second == downloader;
164
+ });
165
+
166
+ if (it == threads.cend ()) {
167
+ freeDownloader = downloader;
168
+ break ;
169
+ }
170
+ }
171
+
172
+ assert (freeDownloader);
173
+ threads[i] = { std::thread (f, freeDownloader, i, assetIds[i]), freeDownloader };
174
+ i++;
155
175
}
156
- };
157
176
158
- std::vector< std::thread> threads ;
177
+ std::this_thread::sleep_for ( std::chrono::milliseconds ( 25 )) ;
159
178
160
- for (unsigned int i = 0 ; i < threadCount; i++)
161
- threads.emplace_back (std::thread (f, i));
179
+ m_assetsMutex.lock ();
162
180
163
- for (unsigned int i = 0 ; i < threadCount; i++)
164
- threads[i].join ();
181
+ if (m_downloadedAssetCount != lastCount) {
182
+ std::cout << " Downloaded assets: " << m_downloadedAssetCount << " of " << count << std::endl;
183
+ lastCount = m_downloadedAssetCount;
184
+ }
185
+
186
+ std::vector<int > toRemove;
187
+
188
+ for (auto &[index, info] : threads) {
189
+ if (!m_assets[index].empty ())
190
+ toRemove.push_back (index);
191
+ }
192
+
193
+ m_assetsMutex.unlock ();
194
+
195
+ for (int index : toRemove) {
196
+ threads[index].first .join ();
197
+ threads.erase (index);
198
+ }
199
+
200
+ if (done) {
201
+ for (auto &[index, info] : threads)
202
+ info.first .join ();
203
+
204
+ break ;
205
+ }
206
+ }
165
207
166
208
CHECK_CANCEL ();
167
209
0 commit comments