diff --git a/pywikidiff2/pywikidiff2.cpp b/pywikidiff2/pywikidiff2.cpp index 3b87f14..a46acc2 100644 --- a/pywikidiff2/pywikidiff2.cpp +++ b/pywikidiff2/pywikidiff2.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "structmember.h" #undef HAVE_CONFIG_H // this disables the php allocator #include "../mediawiki-php-wikidiff2/src/lib/Wikidiff2.h" @@ -118,11 +120,18 @@ static Wikidiff2::String wikidiff2_inline_json_diff(pywikidiff2Obj *self, char* self->config.cancelFlag = &cancelFlag; self->timed_out = false; + std::mutex timerMutex; + std::condition_variable timerCv; + bool diffDone = false; + std::thread timerThread; if (timeout_ms > 0) { - timerThread = std::thread([&cancelFlag, timeout_ms]() { - std::this_thread::sleep_for(std::chrono::milliseconds(timeout_ms)); - cancelFlag.store(true, std::memory_order_relaxed); + timerThread = std::thread([&cancelFlag, &timerMutex, &timerCv, &diffDone, timeout_ms]() { + std::unique_lock lock(timerMutex); + if (!timerCv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&diffDone]{ return diffDone; })) { + // Timeout expired before diff finished + cancelFlag.store(true, std::memory_order_relaxed); + } }); } @@ -140,8 +149,13 @@ static Wikidiff2::String wikidiff2_inline_json_diff(pywikidiff2Obj *self, char* // Check if we timed out before stopping the timer thread self->timed_out = cancelFlag.load(std::memory_order_relaxed); + // Signal timer thread to exit and wait for it if (timerThread.joinable()) { - cancelFlag.store(true, std::memory_order_relaxed); // Stop timer if still waiting + { + std::lock_guard lock(timerMutex); + diffDone = true; + } + timerCv.notify_one(); timerThread.join(); }