move progress reporting to main thread

This commit is contained in:
Lily Tsuru 2023-08-22 00:12:11 -04:00
parent 22c61ea451
commit ad076a8150
1 changed files with 54 additions and 18 deletions

View File

@ -69,6 +69,7 @@ bool NextCode(std::string& buffer, size_t start) {
} }
// see https://bisqwit.iki.fi/jutut/kuvat/programming_examples/cpp_thread_tutorial/ver05.cc // see https://bisqwit.iki.fi/jutut/kuvat/programming_examples/cpp_thread_tutorial/ver05.cc
// this version of the code doesn't even need to worry about synchronization
namespace { namespace {
unsigned ln = 1; unsigned ln = 1;
@ -86,15 +87,17 @@ namespace {
return "\r" + (m < 0 ? "\33[" + std::to_string(-m) + 'A' : std::string(m, '\n')); return "\r" + (m < 0 ? "\33[" + std::to_string(-m) + 'A' : std::string(m, '\n'));
} }
std::mutex print_lock;
} // namespace } // namespace
struct BruteThreadState { struct ThreadDisplayData {
BruteThreadState(unsigned line) : line(line) {} ThreadDisplayData() { codeString.resize(8); }
void DisplayProgress(const std::string& code, std::uint32_t hash) { std::uint32_t threadIndex;
std::lock_guard<std::mutex> lk(print_lock); std::string codeString;
std::uint32_t codeHash;
bool done = false;
void DisplayProgress() {
struct FputcIterator { struct FputcIterator {
using iterator_category = std::output_iterator_tag; using iterator_category = std::output_iterator_tag;
using value_type = void; using value_type = void;
@ -116,34 +119,51 @@ struct BruteThreadState {
std::FILE* file; std::FILE* file;
}; };
std::format_to(FputcIterator(stdout), "{}Thread {:2}: Trying code {}{} {}({:08x}){}", Line(line), line, Color(172), code, Color(166), hash, if(!done)
Reset()); std::format_to(FputcIterator(stdout), "{}Thread {:2}: Trying code {}{} {}({:08x}){}", Line(threadIndex), threadIndex, Color(172),
codeString, Color(166), codeHash, Reset());
else {
std::format_to(FputcIterator(stdout), "{}Thread {:2}: {}Finished!{}", Line(threadIndex), threadIndex, Color(172), Reset());
}
std::fflush(stdout); std::fflush(stdout);
} }
};
std::vector<ThreadDisplayData> data(26);
struct BruteThreadState {
BruteThreadState(unsigned tid) : threadIndex(tid) {}
void BruteForce(char prefix) { void BruteForce(char prefix) {
// for(std::uint32_t i = 8; i <= code_length; ++i) { // for(std::uint32_t i = 8; i <= code_length; ++i) {
std::string test_buffer(code_length, 'a'); test_buffer.resize(code_length, 'a');
test_buffer[0] = prefix; test_buffer[0] = prefix;
// test all possible combinations // test all possible combinations
while(true) { while(true) {
// std::string test_buffer = RandomString(code_length, rng); // std::string test_buffer = RandomString(code_length, rng);
auto hash = SwsfScramble(test_buffer); hash = SwsfScramble(test_buffer);
if(hash == code_hash) { if(hash == code_hash) {
std::cerr << std::format("match: {} ({:08x})\n", test_buffer, hash); std::cerr << std::format("match: {} ({:08x})\n", test_buffer, hash);
} }
DisplayProgress(test_buffer, hash); memcpy(data[threadIndex].codeString.data(), test_buffer.data(), test_buffer.length());
data[threadIndex].codeHash = hash;
// DisplayProgress(test_buffer, hash);
if(!NextCode(test_buffer, 1)) if(!NextCode(test_buffer, 1))
break; break;
} }
//} //}
data[threadIndex].done = true;
} }
private: std::string test_buffer;
unsigned line; std::uint32_t hash;
unsigned threadIndex;
std::random_device rd; std::random_device rd;
// swbf::Xoshiro256ss rng{rd}; // swbf::Xoshiro256ss rng{rd};
}; };
@ -151,17 +171,33 @@ struct BruteThreadState {
int main() { int main() {
asio::io_context ioc; asio::io_context ioc;
asio::thread_pool pool(26); asio::thread_pool pool(27);
auto line = 0u; auto threadIndex = 0u;
// post worker threads to run onto the thread pool & wait for them to complete // post worker threads to run onto the thread pool & wait for them to complete
for(int i = 0; i < 26; ++i) for(int i = 0; i < 26; ++i)
asio::post(pool, [i, l = line++]() { asio::post(pool, [&, i, tid = threadIndex++]() {
BruteThreadState state(l); BruteThreadState state(tid);
data[tid].threadIndex = tid;
state.BruteForce('a' + i); state.BruteForce('a' + i);
}); });
pool.join(); bool done = false;
while(!done) {
int doneIndex = 0;
for(auto& d : data) {
if(d.done)
doneIndex++;
d.DisplayProgress();
}
if(doneIndex == 26) {
done = true;
}
}
pool.join(); // just in case!
return 0; return 0;
} }