From ba77a66e094b056445bac817a298b12217f41087 Mon Sep 17 00:00:00 2001 From: Atul Bagga Date: Thu, 17 Nov 2022 10:46:00 +0530 Subject: [PATCH] Replace timer impl to not use ConcRT --- .../includes/wascore/timer_handler.h | 34 ++++++++++++++- .../src/timer_handler.cpp | 42 +++++++++++++++---- Microsoft.WindowsAzure.Storage/src/util.cpp | 17 ++++---- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/timer_handler.h b/Microsoft.WindowsAzure.Storage/includes/wascore/timer_handler.h index 32bb96ce..6e3ca5e9 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/timer_handler.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/timer_handler.h @@ -27,10 +27,40 @@ #include #include "pplx/threadpool.h" #else -#include +#include "wascore/basic_types.h" #endif namespace azure { namespace storage { namespace core { + + typedef void(__cdecl * TaskProc)(void *); + + // + // Timer implementation + // + class windows_timer + { + public: + windows_timer(TaskProc userFunc, _In_ void * context); + + ~windows_timer(); + + void start(unsigned int ms, bool repeat); + + void stop(bool waitForCallbacks); + + private: + + static void CALLBACK _TimerCallback(PVOID context, BOOLEAN) + { + auto timer = static_cast(context); + timer->m_userFunc(timer->m_userContext); + } + HANDLE m_hTimer; + + TaskProc m_userFunc; + void * m_userContext; + }; + /// /// Used for internal logic of timer handling, including timer creation, deletion and cancellation /// @@ -80,7 +110,7 @@ namespace azure { namespace storage { namespace core { #ifndef _WIN32 std::shared_ptr> m_timer; #else - std::shared_ptr> m_timer; + std::shared_ptr m_timer; #endif std::atomic m_timer_started; }; diff --git a/Microsoft.WindowsAzure.Storage/src/timer_handler.cpp b/Microsoft.WindowsAzure.Storage/src/timer_handler.cpp index f33d1831..a909437c 100644 --- a/Microsoft.WindowsAzure.Storage/src/timer_handler.cpp +++ b/Microsoft.WindowsAzure.Storage/src/timer_handler.cpp @@ -17,9 +17,37 @@ #include "stdafx.h" #include "wascore/timer_handler.h" +#include + namespace azure { namespace storage { namespace core { + windows_timer::windows_timer(TaskProc userFunc, _In_ void * context) + : m_userFunc(userFunc), m_userContext(context) + { + } + + windows_timer::~windows_timer() + { + } + + void windows_timer::start(unsigned int ms, bool repeat) + { + if (!CreateTimerQueueTimer(&m_hTimer, NULL, _TimerCallback, this, ms, repeat ? ms : 0, WT_EXECUTEDEFAULT)) + { + throw std::bad_alloc(); + } + } + + void windows_timer::stop(bool waitForCallbacks) + { + while (!DeleteTimerQueueTimer(NULL, m_hTimer, waitForCallbacks ? INVALID_HANDLE_VALUE : NULL)) + { + if (GetLastError() == ERROR_IO_PENDING) + break; + } + } + timer_handler::timer_handler(const pplx::cancellation_token& token) : m_cancellation_token(token), m_is_canceled_by_timeout(false), m_timer_started(false) { @@ -71,7 +99,7 @@ namespace azure { namespace storage { namespace core { #ifndef _WIN32 m_timer->cancel(); #else - m_timer->stop(); + m_timer->stop(true); #endif if (!m_tce._IsTriggered()) { @@ -113,11 +141,9 @@ namespace azure { namespace storage { namespace core { pplx::task timer_handler::timeout_after(const std::chrono::milliseconds& time) { // Initialize the timer and connect the callback with completion event. - m_timer = std::make_shared>(static_cast(time.count()), 0); - std::weak_ptr weak_this_pointer = shared_from_this(); - auto callback = std::make_shared>([weak_this_pointer](int) + auto callback = [](LPVOID arg) { - auto this_pointer = weak_this_pointer.lock(); + auto this_pointer = static_cast (arg); if (this_pointer) { std::lock_guard guard(this_pointer->m_mutex); @@ -126,9 +152,9 @@ namespace azure { namespace storage { namespace core { this_pointer->m_tce.set(); } } - }); - m_timer->link_target(callback.get()); // When timer stops, tce will trigger cancellation. - m_timer->start(); + }; + m_timer = std::make_shared(callback, this); + m_timer->start(static_cast(time.count()), false); auto event_set = pplx::create_task(m_tce); diff --git a/Microsoft.WindowsAzure.Storage/src/util.cpp b/Microsoft.WindowsAzure.Storage/src/util.cpp index cf0a3116..d5597092 100644 --- a/Microsoft.WindowsAzure.Storage/src/util.cpp +++ b/Microsoft.WindowsAzure.Storage/src/util.cpp @@ -22,11 +22,13 @@ #include "wascore/resources.h" #ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif #include #include #include -#include +#include "wascore/timer_handler.h" #else #include "pplx/threadpool.h" #include @@ -334,8 +336,8 @@ namespace azure { namespace storage { namespace core { utility::string_t str_trim_starting_trailing_whitespaces(const utility::string_t& str) { - auto non_space_begin = std::find_if(str.begin(), str.end(), std::not1(std::ptr_fun(isspace))); - auto non_space_end = std::find_if(str.rbegin(), str.rend(), std::not1(std::ptr_fun(isspace))).base(); + auto non_space_begin = std::find_if(str.begin(), str.end(), [](int c) {return !::isspace(c); }); + auto non_space_end = std::find_if(str.rbegin(), str.rend(), [](int c) {return !::isspace(c); }).base(); return utility::string_t(non_space_begin, non_space_end); } @@ -356,14 +358,14 @@ namespace azure { namespace storage { namespace core { public: #ifdef _WIN32 delay_event(std::chrono::milliseconds timeout) - : m_callback(new concurrency::call(std::function(std::bind(&delay_event::timer_fired, this, std::placeholders::_1)))), m_timer(static_cast(timeout.count()), 0, m_callback, false), + : m_timer([](void* event) { reinterpret_cast(event)->timer_fired(0); }, this), m_timeout(timeout) { } ~delay_event() { - delete m_callback; + m_timer.stop(true); } void start() @@ -378,7 +380,7 @@ namespace azure { namespace storage { namespace core { } else { - m_timer.start(); + m_timer.start(static_cast(m_timeout.count()), false); } } #else @@ -400,8 +402,7 @@ namespace azure { namespace storage { namespace core { private: pplx::task_completion_event m_completion_event; #ifdef _WIN32 - concurrency::call* m_callback; - concurrency::timer m_timer; + windows_timer m_timer; std::chrono::milliseconds m_timeout; #else boost::asio::deadline_timer m_timer;