Skip to content

Instantly share code, notes, and snippets.

@ribtoks
Created September 29, 2016 11:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ribtoks/6bc894e20946073317a339ba17a06464 to your computer and use it in GitHub Desktop.
Save ribtoks/6bc894e20946073317a339ba17a06464 to your computer and use it in GitHub Desktop.
exiv2 threading crash test
#include <iostream>
#include <thread>
#include <windows.h>
#include <vector>
#include <string>
#include <algorithm>
#include <mutex>
#include <chrono>
#include <condition_variable>
#include "../xpiks/src/exiv2-0.25/include/exiv2/exiv2.hpp"
std::mutex coutLock;
void log(const std::string &s) {
std::lock_guard<std::mutex> guard(coutLock);
std::cout << s << std::endl;
}
std::vector<std::string> getAllJpgsInDir(const std::string &folder) {
std::vector<std::string> names;
std::string search_path = folder + "/*.jpg";
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
if (hFind != INVALID_HANDLE_VALUE) {
do {
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
std::string filename = fd.cFileName;
names.push_back(folder + '\\' + filename);
}
} while(::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
class Barrier
{
public:
explicit Barrier(std::size_t count) : _count{count} { }
void wait()
{
std::unique_lock<std::mutex> lock{_mutex};
if (--_count == 0) {
_cv.notify_all();
} else {
_cv.wait(lock, [this] { return _count == 0; });
}
}
private:
std::mutex _mutex;
std::condition_variable _cv;
std::size_t _count;
};
#define BUFSIZE 4096
int main(int argc, char *argv[]) {
if (argc < 2) {
std::cerr << "Directory is not specified" << std::endl;
return 1;
}
std::string directory = argv[1];
char buffer[BUFSIZE];
char **lppPart = nullptr;
DWORD success = GetFullPathName(argv[1], BUFSIZE, buffer, lppPart);
directory = std::string(buffer);
log("Looking for images in " + directory);
std::vector<std::string> filenames = getAllJpgsInDir(directory);
Exiv2::XmpParser::initialize();
std::vector<std::thread> processors;
size_t count = filenames.size();
log("Found " + std::to_string(count) + " images");
log("Starting threads...");
Barrier barrier(count);
for (size_t i = 0; i < count; ++i) {
std::string filepath = filenames[i];
processors.push_back(std::thread([i, filepath, &barrier]() {
log("Processing image " + filepath);
log("Thread " + std::to_string(i) + " waiting on barrier...");
barrier.wait();
std::this_thread::sleep_for(std::chrono::milliseconds(i));
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filepath);
image->readMetadata();
Exiv2::XmpData &xmpData = image->xmpData();
Exiv2::ExifData &exifData = image->exifData();
Exiv2::IptcData &iptcData = image->iptcData();
std::this_thread::sleep_for(std::chrono::seconds(1));
}));
}
log("Threads started. Waiting for join...");
std::for_each(processors.begin(), processors.end(), [](std::thread &t) {
t.join();
});
Exiv2::XmpParser::terminate();
return 0;
}
EXIV2_INCLUDEPATH =../xpiks/src/exiv2-0.25/include
DEFINES =
CXXFLAGS = $(DEFINES) -Zi -MDd -EHa
INCPATH = -I. -I$(EXIV2_INCLUDEPATH)
SOURCES = main.cpp
OBJDEPS = libexiv2.lib libexpat.lib
LINKFLAGS =
.PHONY: debug
debug: test_exiv2
test_exiv2: $(SOURCES) $(OBJDEPS) $(INCDEPS)
$(CXX) -o test_exiv2 $(SOURCES) $(OBJDEPS) $(INCPATH) $(CXXFLAGS) $(LINKFLAGS)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment