Added support for AsyncRequests in cHttp.

Added cThreadLocal and tThreadLocalPtr ( needed for the async requests ).
This commit is contained in:
Martín Lucas Golini
2013-09-30 02:04:06 -03:00
parent aeb6dd4f07
commit cff7eb600f
23 changed files with 515 additions and 52 deletions

View File

@@ -53,6 +53,10 @@ void cHttp::Request::SetBody(const std::string& body) {
mBody = body;
}
const std::string &cHttp::Request::GetUri() const {
return mUri;
}
std::string cHttp::Request::Prepare() const {
std::ostringstream out;
@@ -219,15 +223,36 @@ void cHttp::Response::Parse(const std::string& data) {
}
cHttp::cHttp() :
mConnection( NULL ),
mHost(),
mPort(0)
{
}
cHttp::cHttp(const std::string& host, unsigned short port) {
cHttp::cHttp(const std::string& host, unsigned short port) :
mConnection( NULL )
{
SetHost(host, port);
}
cHttp::~cHttp() {
std::list<cAsyncRequest*>::iterator itt;
// First we wait to finish any request pending
for ( itt = mThreads.begin(); itt != mThreads.end(); itt++ ) {
(*itt)->Wait();
}
for ( itt = mThreads.begin(); itt != mThreads.end(); itt++ ) {
eeDelete( *itt );
}
// Then we destroy the last open connection
cTcpSocket * tcp = mConnection;
eeSAFE_DELETE( tcp );
}
void cHttp::SetHost(const std::string& host, unsigned short port) {
// Check the protocol
if (toLower(host.substr(0, 7)) == "http://") {
@@ -253,6 +278,11 @@ void cHttp::SetHost(const std::string& host, unsigned short port) {
}
cHttp::Response cHttp::SendRequest(const cHttp::Request& request, cTime timeout) {
if ( NULL == mConnection ) {
cTcpSocket * Conn = eeNew( cTcpSocket, () );
mConnection = Conn;
}
// First make sure that the request is valid -- add missing mandatory fields
Request toSend(request);
@@ -286,19 +316,19 @@ cHttp::Response cHttp::SendRequest(const cHttp::Request& request, cTime timeout)
Response received;
// Connect the socket to the host
if (mConnection.Connect(mHost, mPort, timeout) == cSocket::Done) {
if (mConnection->Connect(mHost, mPort, timeout) == cSocket::Done) {
// Convert the request to string and send it through the connected socket
std::string requestStr = toSend.Prepare();
if (!requestStr.empty()) {
// Send it through the socket
if (mConnection.Send(requestStr.c_str(), requestStr.size()) == cSocket::Done) {
if (mConnection->Send(requestStr.c_str(), requestStr.size()) == cSocket::Done) {
// Wait for the server's response
std::string receivedStr;
std::size_t size = 0;
char buffer[1024];
while (mConnection.Receive(buffer, sizeof(buffer), size) == cSocket::Done) {
while (mConnection->Receive(buffer, sizeof(buffer), size) == cSocket::Done) {
receivedStr.append(buffer, buffer + size);
}
@@ -308,10 +338,80 @@ cHttp::Response cHttp::SendRequest(const cHttp::Request& request, cTime timeout)
}
// Close the connection
mConnection.Disconnect();
mConnection->Disconnect();
}
return received;
}
cHttp::cAsyncRequest::cAsyncRequest(cHttp *http, AsyncResponseCallback cb, cHttp::Request request, cTime timeout) :
mHttp( http ),
mCb( cb ),
mRequest( request ),
mTimeout( timeout ),
mRunning( true )
{
}
void cHttp::cAsyncRequest::Run() {
cHttp::Response response = mHttp->SendRequest( mRequest, mTimeout );
mCb( *mHttp, mRequest, response );
// The Async Request destroys the socket used to create the request
cTcpSocket * tcp = mHttp->mConnection;
eeSAFE_DELETE( tcp );
mHttp->mConnection = NULL;
mRunning = false;
}
void cHttp::RemoveOldThreads() {
std::list<cAsyncRequest*> remove;
std::list<cAsyncRequest*>::iterator it = mThreads.begin();
for ( ; it != mThreads.end(); it++ ) {
cAsyncRequest * ar = (*it);
if ( !ar->mRunning ) {
// We need to be sure, since the state is set in the thread, this will not block the thread anyway
ar->Wait();
eeDelete( ar );
remove.push_back( ar );
}
}
for ( it = remove.begin(); it != remove.end(); it++ ) {
mThreads.remove( (*it) );
}
}
void cHttp::SendAsyncRequest( AsyncResponseCallback cb, const cHttp::Request& request, cTime timeout ) {
cAsyncRequest * thread = eeNew( cAsyncRequest, ( this, cb, request, timeout ) );
thread->Launch();
// Clean old threads
cLock l( mThreadsMutex );
RemoveOldThreads();
mThreads.push_back( thread );
}
const cIpAddress &cHttp::GetHost() const {
return mHost;
}
const std::string &cHttp::GetHostName() const {
return mHostName;
}
const unsigned short& cHttp::GetPort() const {
return mPort;
}
}}

View File

@@ -0,0 +1,24 @@
#include <eepp/system/cthreadlocal.hpp>
#include <eepp/system/platform/platformimpl.hpp>
namespace EE { namespace System {
cThreadLocal::cThreadLocal(void* value) :
mImpl( eeNew( Private::cThreadLocalImpl, () ) )
{
Value( value );
}
cThreadLocal::~cThreadLocal() {
eeSAFE_DELETE( mImpl );
}
void cThreadLocal::Value(void* value) {
mImpl->Value(value);
}
void* cThreadLocal::Value() const {
return mImpl->Value();
}
}}

View File

@@ -8,13 +8,15 @@
#include <eepp/system/platform/posix/cmuteximpl.hpp>
#include <eepp/system/platform/posix/cclockimpl.hpp>
#include <eepp/system/platform/posix/cconditionimpl.hpp>
#include <eepp/system/platform/posix/cthreadlocalimpl.hpp>
#elif EE_PLATFORM == EE_PLATFORM_WIN
#include <eepp/system/platform/win/cthreadimpl.hpp>
#include <eepp/system/platform/win/cmuteximpl.hpp>
#include <eepp/system/platform/win/cclockimpl.hpp>
#include <eepp/system/platform/win/cconditionimpl.hpp>
#include <eepp/system/platform/win/cthreadlocalimpl.hpp>
#else
#error Threads, mutexes, conditions and timers not implemented for this platform.
#error Threads, mutexes, conditions, timers and thread local storage not implemented for this platform.
#endif
#endif

View File

@@ -0,0 +1,25 @@
#include <eepp/system/platform/posix/cthreadlocalimpl.hpp>
#if defined( EE_PLATFORM_POSIX )
namespace EE { namespace System { namespace Private {
cThreadLocalImpl::cThreadLocalImpl() {
pthread_key_create(&mKey, NULL);
}
cThreadLocalImpl::~cThreadLocalImpl() {
pthread_key_delete(mKey);
}
void cThreadLocalImpl::Value(void* value) {
pthread_setspecific(mKey, value);
}
void* cThreadLocalImpl::Value() const {
return pthread_getspecific(mKey);
}
}}}
#endif

View File

@@ -0,0 +1,31 @@
#ifndef EE_SYSTEMCTHREADLOCALIMPLPOSIX_HPP
#define EE_SYSTEMCTHREADLOCALIMPLPOSIX_HPP
#include <eepp/base.hpp>
#include <eepp/base/noncopyable.hpp>
#if defined( EE_PLATFORM_POSIX )
#include <pthread.h>
namespace EE { namespace System { namespace Private {
class cThreadLocalImpl : NonCopyable {
public:
cThreadLocalImpl();
~cThreadLocalImpl();
void Value(void* value);
void* Value() const;
private :
pthread_key_t mKey;
};
}}}
#endif
#endif

View File

@@ -0,0 +1,25 @@
#include <eepp/system/platform/win/cthreadlocalimpl.hpp>
#if EE_PLATFORM == EE_PLATFORM_WIN
namespace EE { namespace System { namespace Private {
cThreadLocalImpl::cThreadLocalImpl() {
mIndex = TlsAlloc();
}
cThreadLocalImpl::~cThreadLocalImpl() {
TlsFree(mIndex);
}
void cThreadLocalImpl::Value(void* value) {
TlsSetValue(mIndex, value);
}
void* cThreadLocalImpl::Value() const {
return TlsGetValue(mIndex);
}
}}}
#endif

View File

@@ -0,0 +1,30 @@
#ifndef EE_SYSTEMCTHREADLOCALIMPLWIN_HPP
#define EE_SYSTEMCTHREADLOCALIMPLWIN_HPP
#include <eepp/base.hpp>
#include <eepp/base/noncopyable.hpp>
#if EE_PLATFORM == EE_PLATFORM_WIN
#include <windows.h>
namespace EE { namespace System { namespace Private {
class cThreadLocalImpl : NonCopyable {
public:
cThreadLocalImpl();
~cThreadLocalImpl();
void Value(void* value);
void* Value() const;
private :
DWORD mIndex;
};
}}}
#endif
#endif

View File

@@ -42,7 +42,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
cEngine::DestroySingleton();
// If was compiled in debug mode it will print the memory manager report
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -271,7 +271,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
cEngine::DestroySingleton();
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -118,7 +118,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
cEngine::DestroySingleton();
// If was compiled in debug mode it will print the memory manager report
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -1,28 +1,44 @@
#include <eepp/ee.hpp>
/// Entry point of application
EE_MAIN_FUNC int main (int argc, char * argv [])
{
// Create a new HTTP client
cHttp http;
void AsyncRequestCallback( const cHttp& http, cHttp::Request& request, cHttp::Response& response ) {
std::cout << "Got response from request: " << http.GetHostName() << request.GetUri() << std::endl;
// We'll work on http://www.wikipedia.org
http.SetHost("http://www.wikipedia.org");
// Prepare a request to get the '/' page
cHttp::Request request("/");
// Send the request
cHttp::Response response = http.SendRequest(request);
// Check the status code and display the result
cHttp::Response::Status status = response.GetStatus();
if ( status == cHttp::Response::Ok ) {
if ( response.GetStatus() == cHttp::Response::Ok ) {
std::cout << response.GetBody() << std::endl;
} else {
std::cout << "Error " << status << std::endl;
std::cout << "Error " << response.GetStatus() << std::endl;
}
}
EE_MAIN_FUNC int main (int argc, char * argv []) {
{
// Create a new HTTP client
cHttp http;
// We'll work on http://en.wikipedia.org
http.SetHost("http://en.wikipedia.org");
// Prepare a request to get the '/' page
cHttp::Request request("/wiki/Main_Page");
// Send the request
cHttp::Response response = http.SendRequest(request);
// Check the status code and display the result
cHttp::Response::Status status = response.GetStatus();
if ( status == cHttp::Response::Ok ) {
std::cout << response.GetBody() << std::endl;
} else {
std::cout << "Error " << status << std::endl;
}
cHttp::Request asyncRequest( "/wiki/" + Version::GetCodename() );
http.SendAsyncRequest( cb::Make3( AsyncRequestCallback ), asyncRequest, Seconds( 5 ) );
}
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -642,7 +642,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
cEngine::DestroySingleton();
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -68,7 +68,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
std::cin.ignore(10000, '\n');
// If was compiled in debug mode it will print the memory manager report
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -151,7 +151,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
cEngine::DestroySingleton();
// If was compiled in debug mode it will print the memory manager report
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -152,7 +152,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
cEngine::DestroySingleton();
// If was compiled in debug mode it will print the memory manager report
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}

View File

@@ -1952,7 +1952,7 @@ EE_MAIN_FUNC int main (int argc, char * argv []) {
eeDelete( Test );
EE::MemoryManager::ShowResults();
MemoryManager::ShowResults();
return EXIT_SUCCESS;
}