Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace timer impl to not use ConcRT #416

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions Microsoft.WindowsAzure.Storage/includes/wascore/timer_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,40 @@
#include <boost/asio/basic_waitable_timer.hpp>
#include "pplx/threadpool.h"
#else
#include <agents.h>
#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<windows_timer *>(context);
timer->m_userFunc(timer->m_userContext);
}
HANDLE m_hTimer;

TaskProc m_userFunc;
void * m_userContext;
};

/// <summary>
/// Used for internal logic of timer handling, including timer creation, deletion and cancellation
/// </summary>
Expand Down Expand Up @@ -80,7 +110,7 @@ namespace azure { namespace storage { namespace core {
#ifndef _WIN32
std::shared_ptr<boost::asio::basic_waitable_timer<std::chrono::steady_clock>> m_timer;
#else
std::shared_ptr<concurrency::timer<int>> m_timer;
std::shared_ptr<windows_timer> m_timer;
#endif
std::atomic<bool> m_timer_started;
};
Expand Down
42 changes: 34 additions & 8 deletions Microsoft.WindowsAzure.Storage/src/timer_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,37 @@

#include "stdafx.h"
#include "wascore/timer_handler.h"
#include <Threadpoollegacyapiset.h>


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)
{
Expand Down Expand Up @@ -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())
{
Expand Down Expand Up @@ -113,11 +141,9 @@ namespace azure { namespace storage { namespace core {
pplx::task<void> timer_handler::timeout_after(const std::chrono::milliseconds& time)
{
// Initialize the timer and connect the callback with completion event.
m_timer = std::make_shared<concurrency::timer<int>>(static_cast<unsigned int>(time.count()), 0);
std::weak_ptr<timer_handler> weak_this_pointer = shared_from_this();
auto callback = std::make_shared<concurrency::call<int>>([weak_this_pointer](int)
auto callback = [](LPVOID arg)
{
auto this_pointer = weak_this_pointer.lock();
auto this_pointer = static_cast<timer_handler *> (arg);
if (this_pointer)
{
std::lock_guard<std::mutex> guard(this_pointer->m_mutex);
Expand All @@ -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<windows_timer>(callback, this);
m_timer->start(static_cast<unsigned int>(time.count()), false);

auto event_set = pplx::create_task(m_tce);

Expand Down
17 changes: 9 additions & 8 deletions Microsoft.WindowsAzure.Storage/src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
#include "wascore/resources.h"

#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <float.h>
#include <windows.h>
#include <rpc.h>
#include <agents.h>
#include "wascore/timer_handler.h"
#else
#include "pplx/threadpool.h"
#include <chrono>
Expand Down Expand Up @@ -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<int, int>(isspace)));
auto non_space_end = std::find_if(str.rbegin(), str.rend(), std::not1(std::ptr_fun<int, int>(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);
}

Expand All @@ -356,14 +358,14 @@ namespace azure { namespace storage { namespace core {
public:
#ifdef _WIN32
delay_event(std::chrono::milliseconds timeout)
: m_callback(new concurrency::call<int>(std::function<void(int)>(std::bind(&delay_event::timer_fired, this, std::placeholders::_1)))), m_timer(static_cast<unsigned int>(timeout.count()), 0, m_callback, false),
: m_timer([](void* event) { reinterpret_cast<delay_event*>(event)->timer_fired(0); }, this),
m_timeout(timeout)
{
}

~delay_event()
{
delete m_callback;
m_timer.stop(true);
}

void start()
Expand All @@ -378,7 +380,7 @@ namespace azure { namespace storage { namespace core {
}
else
{
m_timer.start();
m_timer.start(static_cast<unsigned int>(m_timeout.count()), false);
}
}
#else
Expand All @@ -400,8 +402,7 @@ namespace azure { namespace storage { namespace core {
private:
pplx::task_completion_event<void> m_completion_event;
#ifdef _WIN32
concurrency::call<int>* m_callback;
concurrency::timer<int> m_timer;
windows_timer m_timer;
std::chrono::milliseconds m_timeout;
#else
boost::asio::deadline_timer m_timer;
Expand Down