I have a rather basic problem and not sure where it originates from: lambda capture evaluation in a concurrent environment or misuse of boost filesystem library.
This is sample code:
#include <iostream>
#include <vector>
#include <thread>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
void query(const string filename)
{
cout << filename << " ";
}
int main() {
path p("./");
vector<thread> thrs;
for(auto file = directory_iterator(p); file != directory_iterator(); ++file)
{
thread th( [file] {query(file->path().string());} );
thrs.push_back(move(th));
}
for (auto& t : thrs)
t.join();
return 0;
}
which at runtime gives:
:~/workspace/sandbox/Release$ l
main.o makefile objects.mk sandbox* sources.mk subdir.mk
:~/workspace/sandbox/Release$ LD_LIBRARY_PATH=$http://LD_LIBRARY_PATH:/home/a/custom-libs/boost-1_59/lib/ ./sandbox
./subdir.mk ./sources.mk ./sandbox ./objects.mk ./main.o ./main.o
Notice the race condition - not all files end up being passed to thread function (at this run makefile is missing).
I am able to find a workaround by extracting the argument in a local var, rewriting the loop body as:
auto fn = file->path().string();
thread th( [fn] {query(fn);} );
thrs.push_back(move(th));
Where is the race condition coming from?
Isn't file->path().string() evaluated right at the time of thread creation?
Aucun commentaire:
Enregistrer un commentaire