diff --git a/lib/inc/drogon/HttpAppFramework.h b/lib/inc/drogon/HttpAppFramework.h index bfa8cf84..b702126a 100755 --- a/lib/inc/drogon/HttpAppFramework.h +++ b/lib/inc/drogon/HttpAppFramework.h @@ -120,10 +120,10 @@ class HttpAppFramework : public trantor::NonCopyable const std::vector &filtersAndMethods = std::vector()) { LOG_TRACE << "pathPattern:" << pathPattern; - HttpBinderBasePtr binder; + internal::HttpBinderBasePtr binder; binder = std::make_shared< - HttpBinder>(std::forward(function)); + internal::HttpBinder>(std::forward(function)); std::vector validMethods; std::vector filters; @@ -193,7 +193,7 @@ class HttpAppFramework : public trantor::NonCopyable private: virtual void registerHttpController(const std::string &pathPattern, - const HttpBinderBasePtr &binder, + const internal::HttpBinderBasePtr &binder, const std::vector &validMethods = std::vector(), const std::vector &filters = std::vector()) = 0; }; diff --git a/lib/inc/drogon/HttpBinder.h b/lib/inc/drogon/HttpBinder.h index ffd44a4f..324581d6 100755 --- a/lib/inc/drogon/HttpBinder.h +++ b/lib/inc/drogon/HttpBinder.h @@ -23,12 +23,15 @@ #include #include -/// The classes in the file are internal tool classes. Do not include this +/// The classes in the file are internal tool classes. Do not include this /// file directly and use any of these classes directly. namespace drogon { -//we only accept value type or const lreference type as handle method parameters type +namespace internal +{ + +//we only accept value type or const lreference type or right reference type as the handle method parameters type template struct BinderArgTypeTraits { @@ -67,10 +70,6 @@ class HttpBinderBase const HttpRequestPtr &req, std::function callback) = 0; virtual size_t paramCount() = 0; virtual ~HttpBinderBase() {} - - protected: - static std::map> _objMap; - static std::mutex _objMutex; }; typedef std::shared_ptr HttpBinderBasePtr; template @@ -99,7 +98,7 @@ class HttpBinder : public HttpBinderBase private: FUNCTION _func; - typedef utility::FunctionTraits traits; + typedef FunctionTraits traits; template < std::size_t Index> using nth_argument_type = typename traits::template argument; @@ -149,19 +148,7 @@ class HttpBinder : public HttpBinderBase Values &&... values) { static auto className = drogon::DrObjectBase::demangle(typeid(typename traits::class_type).name()); - std::shared_ptr obj; - { - std::lock_guard guard(_objMutex); - if (_objMap.find(className) == _objMap.end()) - { - obj = std::shared_ptr(new typename traits::class_type); - _objMap[className] = obj; - } - else - { - obj = std::dynamic_pointer_cast(_objMap[className]); - } - } + auto &obj=getObj(); assert(obj); ((*obj).*_func)(req, callback, std::move(values)...); }; @@ -173,5 +160,23 @@ class HttpBinder : public HttpBinderBase { _func(req, callback, std::move(values)...); }; + template + typename std::enable_if &>::type getObj() + { + //Initialization of function-local statics is guaranteed to occur only once even when + //called from multiple threads, and may be more efficient than the equivalent code using std::call_once. + static auto obj = std::shared_ptr(new typename traits::class_type); + return obj; + } + template + typename std::enable_if &>::type getObj() + { + //This function will never be called + static auto obj = std::shared_ptr(nullptr); + assert(0); + return obj; + } }; + +} // namespace internal } // namespace drogon diff --git a/lib/inc/drogon/utils/FunctionTraits.h b/lib/inc/drogon/utils/FunctionTraits.h index b8638ae0..a54214cd 100755 --- a/lib/inc/drogon/utils/FunctionTraits.h +++ b/lib/inc/drogon/utils/FunctionTraits.h @@ -26,7 +26,7 @@ class HttpResponse; typedef std::shared_ptr HttpRequestPtr; typedef std::shared_ptr HttpResponsePtr; -namespace utility +namespace internal { template @@ -38,6 +38,7 @@ struct FunctionTraits : public FunctionTraits< decltype(&std::remove_reference::type::operator())> { static const bool isClassFunction = false; + typedef void class_type; static const std::string name() { return std::string("Functor"); @@ -78,6 +79,7 @@ struct FunctionTraits< ReturnType (*)(const HttpRequestPtr &req, const std::function &callback, Arguments...)> : FunctionTraits { static const bool isHTTPFunction = true; + typedef void class_type; }; //normal function @@ -95,11 +97,11 @@ struct FunctionTraits< std::tuple>::type; static const std::size_t arity = sizeof...(Arguments); - + typedef void class_type; static const bool isHTTPFunction = false; static const bool isClassFunction = false; static const std::string name() { return std::string("Normal or Static Function"); } }; -} // namespace utility +} // namespace internal } // namespace drogon diff --git a/lib/src/HttpAppFrameworkImpl.cc b/lib/src/HttpAppFrameworkImpl.cc index 2dd57fda..2a3d86a3 100755 --- a/lib/src/HttpAppFrameworkImpl.cc +++ b/lib/src/HttpAppFrameworkImpl.cc @@ -43,8 +43,6 @@ using namespace drogon; using namespace std::placeholders; -std::map> HttpBinderBase::_objMap; -std::mutex HttpBinderBase::_objMutex; static void godaemon(void) { @@ -189,7 +187,7 @@ void HttpAppFrameworkImpl::registerHttpSimpleController(const std::string &pathN } } void HttpAppFrameworkImpl::addHttpPath(const std::string &path, - const HttpBinderBasePtr &binder, + const internal::HttpBinderBasePtr &binder, const std::vector &validMethods, const std::vector &filters) { @@ -261,7 +259,7 @@ void HttpAppFrameworkImpl::addHttpPath(const std::string &path, } } void HttpAppFrameworkImpl::registerHttpController(const std::string &pathPattern, - const HttpBinderBasePtr &binder, + const internal::HttpBinderBasePtr &binder, const std::vector &validMethods, const std::vector &filters) { diff --git a/lib/src/HttpAppFrameworkImpl.h b/lib/src/HttpAppFrameworkImpl.h index 585912c0..456d0474 100644 --- a/lib/src/HttpAppFrameworkImpl.h +++ b/lib/src/HttpAppFrameworkImpl.h @@ -111,7 +111,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework #endif private: virtual void registerHttpController(const std::string &pathPattern, - const HttpBinderBasePtr &binder, + const internal::HttpBinderBasePtr &binder, const std::vector &validMethods = std::vector(), const std::vector &filters = std::vector()) override; @@ -125,7 +125,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework void onConnection(const TcpConnectionPtr &conn); void readSendFile(const std::string &filePath, const HttpRequestImplPtr &req, const HttpResponsePtr &resp); void addHttpPath(const std::string &path, - const HttpBinderBasePtr &binder, + const internal::HttpBinderBasePtr &binder, const std::vector &validMethods, const std::vector &filters); void initRegex(); @@ -176,7 +176,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework std::string pathParameterPattern; std::vector parameterPlaces; std::map queryParametersPlaces; - HttpBinderBasePtr binderPtr; + internal::HttpBinderBasePtr binderPtr; std::vector filtersName; std::unique_ptr binderMtx = std::unique_ptr(new std::mutex); std::weak_ptr responsePtr;