/* * RequestManager.h * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef MAD_COMMON_REQUESTMANAGER_H_ #define MAD_COMMON_REQUESTMANAGER_H_ #include "Request.h" #include #include #include #include #include namespace Mad { namespace Net { class Packet; } namespace Common { class RequestManager : boost::noncopyable { private: class RequestMap : private std::map >, boost::noncopyable { public: bool addRequest(boost::uint16_t id, boost::shared_ptr info); boost::shared_ptr findRequest(boost::uint16_t id); bool deleteRequest(boost::uint16_t id); }; class RequestHandlerFactory { protected: RequestHandlerFactory() {} public: virtual boost::shared_ptr createRequestHandler(Connection *connection, boost::uint16_t requestId) = 0; virtual ~RequestHandlerFactory() {} }; template class SpecificRequestHandlerFactory : public RequestHandlerFactory { public: virtual boost::shared_ptr createRequestHandler(Connection *connection, boost::uint16_t requestId) { return boost::shared_ptr(new T(connection, requestId)); } }; static RequestManager requestManager; boost::shared_mutex mutex; std::map > requestMaps; bool server; boost::uint16_t lastRequestId; std::map > requestHandlerFactories; boost::uint16_t _getRequestId() { return lastRequestId+=2; } void receiveHandler(Connection *connection, const XmlPacket &packet, boost::uint16_t requestId); boost::shared_ptr _getUnusedRequestId(Connection *connection, boost::uint16_t *requestId); bool send(Request *request); RequestManager(); public: static RequestManager* get() { return &requestManager; } bool isServer() { boost::shared_lock lock(mutex); return server; } void setServer(bool newServer) { boost::lock_guard lock(mutex); server = newServer; if(server) lastRequestId &= ~0x01; else lastRequestId |= 0x01; } void registerConnection(Connection *connection); void unregisterConnection(Connection *connection) { boost::lock_guard lock(mutex); requestMaps.erase(connection); } template void registerPacketType(const std::string &type) { boost::lock_guard lock(mutex); requestHandlerFactories.insert(std::make_pair(type, boost::shared_ptr >(new SpecificRequestHandlerFactory()))); } void unregisterPacketType(const std::string &type) { boost::lock_guard lock(mutex); requestHandlerFactories.erase(type); } template bool sendRequest(Connection *connection, Request::slot_type slot) { boost::unique_lock lock(mutex); boost::shared_ptr requestMap; boost::uint16_t requestId; requestMap = _getUnusedRequestId(connection, &requestId); if(!requestMap) return false; boost::shared_ptr request(new T(connection, requestId, slot)); requestMap->addRequest(requestId, request); lock.unlock(); request->sendRequest(); return true; } template bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1) { boost::unique_lock lock(mutex); boost::shared_ptr requestMap; boost::uint16_t requestId; requestMap = _getUnusedRequestId(connection, &requestId); if(!requestMap) return false; boost::shared_ptr request(new T(connection, requestId, slot, t1)); requestMap->addRequest(requestId, request); lock.unlock(); request->sendRequest(); return true; } template bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1, T2 t2) { boost::unique_lock lock(mutex); boost::shared_ptr requestMap; boost::uint16_t requestId; requestMap = _getUnusedRequestId(connection, &requestId); if(!requestMap) return false; boost::shared_ptr request(new T(connection, requestId, slot, t1, t2)); requestMap->addRequest(requestId, request); lock.unlock(); request->sendRequest(); return true; } template bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1, T2 t2, T3 t3) { boost::unique_lock lock(mutex); boost::shared_ptr requestMap; boost::uint16_t requestId; requestMap = _getUnusedRequestId(connection, &requestId); if(!requestMap) return false; boost::shared_ptr request(new T(connection, requestId, slot, t1, t2, t3)); requestMap->addRequest(requestId, request); lock.unlock(); request->sendRequest(); return true; } template bool sendRequest(Connection *connection, Request::slot_type slot, T1 t1, T2 t2, T3 t3, T4 t4) { boost::unique_lock lock(mutex); boost::shared_ptr requestMap; boost::uint16_t requestId; requestMap = _getUnusedRequestId(connection, &requestId); if(!requestMap) return false; boost::shared_ptr request(new T(connection, requestId, slot, t1, t2, t3, t4)); requestMap->addRequest(requestId, request); lock.unlock(); request->sendRequest(); return true; } }; } } #endif /* MAD_COMMON_REQUESTMANAGER_H_ */