mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-12-02 19:57:43 +08:00
Remove spin-locks
This commit is contained in:
parent
60ac951b38
commit
d16287c9dd
@ -279,9 +279,8 @@ void HttpAppFrameworkImpl::run()
|
||||
}
|
||||
std::vector<std::shared_ptr<HttpServer>> servers;
|
||||
std::vector<std::shared_ptr<EventLoopThread>> loopThreads;
|
||||
_httpCtrlsRouter.init();
|
||||
_httpSimpleCtrlsRouter.init();
|
||||
_websockCtrlsRouter.init();
|
||||
|
||||
std::vector<trantor::EventLoop *> ioLoops;
|
||||
for (auto const &listener : _listeners)
|
||||
{
|
||||
LOG_TRACE << "thread num=" << _threadNum;
|
||||
@ -316,6 +315,7 @@ void HttpAppFrameworkImpl::run()
|
||||
serverPtr->kickoffIdleConnections(_idleConnectionTimeout);
|
||||
serverPtr->start();
|
||||
servers.push_back(serverPtr);
|
||||
ioLoops.push_back(serverPtr->getLoop());
|
||||
}
|
||||
#else
|
||||
auto loopThreadPtr = std::make_shared<EventLoopThread>("DrogonIoLoop");
|
||||
@ -349,9 +349,24 @@ void HttpAppFrameworkImpl::run()
|
||||
serverPtr->setConnectionCallback(std::bind(&HttpAppFrameworkImpl::onConnection, this, _1));
|
||||
serverPtr->kickoffIdleConnections(_idleConnectionTimeout);
|
||||
serverPtr->start();
|
||||
std::promise<int> pro;
|
||||
auto f = pro.get_future();
|
||||
serverPtr->getLoop()->runInLoop([&pro]() {
|
||||
pro.set_value(1);
|
||||
});
|
||||
f.get();
|
||||
auto serverIoLoops = serverPtr->getIoLoops();
|
||||
for (auto serverIoLoop : serverIoLoops)
|
||||
{
|
||||
ioLoops.push_back(serverIoLoop);
|
||||
}
|
||||
servers.push_back(serverPtr);
|
||||
#endif
|
||||
}
|
||||
_httpCtrlsRouter.init(ioLoops);
|
||||
_httpSimpleCtrlsRouter.init(ioLoops);
|
||||
_websockCtrlsRouter.init();
|
||||
|
||||
if (_useSession)
|
||||
{
|
||||
if (_sessionTimeout > 0)
|
||||
|
@ -17,11 +17,10 @@
|
||||
#include "HttpRequestImpl.h"
|
||||
#include "HttpResponseImpl.h"
|
||||
#include "HttpAppFrameworkImpl.h"
|
||||
#include "SpinLock.h"
|
||||
|
||||
using namespace drogon;
|
||||
|
||||
void HttpControllersRouter::init()
|
||||
void HttpControllersRouter::init(const std::vector<trantor::EventLoop *> &ioLoops)
|
||||
{
|
||||
std::string regString;
|
||||
for (auto &router : _ctrlVector)
|
||||
@ -30,11 +29,15 @@ void HttpControllersRouter::init()
|
||||
std::string tmp = std::regex_replace(router._pathParameterPattern, reg, "[^/]*");
|
||||
router._regex = std::regex(router._pathParameterPattern, std::regex_constants::icase);
|
||||
regString.append("(").append(tmp).append(")|");
|
||||
for(auto &binder:router._binders)
|
||||
for (auto &binder : router._binders)
|
||||
{
|
||||
if(binder)
|
||||
if (binder)
|
||||
{
|
||||
binder->_filters = FiltersFunction::createFilters(binder->_filterNames);
|
||||
for(auto ioloop:ioLoops)
|
||||
{
|
||||
binder->_responsePtrMap[ioloop] = std::shared_ptr<HttpResponse>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -218,12 +221,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId)
|
||||
{
|
||||
HttpResponsePtr responsePtr;
|
||||
{
|
||||
SimpleSpinLock guard(ctrlBinderPtr->_binderMtx);
|
||||
responsePtr = ctrlBinderPtr->_responsePtr;
|
||||
}
|
||||
|
||||
HttpResponsePtr &responsePtr = ctrlBinderPtr->_responsePtrMap[req->getLoop()];
|
||||
if (responsePtr && (responsePtr->expiredTime() == 0 || (trantor::Date::now() < responsePtr->creationDate().after(responsePtr->expiredTime()))))
|
||||
{
|
||||
//use cached response!
|
||||
@ -282,9 +280,16 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
|
||||
{
|
||||
//cache the response;
|
||||
std::dynamic_pointer_cast<HttpResponseImpl>(resp)->makeHeaderString();
|
||||
auto loop = req->getLoop();
|
||||
if (loop->isInLoopThread())
|
||||
{
|
||||
SimpleSpinLock guard(ctrlBinderPtr->_binderMtx);
|
||||
ctrlBinderPtr->_responsePtr = resp;
|
||||
ctrlBinderPtr->_responsePtrMap[loop] = resp;
|
||||
}
|
||||
else
|
||||
{
|
||||
req->getLoop()->queueInLoop([loop, resp, ctrlBinderPtr]() {
|
||||
ctrlBinderPtr->_responsePtrMap[loop] = resp;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (needSetJsessionid)
|
||||
|
@ -32,7 +32,7 @@ class HttpControllersRouter : public trantor::NonCopyable
|
||||
{
|
||||
public:
|
||||
HttpControllersRouter() {}
|
||||
void init();
|
||||
void init(const std::vector<trantor::EventLoop *> &ioLoops);
|
||||
void addHttpPath(const std::string &path,
|
||||
const internal::HttpBinderBasePtr &binder,
|
||||
const std::vector<HttpMethod> &validMethods,
|
||||
@ -50,9 +50,7 @@ class HttpControllersRouter : public trantor::NonCopyable
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> _filters;
|
||||
std::vector<size_t> _parameterPlaces;
|
||||
std::map<std::string, size_t> _queryParametersPlaces;
|
||||
//std::atomic<bool> _binderMtx = ATOMIC_VAR_INIT(false);
|
||||
std::atomic_flag _binderMtx = ATOMIC_FLAG_INIT;
|
||||
std::shared_ptr<HttpResponse> _responsePtr;
|
||||
std::map<trantor::EventLoop *,std::shared_ptr<HttpResponse>> _responsePtrMap;
|
||||
};
|
||||
typedef std::shared_ptr<CtrlBinder> CtrlBinderPtr;
|
||||
struct HttpControllerRouterItem
|
||||
|
@ -18,7 +18,8 @@
|
||||
using namespace drogon;
|
||||
|
||||
HttpFileUploadRequest::HttpFileUploadRequest(const std::vector<UploadFile> &files)
|
||||
: _files(files)
|
||||
: HttpRequestImpl(nullptr),
|
||||
_files(files)
|
||||
{
|
||||
_boundary = genRandomString(32);
|
||||
setMethod(drogon::Post);
|
||||
|
@ -317,7 +317,7 @@ void HttpRequestImpl::addHeader(const char *start, const char *colon, const char
|
||||
|
||||
HttpRequestPtr HttpRequest::newHttpRequest()
|
||||
{
|
||||
auto req = std::make_shared<HttpRequestImpl>();
|
||||
auto req = std::make_shared<HttpRequestImpl>(nullptr);
|
||||
req->setMethod(drogon::Get);
|
||||
req->setVersion(drogon::HttpRequest::kHttp11);
|
||||
return req;
|
||||
@ -325,7 +325,7 @@ HttpRequestPtr HttpRequest::newHttpRequest()
|
||||
|
||||
HttpRequestPtr HttpRequest::newHttpFormPostRequest()
|
||||
{
|
||||
auto req = std::make_shared<HttpRequestImpl>();
|
||||
auto req = std::make_shared<HttpRequestImpl>(nullptr);
|
||||
req->setMethod(drogon::Post);
|
||||
req->setVersion(drogon::HttpRequest::kHttp11);
|
||||
req->_contentType = CT_APPLICATION_X_FORM;
|
||||
@ -334,7 +334,7 @@ HttpRequestPtr HttpRequest::newHttpFormPostRequest()
|
||||
|
||||
HttpRequestPtr HttpRequest::newHttpJsonRequest(const Json::Value &data)
|
||||
{
|
||||
auto req = std::make_shared<HttpRequestImpl>();
|
||||
auto req = std::make_shared<HttpRequestImpl>(nullptr);
|
||||
req->setMethod(drogon::Get);
|
||||
req->setVersion(drogon::HttpRequest::kHttp11);
|
||||
req->_contentType = CT_APPLICATION_JSON;
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <trantor/utils/Logger.h>
|
||||
#include <trantor/utils/MsgBuffer.h>
|
||||
#include <trantor/net/InetAddress.h>
|
||||
#include <trantor/net/EventLoop.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -40,14 +42,17 @@ class HttpRequestImpl : public HttpRequest
|
||||
public:
|
||||
friend class HttpRequestParser;
|
||||
|
||||
HttpRequestImpl()
|
||||
HttpRequestImpl(trantor::EventLoop *loop)
|
||||
: _method(Invalid),
|
||||
_version(kUnknown),
|
||||
_date(trantor::Date::now()),
|
||||
_contentLen(0)
|
||||
_contentLen(0),
|
||||
_loop(loop)
|
||||
{
|
||||
}
|
||||
|
||||
trantor::EventLoop *getLoop() { return _loop; }
|
||||
|
||||
void setVersion(Version v)
|
||||
{
|
||||
_version = v;
|
||||
@ -368,10 +373,11 @@ class HttpRequestImpl : public HttpRequest
|
||||
trantor::InetAddress _peer;
|
||||
trantor::InetAddress _local;
|
||||
trantor::Date _date;
|
||||
|
||||
|
||||
protected:
|
||||
std::string _content;
|
||||
size_t _contentLen;
|
||||
trantor::EventLoop *_loop;
|
||||
ContentType _contentType = CT_TEXT_PLAIN;
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,8 @@ using namespace drogon;
|
||||
|
||||
HttpRequestParser::HttpRequestParser(const trantor::TcpConnectionPtr &connPtr)
|
||||
: _state(kExpectRequestLine),
|
||||
_request(new HttpRequestImpl),
|
||||
_loop(connPtr->getLoop()),
|
||||
_request(new HttpRequestImpl(connPtr->getLoop())),
|
||||
_conn(connPtr)
|
||||
{
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class HttpRequestParser
|
||||
void reset()
|
||||
{
|
||||
_state = kExpectRequestLine;
|
||||
_request.reset(new HttpRequestImpl);
|
||||
_request.reset(new HttpRequestImpl(_loop));
|
||||
}
|
||||
|
||||
const HttpRequestPtr request() const
|
||||
@ -96,6 +96,8 @@ class HttpRequestParser
|
||||
bool processRequestLine(const char *begin, const char *end);
|
||||
|
||||
HttpRequestParseState _state;
|
||||
|
||||
trantor::EventLoop *_loop;
|
||||
HttpRequestImplPtr _request;
|
||||
|
||||
bool _firstRequest = true;
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include "HttpAppFrameworkImpl.h"
|
||||
#include "HttpResponseImpl.h"
|
||||
#include "SpinLock.h"
|
||||
#include <drogon/HttpViewBase.h>
|
||||
#include <drogon/HttpViewData.h>
|
||||
#include <drogon/HttpAppFramework.h>
|
||||
@ -350,17 +349,13 @@ std::shared_ptr<std::string> HttpResponseImpl::renderToString() const
|
||||
{
|
||||
_httpStringDate = now.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC;
|
||||
auto newDate = getHttpFullDate(now);
|
||||
{
|
||||
SimpleSpinLock lock(*_httpStringMutex);
|
||||
_httpString = std::make_shared<std::string>(*_httpString);
|
||||
memcpy((void *)&(*_httpString)[_datePos], newDate, strlen(newDate));
|
||||
return _httpString;
|
||||
}
|
||||
}
|
||||
{
|
||||
SimpleSpinLock lock(*_httpStringMutex);
|
||||
|
||||
_httpString = std::make_shared<std::string>(*_httpString);
|
||||
memcpy((void *)&(*_httpString)[_datePos], newDate, strlen(newDate));
|
||||
return _httpString;
|
||||
}
|
||||
|
||||
return _httpString;
|
||||
}
|
||||
}
|
||||
auto httpString = std::make_shared<std::string>();
|
||||
@ -394,7 +389,6 @@ std::shared_ptr<std::string> HttpResponseImpl::renderToString() const
|
||||
httpString->append(*_bodyPtr);
|
||||
if (_expriedTime >= 0)
|
||||
{
|
||||
SimpleSpinLock lock(*_httpStringMutex);
|
||||
_datePos = datePos;
|
||||
_httpString = httpString;
|
||||
}
|
||||
|
@ -40,10 +40,8 @@ class HttpResponseImpl : public HttpResponse
|
||||
_closeConnection(false),
|
||||
_leftBodyLength(0),
|
||||
_currentChunkLength(0),
|
||||
_bodyPtr(new std::string()),
|
||||
_httpStringMutex(new std::atomic_flag)
|
||||
_bodyPtr(new std::string())
|
||||
{
|
||||
_httpStringMutex->clear();
|
||||
}
|
||||
virtual HttpStatusCode statusCode() override
|
||||
{
|
||||
@ -388,7 +386,6 @@ class HttpResponseImpl : public HttpResponse
|
||||
std::shared_ptr<std::string> _fullHeaderString;
|
||||
|
||||
mutable std::shared_ptr<std::string> _httpString;
|
||||
mutable std::shared_ptr<std::atomic_flag> _httpStringMutex;
|
||||
mutable std::string::size_type _datePos = std::string::npos;
|
||||
mutable int64_t _httpStringDate = -1;
|
||||
|
||||
|
@ -78,6 +78,14 @@ class HttpServer : trantor::NonCopyable
|
||||
{
|
||||
_server.kickoffIdleConnections(timeout);
|
||||
}
|
||||
trantor::EventLoop *getLoop()
|
||||
{
|
||||
return _server.getLoop();
|
||||
}
|
||||
std::vector<trantor::EventLoop *> getIoLoops()
|
||||
{
|
||||
return _server.getIoLoops();
|
||||
}
|
||||
void start();
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "FiltersFunction.h"
|
||||
#include "HttpSimpleControllersRouter.h"
|
||||
#include "HttpAppFrameworkImpl.h"
|
||||
#include "SpinLock.h"
|
||||
|
||||
using namespace drogon;
|
||||
|
||||
@ -124,12 +123,7 @@ void HttpSimpleControllersRouter::doControllerHandler(SimpleControllerRouterItem
|
||||
auto &controller = item._controller;
|
||||
if (controller)
|
||||
{
|
||||
HttpResponsePtr responsePtr;
|
||||
{
|
||||
//Maybe update the _responsePtr, so we use shared_lock to protect;
|
||||
SimpleSpinLock guard(item._mutex);
|
||||
responsePtr = item._responsePtr;
|
||||
}
|
||||
HttpResponsePtr &responsePtr = item._responsePtrMap[req->getLoop()];
|
||||
if (responsePtr && (responsePtr->expiredTime() == 0 || (trantor::Date::now() < responsePtr->creationDate().after(responsePtr->expiredTime()))))
|
||||
{
|
||||
//use cached response!
|
||||
@ -154,9 +148,16 @@ void HttpSimpleControllersRouter::doControllerHandler(SimpleControllerRouterItem
|
||||
{
|
||||
//cache the response;
|
||||
std::dynamic_pointer_cast<HttpResponseImpl>(resp)->makeHeaderString();
|
||||
auto loop = req->getLoop();
|
||||
if (loop->isInLoopThread())
|
||||
{
|
||||
SimpleSpinLock guard(item._mutex);
|
||||
item._responsePtr = resp;
|
||||
item._responsePtrMap[loop] = resp;
|
||||
}
|
||||
else
|
||||
{
|
||||
loop->queueInLoop([loop, resp, &item]() {
|
||||
item._responsePtrMap[loop] = resp;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (needSetJsessionid)
|
||||
@ -186,11 +187,15 @@ void HttpSimpleControllersRouter::doControllerHandler(SimpleControllerRouterItem
|
||||
}
|
||||
}
|
||||
|
||||
void HttpSimpleControllersRouter::init()
|
||||
void HttpSimpleControllersRouter::init(const std::vector<trantor::EventLoop *> &ioLoops)
|
||||
{
|
||||
for (auto &iter : _simpCtrlMap)
|
||||
{
|
||||
auto &item = iter.second;
|
||||
item._filters = FiltersFunction::createFilters(item._filterNames);
|
||||
for (auto ioloop : ioLoops)
|
||||
{
|
||||
item._responsePtrMap[ioloop] = std::shared_ptr<HttpResponse>();
|
||||
}
|
||||
}
|
||||
}
|
@ -44,7 +44,7 @@ class HttpSimpleControllersRouter : public trantor::NonCopyable
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
void init();
|
||||
void init(const std::vector<trantor::EventLoop *> &ioLoops);
|
||||
|
||||
private:
|
||||
HttpControllersRouter &_httpCtrlsRouter;
|
||||
@ -55,9 +55,9 @@ class HttpSimpleControllersRouter : public trantor::NonCopyable
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> _filters;
|
||||
std::vector<int> _validMethodsFlags;
|
||||
std::shared_ptr<HttpSimpleControllerBase> _controller;
|
||||
std::shared_ptr<HttpResponse> _responsePtr;
|
||||
std::map<trantor::EventLoop *, std::shared_ptr<HttpResponse>> _responsePtrMap;
|
||||
//std::atomic<bool> _mutex = ATOMIC_VAR_INIT(false);
|
||||
std::atomic_flag _mutex = ATOMIC_FLAG_INIT;
|
||||
//std::atomic_flag _mutex = ATOMIC_FLAG_INIT;
|
||||
};
|
||||
std::unordered_map<std::string, SimpleControllerRouterItem> _simpCtrlMap;
|
||||
std::mutex _simpCtrlMutex;
|
||||
|
Loading…
Reference in New Issue
Block a user