diff --git a/include/core/rom.hpp b/include/core/rom.hpp index 95890d3d..dc7380aa 100644 --- a/include/core/rom.hpp +++ b/include/core/rom.hpp @@ -64,11 +64,11 @@ struct loaded_rom /** * Loaded main ROM */ - loaded_image romimg[ROM_SLOT_COUNT]; + fileimage::image romimg[ROM_SLOT_COUNT]; /** * Loaded main ROM XML */ - loaded_image romxml[ROM_SLOT_COUNT]; + fileimage::image romxml[ROM_SLOT_COUNT]; /** * MSU-1 base. */ @@ -131,7 +131,7 @@ extern std::map preferred_core; //Preferred overall core. extern std::string preferred_core_default; //Main hasher -extern sha256_hasher lsnes_image_hasher; +extern fileimage::hash lsnes_image_hasher; #endif diff --git a/include/library/fileimage.hpp b/include/library/fileimage.hpp index b162ed6d..bff4856f 100644 --- a/include/library/fileimage.hpp +++ b/include/library/fileimage.hpp @@ -7,22 +7,24 @@ #include #include "threadtypes.hpp" -class sha256_hasher; +namespace fileimage +{ +class hash; /** * Future for SHA-256 computation. */ -class sha256_future +class hashval { public: /** * Construct a null future, never resolves. */ - sha256_future(); + hashval(); /** * Construct a future, with value that is immediately resolved. */ - sha256_future(const std::string& value, uint64_t _prefix = 0); + hashval(const std::string& value, uint64_t _prefix = 0); /** * Is the result known? */ @@ -38,27 +40,27 @@ public: /** * Copy a future. */ - sha256_future(const sha256_future& f); + hashval(const hashval& f); /** * Assign a future. */ - sha256_future& operator=(const sha256_future& f); + hashval& operator=(const hashval& f); /** * Destroy a future. */ - ~sha256_future(); + ~hashval(); private: /** * Create a new future. */ - sha256_future(sha256_hasher& h, unsigned id); + hashval(hash& h, unsigned id); /** * Resolve a future. */ void resolve(unsigned id, const std::string& hash, uint64_t _prefix); void resolve_error(unsigned id, const std::string& err); - friend class sha256_hasher; + friend class hash; mutable mutex_class mutex; mutable cv_class condition; bool is_ready; @@ -66,25 +68,25 @@ private: uint64_t prefixv; std::string value; std::string error; - sha256_future* prev; - sha256_future* next; - sha256_hasher* hasher; + hashval* prev; + hashval* next; + hash* hasher; }; /** * Class performing SHA-256 hashing. */ -class sha256_hasher +class hash { public: /** * Create a new SHA-256 hasher. */ - sha256_hasher(); + hash(); /** * Destroy a SHA-256 hasher. Causes all current jobs to fail. */ - ~sha256_hasher(); + ~hash(); /** * Set callback. */ @@ -92,22 +94,22 @@ public: /** * Compute SHA-256 of file. */ - sha256_future operator()(const std::string& filename, uint64_t prefixlen = 0); + hashval operator()(const std::string& filename, uint64_t prefixlen = 0); /** * Compute SHA-256 of file. */ - sha256_future operator()(const std::string& filename, std::function prefixlen); + hashval operator()(const std::string& filename, std::function prefixlen); /** * Thread entrypoint. */ void entrypoint(); private: - void link(sha256_future& future); - void unlink(sha256_future& future); + void link(hashval& future); + void unlink(hashval& future); void send_callback(uint64_t this_completed); void send_idle(); - friend class sha256_future; + friend class hashval; struct queue_job { std::string filename; @@ -116,15 +118,15 @@ private: unsigned cbid; volatile unsigned interested; }; - sha256_hasher(const sha256_hasher&); - sha256_hasher& operator=(const sha256_hasher&); + hash(const hash&); + hash& operator=(const hash&); thread_class* hash_thread; mutex_class mutex; cv_class condition; std::list queue; std::list::iterator current_job; - sha256_future* first_future; - sha256_future* last_future; + hashval* first_future; + hashval* last_future; unsigned next_cbid; std::function progresscb; bool quitting; @@ -137,7 +139,7 @@ private: * * The loaded images are copied in CoW manner. */ -struct loaded_image +struct image { /** * Information about image to load. @@ -159,7 +161,7 @@ struct loaded_image * * throws std::bad_alloc: Not enough memory. */ - loaded_image() throw(std::bad_alloc); + image() throw(std::bad_alloc); /** * This constructor construct slot by reading data from file. If filename is "", constructs an empty slot. @@ -171,7 +173,7 @@ struct loaded_image * throws std::bad_alloc: Not enough memory. * throws std::runtime_error: Can't load the data. */ - loaded_image(sha256_hasher& hasher, const std::string& filename, const std::string& base, + image(hash& hasher, const std::string& filename, const std::string& base, const struct info& imginfo) throw(std::bad_alloc, std::runtime_error); /** @@ -210,7 +212,7 @@ struct loaded_image * * Note, for file images, this takes a bit of time to fill. */ - sha256_future sha_256; + hashval sha_256; /** * Get pointer to loaded data * @@ -244,5 +246,5 @@ struct loaded_image * Get headersize function. */ std::function std_headersize_fn(uint64_t hdrsize); - +} #endif diff --git a/src/core/moviedata.cpp b/src/core/moviedata.cpp index 8d0b1ae7..a9ab46ee 100644 --- a/src/core/moviedata.cpp +++ b/src/core/moviedata.cpp @@ -79,7 +79,7 @@ namespace messages << "Saved core state to " << name << std::endl; }); - bool warn_hash_mismatch(const std::string& mhash, const loaded_image& slot, + bool warn_hash_mismatch(const std::string& mhash, const fileimage::image& slot, const std::string& name, bool fatal) { if(mhash == slot.sha_256.read()) diff --git a/src/core/rom.cpp b/src/core/rom.cpp index 13486f86..f6da0362 100644 --- a/src/core/rom.cpp +++ b/src/core/rom.cpp @@ -185,19 +185,19 @@ namespace return fallback; } - struct loaded_image::info get_xml_info() + struct fileimage::image::info get_xml_info() { - loaded_image::info i; - i.type = loaded_image::info::IT_MARKUP; + fileimage::image::info i; + i.type = fileimage::image::info::IT_MARKUP; i.headersize = 0; return i; } - struct loaded_image::info xlate_info(core_romimage_info ri) + struct fileimage::image::info xlate_info(core_romimage_info ri) { - loaded_image::info i; - if(ri.pass_mode == 0) i.type = loaded_image::info::IT_MEMORY; - if(ri.pass_mode == 1) i.type = loaded_image::info::IT_FILE; + fileimage::image::info i; + if(ri.pass_mode == 0) i.type = fileimage::image::info::IT_MEMORY; + if(ri.pass_mode == 1) i.type = fileimage::image::info::IT_FILE; i.headersize = ri.headersize; return i; } @@ -217,7 +217,7 @@ namespace } } -sha256_hasher lsnes_image_hasher; +fileimage::hash lsnes_image_hasher; std::pair get_current_rom_info() throw() { @@ -243,14 +243,14 @@ loaded_rom::loaded_rom(const std::string& file, core_type& ctype) throw(std::bad //This thing has a BIOS. romidx = 1; std::string basename = lsnes_vset["firmwarepath"].str() + "/" + bios; - romimg[0] = loaded_image(lsnes_image_hasher, basename, "", xlate_info(ctype.get_image_info(0))); + romimg[0] = fileimage::image(lsnes_image_hasher, basename, "", xlate_info(ctype.get_image_info(0))); if(zip::file_exists(basename + ".xml")) - romxml[0] = loaded_image(lsnes_image_hasher, basename + ".xml", "", get_xml_info()); + romxml[0] = fileimage::image(lsnes_image_hasher, basename + ".xml", "", get_xml_info()); pmand |= ctype.get_image_info(0).mandatory; } - romimg[romidx] = loaded_image(lsnes_image_hasher, file, "", xlate_info(ctype.get_image_info(romidx))); + romimg[romidx] = fileimage::image(lsnes_image_hasher, file, "", xlate_info(ctype.get_image_info(romidx))); if(zip::file_exists(file + ".xml")) - romxml[romidx] = loaded_image(lsnes_image_hasher, file + ".xml", "", get_xml_info()); + romxml[romidx] = fileimage::image(lsnes_image_hasher, file + ".xml", "", get_xml_info()); pmand |= ctype.get_image_info(romidx).mandatory; msu1_base = zip::resolverel(file, ""); record_files(*this); @@ -284,16 +284,17 @@ loaded_rom::loaded_rom(const std::string& file, const std::string& tmpprefer) th //This thing has a BIOS. romidx = 1; std::string basename = lsnes_vset["firmwarepath"].str() + "/" + bios; - romimg[0] = loaded_image(lsnes_image_hasher, basename, "", + romimg[0] = fileimage::image(lsnes_image_hasher, basename, "", xlate_info(coretype->get_image_info(0))); if(zip::file_exists(basename + ".xml")) - romxml[0] = loaded_image(lsnes_image_hasher, basename + ".xml", "", get_xml_info()); + romxml[0] = fileimage::image(lsnes_image_hasher, basename + ".xml", "", + get_xml_info()); pmand |= rtype->get_image_info(0).mandatory; } - romimg[romidx] = loaded_image(lsnes_image_hasher, file, "", + romimg[romidx] = fileimage::image(lsnes_image_hasher, file, "", xlate_info(coretype->get_image_info(romidx))); if(zip::file_exists(file + ".xml")) - romxml[romidx] = loaded_image(lsnes_image_hasher, file + ".xml", "", get_xml_info()); + romxml[romidx] = fileimage::image(lsnes_image_hasher, file + ".xml", "", get_xml_info()); pmand |= rtype->get_image_info(romidx).mandatory; msu1_base = zip::resolverel(file, ""); record_files(*this); @@ -369,8 +370,9 @@ loaded_rom::loaded_rom(const std::string& file, const std::string& tmpprefer) th //Load ROMs. for(size_t i = 0; i < rtype->get_image_count(); i++) { - romimg[i] = loaded_image(lsnes_image_hasher, cromimg[i], file, xlate_info(rtype->get_image_info(i))); - romxml[i] = loaded_image(lsnes_image_hasher, cromxml[i], file, get_xml_info()); + romimg[i] = fileimage::image(lsnes_image_hasher, cromimg[i], file, + xlate_info(rtype->get_image_info(i))); + romxml[i] = fileimage::image(lsnes_image_hasher, cromxml[i], file, get_xml_info()); } record_files(*this); //Have to do this before patching. @@ -483,14 +485,14 @@ loaded_rom::loaded_rom(const std::string& file, const std::string& core, const s unsigned romidx = (bios != "") ? 1 : 0; if(bios != "") { std::string basename = lsnes_vset["firmwarepath"].str() + "/" + bios; - romimg[0] = loaded_image(lsnes_image_hasher, basename, "", xlate_info(t->get_image_info(0))); + romimg[0] = fileimage::image(lsnes_image_hasher, basename, "", xlate_info(t->get_image_info(0))); if(zip::file_exists(basename + ".xml")) - romxml[0] = loaded_image(lsnes_image_hasher, basename + ".xml", "", get_xml_info()); + romxml[0] = fileimage::image(lsnes_image_hasher, basename + ".xml", "", get_xml_info()); pmand |= t->get_image_info(0).mandatory; } - romimg[romidx] = loaded_image(lsnes_image_hasher, file, "", xlate_info(t->get_image_info(romidx))); + romimg[romidx] = fileimage::image(lsnes_image_hasher, file, "", xlate_info(t->get_image_info(romidx))); if(zip::file_exists(file + ".xml")) - romxml[romidx] = loaded_image(lsnes_image_hasher, file + ".xml", "", get_xml_info()); + romxml[romidx] = fileimage::image(lsnes_image_hasher, file + ".xml", "", get_xml_info()); pmand |= t->get_image_info(romidx).mandatory; msu1_base = zip::resolverel(file, ""); record_files(*this); @@ -532,9 +534,9 @@ loaded_rom::loaded_rom(const std::string file[ROM_SLOT_COUNT], const std::string if(file[i] != "") pmand |= t->get_image_info(i).mandatory; tmand |= t->get_image_info(i).mandatory; - romimg[i] = loaded_image(lsnes_image_hasher, file[i], "", xlate_info(t->get_image_info(i))); + romimg[i] = fileimage::image(lsnes_image_hasher, file[i], "", xlate_info(t->get_image_info(i))); if(zip::file_exists(file[i] + ".xml")) - romxml[i] = loaded_image(lsnes_image_hasher, file[i] + ".xml", "", get_xml_info()); + romxml[i] = fileimage::image(lsnes_image_hasher, file[i] + ".xml", "", get_xml_info()); } msu1_base = zip::resolverel(file[romidx], ""); record_files(*this); diff --git a/src/core/romguess.cpp b/src/core/romguess.cpp index 977c03ce..cecd571e 100644 --- a/src/core/romguess.cpp +++ b/src/core/romguess.cpp @@ -94,7 +94,7 @@ namespace return ""; } try { - sha256_future f = lsnes_image_hasher(file, std_headersize_fn(hsize)); + fileimage::hashval f = lsnes_image_hasher(file, fileimage::std_headersize_fn(hsize)); std::string hash = f.read(); uint64_t prefix = f.prefix(); record_hash(file, prefix, hash); diff --git a/src/library/fileimage.cpp b/src/library/fileimage.cpp index 10ecb54b..324f7241 100644 --- a/src/library/fileimage.cpp +++ b/src/library/fileimage.cpp @@ -7,6 +7,8 @@ #include "directory.hpp" #include +namespace fileimage +{ namespace { std::map> cached_entries; @@ -24,7 +26,7 @@ namespace return 0; } - void* thread_trampoline(sha256_hasher* h) + void* thread_trampoline(hash* h) { h->entrypoint(); return NULL; @@ -94,7 +96,7 @@ namespace } } -sha256_future::sha256_future() +hashval::hashval() { is_ready = false; cbid = 0; @@ -102,7 +104,7 @@ sha256_future::sha256_future() hasher = NULL; } -sha256_future::sha256_future(const std::string& _value, uint64_t _prefix) +hashval::hashval(const std::string& _value, uint64_t _prefix) { is_ready = true; value = _value; @@ -112,7 +114,7 @@ sha256_future::sha256_future(const std::string& _value, uint64_t _prefix) hasher = NULL; } -sha256_future::sha256_future(sha256_hasher& h, unsigned id) +hashval::hashval(hash& h, unsigned id) { umutex_class h2(global_queue_mutex()); is_ready = false; @@ -122,7 +124,7 @@ sha256_future::sha256_future(sha256_hasher& h, unsigned id) hasher->link(*this); } -sha256_future::~sha256_future() +hashval::~hashval() { umutex_class h2(global_queue_mutex()); umutex_class h(mutex); @@ -130,13 +132,13 @@ sha256_future::~sha256_future() hasher->unlink(*this); } -bool sha256_future::ready() const +bool hashval::ready() const { umutex_class h(mutex); return is_ready; } -std::string sha256_future::read() const +std::string hashval::read() const { umutex_class h(mutex); while(!is_ready) @@ -146,7 +148,7 @@ std::string sha256_future::read() const return value; } -uint64_t sha256_future::prefix() const +uint64_t hashval::prefix() const { umutex_class h(mutex); while(!is_ready) @@ -156,7 +158,7 @@ uint64_t sha256_future::prefix() const return prefixv; } -sha256_future::sha256_future(const sha256_future& f) +hashval::hashval(const hashval& f) { umutex_class h2(global_queue_mutex()); umutex_class h(f.mutex); @@ -171,7 +173,7 @@ sha256_future::sha256_future(const sha256_future& f) hasher->link(*this); } -sha256_future& sha256_future::operator=(const sha256_future& f) +hashval& hashval::operator=(const hashval& f) { if(this == &f) return *this; @@ -199,7 +201,7 @@ sha256_future& sha256_future::operator=(const sha256_future& f) f.mutex.unlock(); } -void sha256_future::resolve(unsigned id, const std::string& hash, uint64_t _prefix) +void hashval::resolve(unsigned id, const std::string& hash, uint64_t _prefix) { umutex_class h(mutex); hasher->unlink(*this); @@ -211,7 +213,7 @@ void sha256_future::resolve(unsigned id, const std::string& hash, uint64_t _pref condition.notify_all(); } -void sha256_future::resolve_error(unsigned id, const std::string& err) +void hashval::resolve_error(unsigned id, const std::string& err) { umutex_class h(mutex); hasher->unlink(*this); @@ -223,7 +225,7 @@ void sha256_future::resolve_error(unsigned id, const std::string& err) condition.notify_all(); } -void sha256_hasher::link(sha256_future& future) +void hash::link(hashval& future) { //We assume caller holds global queue lock. { @@ -242,7 +244,7 @@ void sha256_hasher::link(sha256_future& future) first_future = &future; } -void sha256_hasher::unlink(sha256_future& future) +void hash::unlink(hashval& future) { //We assume caller holds global queue lock. { @@ -262,7 +264,7 @@ void sha256_hasher::unlink(sha256_future& future) future.next->prev = future.prev; } -sha256_future sha256_hasher::operator()(const std::string& filename, uint64_t prefixlen) +hashval hash::operator()(const std::string& filename, uint64_t prefixlen) { queue_job j; j.filename = filename; @@ -270,7 +272,7 @@ sha256_future sha256_hasher::operator()(const std::string& filename, uint64_t pr j.size = get_file_size(filename); j.cbid = next_cbid++; j.interested = 1; - sha256_future future(*this, j.cbid); + hashval future(*this, j.cbid); queue.push_back(j); umutex_class h(mutex); total_work += j.size; @@ -279,7 +281,7 @@ sha256_future sha256_hasher::operator()(const std::string& filename, uint64_t pr return future; } -sha256_future sha256_hasher::operator()(const std::string& filename, std::function prefixlen) +hashval hash::operator()(const std::string& filename, std::function prefixlen) { queue_job j; j.filename = filename; @@ -287,7 +289,7 @@ sha256_future sha256_hasher::operator()(const std::string& filename, std::functi j.prefix = prefixlen(j.size); j.cbid = next_cbid++; j.interested = 1; - sha256_future future(*this, j.cbid); + hashval future(*this, j.cbid); queue.push_back(j); umutex_class h(mutex); total_work += j.size; @@ -296,13 +298,13 @@ sha256_future sha256_hasher::operator()(const std::string& filename, std::functi return future; } -void sha256_hasher::set_callback(std::function cb) +void hash::set_callback(std::function cb) { umutex_class h(mutex); progresscb = cb; } -sha256_hasher::sha256_hasher() +hash::hash() { quitting = false; first_future = NULL; @@ -314,7 +316,7 @@ sha256_hasher::sha256_hasher() hash_thread = new thread_class(thread_trampoline, this); } -sha256_hasher::~sha256_hasher() +hash::~hash() { { umutex_class h(mutex); @@ -328,7 +330,7 @@ sha256_hasher::~sha256_hasher() first_future->resolve_error(first_future->cbid, "Hasher deleted"); } -void sha256_hasher::entrypoint() +void hash::entrypoint() { FILE* fp; while(true) { @@ -352,14 +354,14 @@ void sha256_hasher::entrypoint() cached_hash = lookup_cache(current_job->filename, current_job->prefix); if(cached_hash != "") { umutex_class h2(global_queue_mutex()); - for(sha256_future* fut = first_future; fut != NULL; fut = fut->next) + for(hashval* fut = first_future; fut != NULL; fut = fut->next) fut->resolve(current_job->cbid, cached_hash, current_job->prefix); goto finished; } fp = fopen(current_job->filename.c_str(), "rb"); if(!fp) { umutex_class h2(global_queue_mutex()); - for(sha256_future* fut = first_future; fut != NULL; fut = fut->next) + for(hashval* fut = first_future; fut != NULL; fut = fut->next) fut->resolve_error(current_job->cbid, "Can't open file"); } else { sha256 hash; @@ -382,12 +384,12 @@ void sha256_hasher::entrypoint() } if(ferror(fp)) { umutex_class h2(global_queue_mutex()); - for(sha256_future* fut = first_future; fut != NULL; fut = fut->next) + for(hashval* fut = first_future; fut != NULL; fut = fut->next) fut->resolve_error(current_job->cbid, "Can't read file"); } else { std::string hval = hash.read(); umutex_class h2(global_queue_mutex()); - for(sha256_future* fut = first_future; fut != NULL; fut = fut->next) + for(hashval* fut = first_future; fut != NULL; fut = fut->next) fut->resolve(current_job->cbid, hval, current_job->prefix); store_cache(current_job->filename, current_job->prefix, hval); } @@ -404,7 +406,7 @@ finished: } } -void sha256_hasher::send_callback(uint64_t this_completed) +void hash::send_callback(uint64_t this_completed) { uint64_t amount; { @@ -417,28 +419,28 @@ void sha256_hasher::send_callback(uint64_t this_completed) progresscb(amount, work_size); } -void sha256_hasher::send_idle() +void hash::send_idle() { work_size = 0; //Delete work when idle. progresscb(0xFFFFFFFFFFFFFFFFULL, 0); } -loaded_image::loaded_image() throw(std::bad_alloc) +image::image() throw(std::bad_alloc) { type = info::IT_NONE; - sha_256 = sha256_future(""); + sha_256 = hashval(""); filename = ""; } -loaded_image::loaded_image(sha256_hasher& h, const std::string& _filename, const std::string& base, - const struct loaded_image::info& info) throw(std::bad_alloc, std::runtime_error) +image::image(hash& h, const std::string& _filename, const std::string& base, + const struct image::info& info) throw(std::bad_alloc, std::runtime_error) { if(info.type == info::IT_NONE && _filename != "") throw std::runtime_error("Tried to load NULL image"); if(_filename == "") { //NULL. type = info::IT_NONE; - sha_256 = sha256_future(""); + sha_256 = hashval(""); stripped = 0; return; } @@ -472,7 +474,7 @@ loaded_image::loaded_image(sha256_hasher& h, const std::string& _filename, const data->resize(0); } stripped = headered; - sha_256 = sha256_future(sha256::hash(*data), headered); + sha_256 = hashval(sha256::hash(*data), headered); if(info.type == info::IT_MARKUP) { size_t osize = data->size(); data->resize(osize + 1); @@ -493,7 +495,7 @@ loaded_image::loaded_image(sha256_hasher& h, const std::string& _filename, const throw std::runtime_error("Unknown image type"); } -void loaded_image::patch(const std::vector& patch, int32_t offset) throw(std::bad_alloc, std::runtime_error) +void image::patch(const std::vector& patch, int32_t offset) throw(std::bad_alloc, std::runtime_error) { if(type == info::IT_NONE) throw std::runtime_error("Not an image"); @@ -512,7 +514,7 @@ void loaded_image::patch(const std::vector& patch, int32_t offset) throw(s data2[osize] = 0; } data.reset(new std::vector(data2)); - sha_256 = sha256_future(new_sha256); + sha_256 = hashval(new_sha256); } catch(...) { throw; } @@ -523,3 +525,4 @@ std::function std_headersize_fn(uint64_t hdrsize) uint64_t h = hdrsize; return ([h](uint64_t x) -> uint64_t { return calculate_headersize(x, h); }); } +} diff --git a/src/platform/wxwidgets/requestrom.cpp b/src/platform/wxwidgets/requestrom.cpp index d8621a92..c84933d4 100644 --- a/src/platform/wxwidgets/requestrom.cpp +++ b/src/platform/wxwidgets/requestrom.cpp @@ -262,13 +262,13 @@ namespace std::string filename = tostdstring(filenames[i]->GetValue()); if(!zip::file_exists(filename)) { - hashfutures[i] = sha256_future(); + hashfutures[i] = fileimage::hashval(); hash_ready[i] = true; hashes[i]->SetLabel(towxstring("Not found")); return; } //TODO: Handle files inside ZIP files. - hashfutures[i] = lsnes_image_hasher(filename, std_headersize_fn(header)); + hashfutures[i] = lsnes_image_hasher(filename, fileimage::std_headersize_fn(header)); if(hash_ready[i] = hashfutures[i].ready()) try { hashes[i]->SetLabel(towxstring("Hash: " + hashfutures[i].read())); @@ -298,7 +298,7 @@ namespace wxButton* fileselect[ROM_SLOT_COUNT]; wxStaticText* hashes[ROM_SLOT_COUNT]; bool hash_ready[ROM_SLOT_COUNT]; - sha256_future hashfutures[ROM_SLOT_COUNT]; + fileimage::hashval hashfutures[ROM_SLOT_COUNT]; wxButton* okb; wxButton* cancelb; update_timer* timer; @@ -408,7 +408,7 @@ again: goto again; } try { - auto future = lsnes_image_hasher(req.filename[i], std_headersize_fn(header)); + auto future = lsnes_image_hasher(req.filename[i], fileimage::std_headersize_fn(header)); //Dirty method to run the event loop until hashing finishes. while(!future.ready()) { wxSafeYield();