124 |
125 | std::vector<std::thread> threads;
126 | int n_tasks = std::max(1u, std::thread::hardware_concurrency());
127 | for (int i = 0; i < n_tasks; ++i) {
128 | - threads.emplace_back( grind_task, nBits, std::ref(header), i, n_tasks, std::ref(found) );
129 | + threads.emplace_back(grind_task, nBits, header, i, n_tasks, std::ref(found));
Maybe just pass in both a std::atomic<bool>& found and a std::atomic<uint32_t>& proposed_nonce with the threads doing:
if (hash <= target) { found = true; proposed_nonce = header.nNonce; return; }
and the parent doing
if (found) { header.nNonce = proposed_nonce }
else { error; }
(gcc seems to treat optional<atomic<int>> and atomic<bool> + atomic<int> pretty similarly; clang seems to need to do calls to atomic_load/atomic_store with the optional which seems lame to me. mostly the code seems easier to read without the .load() and .has_value() stuff. But only very weak preference)
Huh? Are you sure this will work. What if the thread is put to sleep after found=true and before setting the nonce. Then, the parent will succeed with if(found), but fail to read the nonce.
Oh, I guess it requires the threads to join, which was the requirement before as well.