summaryrefslogtreecommitdiffstats
path: root/src/Common
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common')
-rw-r--r--src/Common/Connection.h4
-rw-r--r--src/Common/Request.cpp2
-rw-r--r--src/Common/Request.h70
-rw-r--r--src/Common/RequestHandler.h15
-rw-r--r--src/Common/RequestManager.cpp8
-rw-r--r--src/Common/RequestManager.h46
6 files changed, 105 insertions, 40 deletions
diff --git a/src/Common/Connection.h b/src/Common/Connection.h
index 2d74548..0dd2f2e 100644
--- a/src/Common/Connection.h
+++ b/src/Common/Connection.h
@@ -39,7 +39,7 @@ class Connection : private boost::noncopyable {
private:
bool authenticated;
- Net::Signals::Signal2<void, const XmlPacket&, uint16_t> signalReceive;
+ Net::Signals::Signal2<const XmlPacket&, uint16_t> signalReceive;
protected:
Connection() : authenticated(0) {}
@@ -53,7 +53,7 @@ class Connection : private boost::noncopyable {
bool sendPacket(const XmlPacket &packet, uint16_t requestId);
- Net::Signals::Connection connectSignalReceive(const Net::Signals::Signal2<void, const XmlPacket&, uint16_t>::slot_type &slot) {
+ Net::Signals::Connection connectSignalReceive(const Net::Signals::Signal2<const XmlPacket&, uint16_t>::slot_type &slot) {
return signalReceive.connect(slot);
}
diff --git a/src/Common/Request.cpp b/src/Common/Request.cpp
index 5f4c201..e27c1b9 100644
--- a/src/Common/Request.cpp
+++ b/src/Common/Request.cpp
@@ -22,6 +22,8 @@
namespace Mad {
namespace Common {
+Request::slot_type Request::empty_slot(&Request::doNothing);
+
void Request::handlePacket(const XmlPacket &packet) {
if(packet.getType() == "Error") {
finishWithError(Net::Exception(packet["Where"], packet["ErrorCode"], packet["SubCode"], packet["SubSubCode"]));
diff --git a/src/Common/Request.h b/src/Common/Request.h
index 6f72667..d351c2a 100644
--- a/src/Common/Request.h
+++ b/src/Common/Request.h
@@ -26,6 +26,9 @@
#include <memory>
#include <boost/bind.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/mutex.hpp>
namespace Mad {
namespace Common {
@@ -34,35 +37,88 @@ class Request : public RequestHandler {
private:
friend class RequestManager;
- Net::Signals::Signal1<void, const Request&> finished;
+ Net::Signals::Signal1<Request&> finished;
std::auto_ptr<XmlPacket> res;
Net::Exception exp;
+ boost::mutex mutex;
+ boost::condition_variable finishCond;
+ bool isFinished;
+
+ static void doNothing(Request&) {}
+
public:
- typedef Net::Signals::Signal1<void, const Request&>::slot_type slot_type;
+ typedef Net::Signals::Signal1<Request&>::slot_type slot_type;
protected:
+ static slot_type empty_slot;
+
Request(Connection *connection, uint16_t requestId, slot_type slot)
- : RequestHandler(connection, requestId), exp(Net::Exception::NOT_FINISHED) {
+ : RequestHandler(connection, requestId), exp(Net::Exception::NOT_FINISHED), isFinished(false) {
finished.connect(slot);
finished.connect(boost::bind(&Request::signalFinished, this));
}
- void finish(std::auto_ptr<XmlPacket> result) {res = result; finished.emit(*this);}
- void finish(const XmlPacket& result) {res.reset(new XmlPacket(result)); finished.emit(*this);}
- void finishWithError(const Net::Exception &e) {exp = e; finished.emit(*this);}
+ virtual ~Request() {
+ wait();
+ }
+
+ void finish(std::auto_ptr<XmlPacket> result) {
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+
+ res = result;
+ isFinished = true;
+ }
+
+ finishCond.notify_all();
+ finished.emit(*this);
+ }
+
+ void finish(const XmlPacket& result) {
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+
+ res.reset(new XmlPacket(result));
+ isFinished = true;
+ }
+
+ finishCond.notify_all();
+ finished.emit(*this);
+ }
+
+ void finishWithError(const Net::Exception &e) {
+ {
+ boost::lock_guard<boost::mutex> lock(mutex);
+
+ exp = e;
+ isFinished = true;
+ }
+
+ finishCond.notify_all();
+ finished.emit(*this);
+ }
virtual void sendRequest() = 0;
virtual void handlePacket(const XmlPacket &packet);
public:
- const XmlPacket& getResult() const throw(Net::Exception) {
+ const XmlPacket& getResult() throw(Net::Exception) {
+ boost::lock_guard<boost::mutex> lock(mutex);
+
if(res.get())
return *res;
throw exp;
}
+
+ void wait() {
+ boost::unique_lock<boost::mutex> lock(mutex);
+
+ while(!isFinished)
+ finishCond.wait(lock);
+ }
};
}
diff --git a/src/Common/RequestHandler.h b/src/Common/RequestHandler.h
index 58ffeb7..d35ab1b 100644
--- a/src/Common/RequestHandler.h
+++ b/src/Common/RequestHandler.h
@@ -33,22 +33,21 @@ namespace Common {
class Connection;
class RequestManager;
-class RequestHandler {
+class RequestHandler : private boost::noncopyable {
private:
- Net::Signals::Signal0<void> finished;
+ Net::Signals::Signal0 finished;
Connection *connection;
boost::uint16_t requestId;
- // Prevent shallow copy
- RequestHandler(const RequestHandler &o);
- RequestHandler& operator=(const RequestHandler &o);
-
protected:
RequestHandler(Connection *connection0, boost::uint16_t requestId0) : connection(connection0), requestId(requestId0) {}
- void signalFinished() {finished.emit();}
- Net::Signals::Connection connectSignalFinished(const Net::Signals::Signal0<void>::slot_type &slot) {
+ void signalFinished() {
+ finished.emit();
+ }
+
+ Net::Signals::Connection connectSignalFinished(const Net::Signals::Signal0::slot_type &slot) {
return finished.connect(slot);
}
diff --git a/src/Common/RequestManager.cpp b/src/Common/RequestManager.cpp
index f328bf7..da9979a 100644
--- a/src/Common/RequestManager.cpp
+++ b/src/Common/RequestManager.cpp
@@ -46,8 +46,12 @@ boost::shared_ptr<RequestHandler> RequestManager::RequestMap::findRequest(boost:
return it->second;
}
-bool RequestManager::RequestMap::deleteRequest(boost::uint16_t id) {
- return erase(id);
+void RequestManager::RequestMap::deleteRequest(boost::uint16_t id) {
+ Net::ThreadManager::get()->pushWork(boost::bind(&RequestMap::doDeleteRequest, this, id));
+}
+
+void RequestManager::RequestMap::doDeleteRequest(boost::uint16_t id) {
+ erase(id);
}
diff --git a/src/Common/RequestManager.h b/src/Common/RequestManager.h
index d9e7fbb..bd1c12d 100644
--- a/src/Common/RequestManager.h
+++ b/src/Common/RequestManager.h
@@ -21,6 +21,7 @@
#define MAD_COMMON_REQUESTMANAGER_H_
#include "Request.h"
+#include <Net/ThreadManager.h>
#include <map>
#include <memory>
@@ -43,7 +44,10 @@ class RequestManager : boost::noncopyable {
public:
bool addRequest(boost::uint16_t id, boost::shared_ptr<RequestHandler> info);
boost::shared_ptr<RequestHandler> findRequest(boost::uint16_t id);
- bool deleteRequest(boost::uint16_t id);
+ void deleteRequest(boost::uint16_t id);
+
+ private:
+ void doDeleteRequest(boost::uint16_t id);
};
class RequestHandlerFactory {
@@ -123,7 +127,7 @@ class RequestManager : boost::noncopyable {
}
template <class T>
- bool sendRequest(Connection *connection, Request::slot_type slot) {
+ boost::shared_ptr<Request> sendRequest0(Connection *connection, Request::slot_type slot = Request::empty_slot) {
boost::unique_lock<boost::shared_mutex> lock(mutex);
boost::shared_ptr<RequestMap> requestMap;
@@ -132,19 +136,19 @@ class RequestManager : boost::noncopyable {
requestMap = _getUnusedRequestId(connection, &requestId);
if(!requestMap)
- return false;
+ return boost::shared_ptr<Request>();
boost::shared_ptr<Request> request(new T(connection, requestId, slot));
requestMap->addRequest(requestId, request);
lock.unlock();
- request->sendRequest();
+ Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request));
- return true;
+ return request;
}
template <class T, typename T1>
- bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1) {
+ boost::shared_ptr<Request> sendRequest1(Connection *connection, T1 t1, Request::slot_type slot = Request::empty_slot) {
boost::unique_lock<boost::shared_mutex> lock(mutex);
boost::shared_ptr<RequestMap> requestMap;
@@ -153,19 +157,19 @@ class RequestManager : boost::noncopyable {
requestMap = _getUnusedRequestId(connection, &requestId);
if(!requestMap)
- return false;
+ return boost::shared_ptr<Request>();
boost::shared_ptr<Request> request(new T(connection, requestId, slot, t1));
requestMap->addRequest(requestId, request);
lock.unlock();
- request->sendRequest();
+ Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request));
- return true;
+ return request;
}
template <class T, typename T1, typename T2>
- bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1, T2 t2) {
+ boost::shared_ptr<Request> sendRequest2(Connection *connection, T1 t1, T2 t2, Request::slot_type slot = Request::empty_slot) {
boost::unique_lock<boost::shared_mutex> lock(mutex);
boost::shared_ptr<RequestMap> requestMap;
@@ -174,19 +178,19 @@ class RequestManager : boost::noncopyable {
requestMap = _getUnusedRequestId(connection, &requestId);
if(!requestMap)
- return false;
+ return boost::shared_ptr<Request>();
boost::shared_ptr<Request> request(new T(connection, requestId, slot, t1, t2));
requestMap->addRequest(requestId, request);
lock.unlock();
- request->sendRequest();
+ Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request));
- return true;
+ return request;
}
template <class T, typename T1, typename T2, typename T3>
- bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1, T2 t2, T3 t3) {
+ boost::shared_ptr<Request> sendRequest3(Connection *connection, T1 t1, T2 t2, T3 t3, Request::slot_type slot = Request::empty_slot) {
boost::unique_lock<boost::shared_mutex> lock(mutex);
boost::shared_ptr<RequestMap> requestMap;
@@ -195,19 +199,19 @@ class RequestManager : boost::noncopyable {
requestMap = _getUnusedRequestId(connection, &requestId);
if(!requestMap)
- return false;
+ return boost::shared_ptr<Request>();
boost::shared_ptr<T> request(new T(connection, requestId, slot, t1, t2, t3));
requestMap->addRequest(requestId, request);
lock.unlock();
- request->sendRequest();
+ Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request));
- return true;
+ return request;
}
template <class T, typename T1, typename T2, typename T3, typename T4>
- bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1, T2 t2, T3 t3, T4 t4) {
+ boost::shared_ptr<Request> sendRequest4(Connection *connection, T1 t1, T2 t2, T3 t3, T4 t4, Request::slot_type slot = Request::empty_slot) {
boost::unique_lock<boost::shared_mutex> lock(mutex);
boost::shared_ptr<RequestMap> requestMap;
@@ -216,15 +220,15 @@ class RequestManager : boost::noncopyable {
requestMap = _getUnusedRequestId(connection, &requestId);
if(!requestMap)
- return false;
+ return boost::shared_ptr<Request>();
boost::shared_ptr<Request> request(new T(connection, requestId, slot, t1, t2, t3, t4));
requestMap->addRequest(requestId, request);
lock.unlock();
- request->sendRequest();
+ Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request));
- return true;
+ return request;
}
};