mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-03 20:16:29 +03:00
Added support for AsyncRequests in cHttp.
Added cThreadLocal and tThreadLocalPtr ( needed for the async requests ).
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
24
src/eepp/system/cthreadlocal.cpp
Normal file
24
src/eepp/system/cthreadlocal.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -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
|
||||
|
||||
25
src/eepp/system/platform/posix/cthreadlocalimpl.cpp
Normal file
25
src/eepp/system/platform/posix/cthreadlocalimpl.cpp
Normal 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
|
||||
31
src/eepp/system/platform/posix/cthreadlocalimpl.hpp
Normal file
31
src/eepp/system/platform/posix/cthreadlocalimpl.hpp
Normal 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
|
||||
|
||||
25
src/eepp/system/platform/win/cthreadlocalimpl.cpp
Normal file
25
src/eepp/system/platform/win/cthreadlocalimpl.cpp
Normal 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
|
||||
30
src/eepp/system/platform/win/cthreadlocalimpl.hpp
Normal file
30
src/eepp/system/platform/win/cthreadlocalimpl.hpp
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
|
||||
|
||||
cEngine::DestroySingleton();
|
||||
|
||||
EE::MemoryManager::ShowResults();
|
||||
MemoryManager::ShowResults();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -642,7 +642,7 @@ EE_MAIN_FUNC int main (int argc, char * argv [])
|
||||
|
||||
cEngine::DestroySingleton();
|
||||
|
||||
EE::MemoryManager::ShowResults();
|
||||
MemoryManager::ShowResults();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1952,7 +1952,7 @@ EE_MAIN_FUNC int main (int argc, char * argv []) {
|
||||
|
||||
eeDelete( Test );
|
||||
|
||||
EE::MemoryManager::ShowResults();
|
||||
MemoryManager::ShowResults();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user