/* simple tool for a parallel search of a simple string within a file */ #include #include #include #include #include #include #include "engine.hpp" #include "mapped_file.hpp" int main(int argc, char** argv) { const char* cmdname = *argv++; --argc; if (argc != 3) { std::cerr << "Usage: " << cmdname << " nthreads regex file" << std::endl; exit(1); } const char* nthreads = *argv++; --argc; const char* regex = *argv++; --argc; if (*regex == 0) { std::cerr << cmdname << ": empty regular expression given" << std::endl; exit(1); } std::regex re(regex); const char* filename = *argv++; --argc; std::istringstream is(nthreads); unsigned int nofthreads; if (!(is >> nofthreads) || nofthreads == 0) { std::cerr << cmdname << ": bad value for nthreads" << std::endl; exit(1); } MappedFile mf(filename); if (!mf.valid()) { std::cerr << cmdname << ": " << filename << ": " << strerror(mf.get_errno()) << std::endl; exit(1); } const char* addr = mf.get_addr(); size_t len = mf.get_length(); if (nofthreads >= len) { nofthreads = 1; } std::vector tstart(nofthreads); std::vector tlen(nofthreads); const char* start = addr; for (unsigned int i = 0; i < nofthreads; ++i) { tstart[i] = start; if (i == nofthreads - 1) { tlen[i] = len - (start - addr); /* take the rest */ } else { const char* cp = start + (addr + len - start) / (nofthreads - i); /* find next line terminator */ while (cp < addr + len && *cp != '\n') ++cp; if (cp < addr) ++cp; /* skip line terminator */ tlen[i] = cp - start; start = cp; if (cp == addr + len) { /* we need less threads */ nofthreads = i + 1; break; } } } /* fork... */ std::vector engines(nofthreads); std::vector threads(nofthreads); for (unsigned int tid = 0; tid < nofthreads; ++tid) { const char* addr = tstart[tid]; size_t len = tlen[tid]; threads[tid] = std::thread([=,&engines]() { Engine& engine(engines[tid]); engine.configure(addr, len); engine.search(re); }); } /* ...and join */ for (auto& t: threads) { t.join(); } /* print results */ size_t lines = 0; for (auto& engine: engines) { auto results = engine.fetch_results(); for (auto& result: results) { std::size_t line = lines + result.rline_no; std::cout << line << ": "; std::cout.write(result.line, result.len); std::cout << std::endl; } lines += engine.get_number_of_lines(); } }