Modify the HttpBinder class template

This commit is contained in:
antao 2019-01-16 18:39:48 +08:00
parent 01de7f4f1e
commit 0b53021358
5 changed files with 38 additions and 33 deletions

View File

@ -120,10 +120,10 @@ class HttpAppFramework : public trantor::NonCopyable
const std::vector<any> &filtersAndMethods = std::vector<any>())
{
LOG_TRACE << "pathPattern:" << pathPattern;
HttpBinderBasePtr binder;
internal::HttpBinderBasePtr binder;
binder = std::make_shared<
HttpBinder<FUNCTION>>(std::forward<FUNCTION>(function));
internal::HttpBinder<FUNCTION>>(std::forward<FUNCTION>(function));
std::vector<HttpMethod> validMethods;
std::vector<std::string> 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<HttpMethod> &validMethods = std::vector<HttpMethod>(),
const std::vector<std::string> &filters = std::vector<std::string>()) = 0;
};

View File

@ -23,12 +23,15 @@
#include <sstream>
#include <memory>
/// 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 <typename T>
struct BinderArgTypeTraits
{
@ -67,10 +70,6 @@ class HttpBinderBase
const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> callback) = 0;
virtual size_t paramCount() = 0;
virtual ~HttpBinderBase() {}
protected:
static std::map<std::string, std::shared_ptr<drogon::DrObjectBase>> _objMap;
static std::mutex _objMutex;
};
typedef std::shared_ptr<HttpBinderBase> HttpBinderBasePtr;
template <typename FUNCTION>
@ -99,7 +98,7 @@ class HttpBinder : public HttpBinderBase
private:
FUNCTION _func;
typedef utility::FunctionTraits<FUNCTION> traits;
typedef FunctionTraits<FUNCTION> traits;
template <
std::size_t Index>
using nth_argument_type = typename traits::template argument<Index>;
@ -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<typename traits::class_type> obj;
{
std::lock_guard<std::mutex> guard(_objMutex);
if (_objMap.find(className) == _objMap.end())
{
obj = std::shared_ptr<typename traits::class_type>(new typename traits::class_type);
_objMap[className] = obj;
}
else
{
obj = std::dynamic_pointer_cast<typename traits::class_type>(_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 <bool isClassFunction = traits::isClassFunction>
typename std::enable_if<isClassFunction, const std::shared_ptr<typename traits::class_type> &>::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<typename traits::class_type>(new typename traits::class_type);
return obj;
}
template <bool isClassFunction = traits::isClassFunction>
typename std::enable_if<!isClassFunction, const std::shared_ptr<void> &>::type getObj()
{
//This function will never be called
static auto obj = std::shared_ptr<void>(nullptr);
assert(0);
return obj;
}
};
} // namespace internal
} // namespace drogon

View File

@ -26,7 +26,7 @@ class HttpResponse;
typedef std::shared_ptr<HttpRequest> HttpRequestPtr;
typedef std::shared_ptr<HttpResponse> HttpResponsePtr;
namespace utility
namespace internal
{
template <typename>
@ -38,6 +38,7 @@ struct FunctionTraits : public FunctionTraits<
decltype(&std::remove_reference<Function>::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<void(const HttpResponsePtr &)> &callback, Arguments...)> : FunctionTraits<ReturnType (*)(Arguments...)>
{
static const bool isHTTPFunction = true;
typedef void class_type;
};
//normal function
@ -95,11 +97,11 @@ struct FunctionTraits<
std::tuple<Arguments...>>::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

View File

@ -43,8 +43,6 @@
using namespace drogon;
using namespace std::placeholders;
std::map<std::string, std::shared_ptr<drogon::DrObjectBase>> 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<HttpMethod> &validMethods,
const std::vector<std::string> &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<HttpMethod> &validMethods,
const std::vector<std::string> &filters)
{

View File

@ -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<HttpMethod> &validMethods = std::vector<HttpMethod>(),
const std::vector<std::string> &filters = std::vector<std::string>()) 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<HttpMethod> &validMethods,
const std::vector<std::string> &filters);
void initRegex();
@ -176,7 +176,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework
std::string pathParameterPattern;
std::vector<size_t> parameterPlaces;
std::map<std::string, size_t> queryParametersPlaces;
HttpBinderBasePtr binderPtr;
internal::HttpBinderBasePtr binderPtr;
std::vector<std::string> filtersName;
std::unique_ptr<std::mutex> binderMtx = std::unique_ptr<std::mutex>(new std::mutex);
std::weak_ptr<HttpResponse> responsePtr;