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

Delete open() from _http_client_communicator #819

Merged
merged 2 commits into from
Aug 1, 2018
Merged
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
67 changes: 17 additions & 50 deletions Release/src/http/client/http_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ request_context::request_context(const std::shared_ptr<_http_client_communicator
responseImpl->_prepare_to_receive_data();
}

void _http_client_communicator::open_and_send_request_async(const std::shared_ptr<request_context> &request)
void _http_client_communicator::async_send_request_impl(const std::shared_ptr<request_context> &request)
{
auto self = std::static_pointer_cast<_http_client_communicator>(this->shared_from_this());
// Schedule a task to start sending.
pplx::create_task([self, request]
{
try
{
self->open_and_send_request(request);
self->send_request(request);
}
catch (...)
{
Expand All @@ -150,20 +150,21 @@ void _http_client_communicator::async_send_request(const std::shared_ptr<request
{
if (m_client_config.guarantee_order())
{
pplx::extensibility::scoped_critical_section_t l(m_open_lock);
pplx::extensibility::scoped_critical_section_t l(m_client_lock);

if (++m_scheduled == 1)
if (m_outstanding)
{
open_and_send_request_async(request);
m_requests_queue.push(request);
}
else
{
m_requests_queue.push(request);
async_send_request_impl(request);
m_outstanding = true;
}
}
else
{
open_and_send_request_async(request);
async_send_request_impl(request);
}
}

Expand All @@ -172,16 +173,18 @@ void _http_client_communicator::finish_request()
// If guarantee order is specified we don't need to do anything.
if (m_client_config.guarantee_order())
{
pplx::extensibility::scoped_critical_section_t l(m_open_lock);

--m_scheduled;
pplx::extensibility::scoped_critical_section_t l(m_client_lock);

if (!m_requests_queue.empty())
if (m_requests_queue.empty())
{
m_outstanding = false;
}
else
{
auto request = m_requests_queue.front();
m_requests_queue.pop();

open_and_send_request_async(request);
async_send_request_impl(request);
}
}
}
Expand All @@ -197,46 +200,10 @@ const uri & _http_client_communicator::base_uri() const
}

_http_client_communicator::_http_client_communicator(http::uri&& address, http_client_config&& client_config)
: m_uri(std::move(address)), m_client_config(std::move(client_config)), m_opened(false), m_scheduled(0)
: m_uri(std::move(address)), m_client_config(std::move(client_config)), m_outstanding(false)
{
}

// Wraps opening the client around sending a request.
void _http_client_communicator::open_and_send_request(const std::shared_ptr<request_context> &request)
{
// First see if client needs to be opened.
unsigned long error = 0;

if (!m_opened)
{
pplx::extensibility::scoped_critical_section_t l(m_open_lock);

// Check again with the lock held
if (!m_opened)
{
error = open();

if (error == 0)
{
m_opened = true;
}
}
}

if (error != 0)
{
// Failed to open
request->report_error(error, _XPLATSTR("Open failed"));

// DO NOT TOUCH the this pointer after completing the request
// This object could be freed along with the request as it could
// be the last reference to this object
return;
}

send_request(request);
}

inline void request_context::finish()
{
// If cancellation is enabled and registration was performed, unregister.
Expand Down Expand Up @@ -399,4 +366,4 @@ pplx::task<http_response> http_client::request(http_request request, const pplx:
}


}}}
}}}
2 changes: 0 additions & 2 deletions Release/src/http/client/http_client_asio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,6 @@ class asio_client final : public _http_client_communicator

void send_request(const std::shared_ptr<request_context> &request_ctx) override;

unsigned long open() override { return 0; }

void release_connection(std::shared_ptr<asio_connection>& conn)
{
m_pool->release(conn);
Expand Down
15 changes: 4 additions & 11 deletions Release/src/http/client/http_client_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,35 +117,28 @@ class _http_client_communicator : public http_pipeline_stage
protected:
_http_client_communicator(http::uri&& address, http_client_config&& client_config);

// Method to open client.
virtual unsigned long open() = 0;

// HTTP client implementations must implement send_request.
virtual void send_request(_In_ const std::shared_ptr<request_context> &request) = 0;

// URI to connect to.
const http::uri m_uri;

pplx::extensibility::critical_section_t m_client_lock;
private:

http_client_config m_client_config;

std::atomic<bool> m_opened;

pplx::extensibility::critical_section_t m_open_lock;

// Wraps opening the client around sending a request.
void open_and_send_request_async(const std::shared_ptr<request_context> &request);
void open_and_send_request(const std::shared_ptr<request_context> &request);
void async_send_request_impl(const std::shared_ptr<request_context> &request);

// Queue used to guarantee ordering of requests, when applicable.
std::queue<std::shared_ptr<request_context>> m_requests_queue;
int m_scheduled;
bool m_outstanding;
};

/// <summary>
/// Factory function implemented by the separate platforms to construct their subclasses of _http_client_communicator
/// </summary>
std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config);

}}}}
}}}}
31 changes: 29 additions & 2 deletions Release/src/http/client/http_client_winhttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
****/
#include "stdafx.h"

#include <atomic>

#include "cpprest/http_headers.h"
#include "http_client_impl.h"

Expand Down Expand Up @@ -351,6 +353,7 @@ class winhttp_client : public _http_client_communicator
winhttp_client(http::uri address, http_client_config client_config)
: _http_client_communicator(std::move(address), std::move(client_config))
, m_secure(m_uri.scheme() == _XPLATSTR("https"))
, m_opened(false)
, m_hSession(nullptr)
, m_hConnection(nullptr) { }

Expand Down Expand Up @@ -403,8 +406,19 @@ class winhttp_client : public _http_client_communicator
}

// Open session and connection with the server.
virtual unsigned long open() override
unsigned long open()
{
if (m_opened)
{
return 0;
}

pplx::extensibility::scoped_critical_section_t l(m_client_lock);
if (m_opened)
{
return 0;
}

// This object have lifetime greater than proxy_name and proxy_bypass
// which may point to its elements.
ie_proxy_config proxyIE;
Expand Down Expand Up @@ -575,12 +589,24 @@ class winhttp_client : public _http_client_communicator
return report_failure(_XPLATSTR("Error opening connection"));
}

m_opened = true;
return S_OK;
}

// Start sending request.
void send_request(_In_ const std::shared_ptr<request_context> &request)
{
// First see if we need to be opened.
unsigned long error = open();
if (error != 0)
{
// DO NOT TOUCH the this pointer after completing the request
// This object could be freed along with the request as it could
// be the last reference to this object
request->report_error(error, _XPLATSTR("Open failed"));
return;
}

http_request &msg = request->m_request;
std::shared_ptr<winhttp_request_context> winhttp_context = std::static_pointer_cast<winhttp_request_context>(request);
std::weak_ptr<winhttp_request_context> weak_winhttp_context = winhttp_context;
Expand Down Expand Up @@ -1546,6 +1572,8 @@ class winhttp_client : public _http_client_communicator
}
}

std::atomic<bool> m_opened;

// WinHTTP session and connection
HINTERNET m_hSession;
HINTERNET m_hConnection;
Expand All @@ -1564,4 +1592,3 @@ std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(
}

}}}}

6 changes: 0 additions & 6 deletions Release/src/http/client/http_client_winrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,6 @@ class winrt_client : public _http_client_communicator

protected:

// Method to open client.
unsigned long open()
{
return 0;
}

// Start sending request.
void send_request(_In_ const std::shared_ptr<request_context> &request)
{
Expand Down