Created
August 30, 2019 09:40
-
-
Save kbridge/251808f0cb7411782c3a2ce5f4877287 to your computer and use it in GitHub Desktop.
spdlog periodic_worker workaround for MSVC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. | |
// Distributed under the MIT License (http://opensource.org/licenses/MIT) | |
#pragma once | |
#ifndef SPDLOG_HEADER_ONLY | |
#include "spdlog/details/periodic_worker.h" | |
#endif | |
namespace spdlog { | |
namespace details { | |
SPDLOG_INLINE periodic_worker::periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval) | |
{ | |
#ifdef _WIN32 | |
::InitializeCriticalSection(&cs_); | |
::InitializeConditionVariable(&cv_); | |
#endif | |
active_ = (interval > std::chrono::seconds::zero()); | |
if (!active_) | |
{ | |
return; | |
} | |
worker_thread_ = std::thread([this, callback_fun, interval]() { | |
for (;;) | |
{ | |
#ifdef _WIN32 | |
::EnterCriticalSection(&cs_); | |
if (!active_) | |
{ | |
::LeaveCriticalSection(&cs_); | |
return; | |
} | |
else | |
{ | |
SleepConditionVariableCS(&cv_, &cs_, static_cast<DWORD>(interval.count()) * 1000); | |
if (!active_) | |
{ | |
::LeaveCriticalSection(&cs_); | |
return; | |
} | |
// TODO if not timed-out, sleep more | |
} | |
callback_fun(); | |
::LeaveCriticalSection(&cs_); | |
#else | |
std::unique_lock<std::mutex> lock(this->mutex_); | |
if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) | |
{ | |
return; // active_ == false, so exit this thread | |
} | |
callback_fun(); | |
#endif | |
} | |
}); | |
} | |
// stop the worker thread and join it | |
SPDLOG_INLINE periodic_worker::~periodic_worker() | |
{ | |
if (worker_thread_.joinable()) | |
{ | |
#ifdef _WIN32 | |
{ | |
::EnterCriticalSection(&cs_); | |
active_ = false; | |
::LeaveCriticalSection(&cs_); | |
} | |
WakeConditionVariable(&cv_); | |
#else | |
{ | |
std::lock_guard<std::mutex> lock(mutex_); | |
active_ = false; | |
} | |
cv_.notify_one(); | |
#endif | |
worker_thread_.join(); | |
} | |
#ifdef _WIN32 | |
::DeleteCriticalSection(&cs_); | |
#endif | |
} | |
} // namespace details | |
} // namespace spdlog |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. | |
// Distributed under the MIT License (http://opensource.org/licenses/MIT) | |
#pragma once | |
// periodic worker thread - periodically executes the given callback function. | |
// | |
// RAII over the owned thread: | |
// creates the thread on construction. | |
// stops and joins the thread on destruction (if the thread is executing a callback, wait for it to finish first). | |
#include <chrono> | |
#include <condition_variable> | |
#include <functional> | |
#include <mutex> | |
#include <thread> | |
namespace spdlog { | |
namespace details { | |
class periodic_worker | |
{ | |
public: | |
periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval); | |
periodic_worker(const periodic_worker &) = delete; | |
periodic_worker &operator=(const periodic_worker &) = delete; | |
// stop the worker thread and join it | |
~periodic_worker(); | |
private: | |
bool active_; | |
std::thread worker_thread_; | |
#ifdef _WIN32 | |
CRITICAL_SECTION cs_; | |
CONDITION_VARIABLE cv_; | |
#else | |
std::mutex mutex_; | |
std::condition_variable cv_; | |
#endif | |
}; | |
} // namespace details | |
} // namespace spdlog | |
#ifdef SPDLOG_HEADER_ONLY | |
#include "periodic_worker-inl.h" | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment