/* * 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 Lesser 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #ifndef MAD_COMMON_REQUESTMANAGER_H_ #define MAD_COMMON_REQUESTMANAGER_H_ #include "export.h" #include "Request.h" #include "RequestHandlerGroup.h" #include #include #include #include #include namespace Mad { namespace Common { class Application; class MAD_COMMON_EXPORT RequestManager : private boost::noncopyable { private: friend class Application; friend class RequestHandler; class MAD_COMMON_EXPORT RequestMap : private boost::noncopyable { private: typedef std::map > IdMap; typedef std::map > HandlerMap; std::map connectionMap; HandlerMap handlerMap; public: void registerConnection(Connection *connection) { connectionMap.insert(std::make_pair(connection, IdMap())); } void unregisterConnection(Connection *connection); bool isConnectionRegistered(Connection *connection) const { return connectionMap.count(connection); } bool addRequest(Connection *con, boost::uint16_t id, boost::shared_ptr info); boost::shared_ptr findRequest(Connection *con, boost::uint16_t id); void deleteRequest(Connection *con, boost::uint16_t id); std::pair getRequestInfo(const RequestHandler *requestHandler); }; template class RequestHandlerFactory0 : public RequestHandlerGroup { private: std::set types; public: RequestHandlerFactory0(const Core::String &type) { types.insert(type); } virtual const std::set& getPacketTypes() { return types; } virtual boost::shared_ptr createRequestHandler(Application *application, const Core::String& /*type*/) { return boost::shared_ptr(new T(application)); } }; template class RequestHandlerFactory1 : public RequestHandlerGroup { private: std::set types; T1 arg1; public: RequestHandlerFactory1(const Core::String &type, T1 argT1) : arg1(argT1) { types.insert(type); } virtual const std::set& getPacketTypes() { return types; } virtual boost::shared_ptr createRequestHandler(Application *application, const Core::String& /*type*/) { return boost::shared_ptr(new T(application, arg1)); } }; Application *application; boost::shared_mutex mutex; RequestMap requestMap; boost::uint16_t lastRequestId; std::map > requestHandlerGroups; boost::uint16_t _getRequestId() { return lastRequestId+=2; } void receiveHandler(Connection *connection, boost::shared_ptr packet, boost::uint16_t requestId); void handleRequestFinished(Connection *con, boost::uint16_t requestId) { boost::lock_guard lock(mutex); requestMap.deleteRequest(con, requestId); } boost::uint16_t _getUnusedRequestId(Connection *connection); bool send(Request *request); RequestManager(Application *application0, bool server); public: void registerConnection(Connection *connection); void unregisterConnection(Connection *connection) { boost::lock_guard lock(mutex); requestMap.unregisterConnection(connection); } void registerRequestHandlerGroup(boost::shared_ptr requestHandlerGroup) { boost::lock_guard lock(mutex); const std::set &types = requestHandlerGroup->getPacketTypes(); for(std::set::const_iterator type = types.begin(); type != types.end(); ++type) requestHandlerGroups.insert(std::make_pair(*type, requestHandlerGroup)); } void unregisterRequestHandlerGroup(boost::shared_ptr requestHandlerGroup) { boost::lock_guard lock(mutex); const std::set &types = requestHandlerGroup->getPacketTypes(); for(std::set::const_iterator type = types.begin(); type != types.end(); ++type) { std::map >::iterator it = requestHandlerGroups.find(*type); if(it == requestHandlerGroups.end() || it->second != requestHandlerGroup) continue; requestHandlerGroups.erase(it); } } template void registerPacketType(const Core::String &type) { registerRequestHandlerGroup(boost::shared_ptr >(new RequestHandlerFactory0(type))); } template void registerPacketType(const Core::String &type, T1 arg1) { registerRequestHandlerGroup(boost::shared_ptr >(new RequestHandlerFactory1(type, arg1))); } void unregisterPacketType(const Core::String &type) { boost::lock_guard lock(mutex); requestHandlerGroups.erase(type); } bool sendRequest(Connection *connection, boost::shared_ptr request); }; } } #endif /* MAD_COMMON_REQUESTMANAGER_H_ */