diff options
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/Connection.h | 4 | ||||
-rw-r--r-- | src/Common/Request.cpp | 2 | ||||
-rw-r--r-- | src/Common/Request.h | 70 | ||||
-rw-r--r-- | src/Common/RequestHandler.h | 15 | ||||
-rw-r--r-- | src/Common/RequestManager.cpp | 8 | ||||
-rw-r--r-- | src/Common/RequestManager.h | 46 |
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; } }; |