Add the getLoop() method to the HttpAppFramework class

This commit is contained in:
antao 2019-03-26 10:45:39 +08:00
parent 798861a1cc
commit 65c101bee0
6 changed files with 79 additions and 41 deletions

View File

@ -71,8 +71,8 @@ class HttpAppFramework : public trantor::NonCopyable
///Run the event loop
/**
* Calling this method starts the IO event loops and the main loop of the application;
* Usually, the thread that calls this method is the main thread of the application;
* This method blocks the calling thread until the main loop exits.
* This method MUST be called in the main thread.
* This method blocks the main thread until the main event loop exits.
*/
virtual void run() = 0;
@ -83,7 +83,7 @@ class HttpAppFramework : public trantor::NonCopyable
/**
* Calling this method results in stopping all network IO in the
* framework and interrupting the blocking of the run() method. Usually,
* after calling this method, the application will exit.
* after calling this method, the application exits.
*
* NOTE:
* This method can be called in any thread and anywhere.
@ -91,16 +91,15 @@ class HttpAppFramework : public trantor::NonCopyable
*/
virtual void quit() = 0;
//////////////////////////////////////////////////////
// ///Get the event loop of the framework;
// /**
// * NOTE:
// * The event loop is not the network IO loop, but the main event loop
// * of the framework in which only some timer tasks are running;
// * You can run some timer tasks or other tasks in this loop;
// */
// // virtual trantor::EventLoop *loop() = 0;
///////////////////////////////////////////////////////////
///Get the main event loop of the framework;
/**
* NOTE:
* The event loop is not the network IO loop, but the main event loop
* of the framework in which only some timer tasks are running;
* User can run some timer tasks or other tasks in this loop;
* This method can be call in any thread.
*/
virtual trantor::EventLoop *getLoop() = 0;
///Load the configuration file with json format.
virtual void loadConfigFile(const std::string &fileName) = 0;
@ -130,18 +129,18 @@ class HttpAppFramework : public trantor::NonCopyable
* @param filtersAndMethods is the same as the third parameter in the above method.
*
* FOR EXAMPLE:
* app.registerHandler("/hello?username={1}",
[](const HttpRequestPtr& req,
const std::function<void (const HttpResponsePtr &)> & callback,
const std::string &name)
{
Json::Value json;
json["result"]="ok";
json["message"]=std::string("hello,")+name;
auto resp=HttpResponse::newHttpJsonResponse(json);
callback(resp);
},
{Get,"LoginFilter"});
* app.registerHandler("/hello?username={1}",
* [](const HttpRequestPtr& req,
* const std::function<void (const HttpResponsePtr &)> & callback,
* const std::string &name)
* {
* Json::Value json;
* json["result"]="ok";
* json["message"]=std::string("hello,")+name;
* auto resp=HttpResponse::newHttpJsonResponse(json);
* callback(resp);
* },
* {Get,"LoginFilter"});
*
* NOTE:
* As you can see in the above example, this method supports parameters mapping.
@ -182,6 +181,7 @@ class HttpAppFramework : public trantor::NonCopyable
}
registerHttpController(pathPattern, binder, validMethods, filters);
}
/// Register a WebSocketController into the framework.
/// The parameters of this method are the same as those in the registerHttpSimpleController() method.
virtual void registerWebSocketController(const std::string &pathName,
@ -424,9 +424,17 @@ class HttpAppFramework : public trantor::NonCopyable
#if USE_ORM
///Get a database client by @param name
/**
* NOTE:
* This method must be called after the framework has been run.
*/
virtual orm::DbClientPtr getDbClient(const std::string &name = "default") = 0;
///Get a 'fast' database client by @param name
/**
* NOTE:
* This method must be called after the framework has been run.
*/
virtual orm::DbClientPtr getFastDbClient(const std::string &name = "default") = 0;
///Create a database client

View File

@ -44,6 +44,13 @@
using namespace drogon;
using namespace std::placeholders;
///Make sure that the main event loop is initialized in the main thread.
drogon::InitBeforeMainFunction drogon::HttpAppFrameworkImpl::_initFirst([]() {
HttpAppFrameworkImpl::instance().getLoop()->runInLoop([]() {
LOG_TRACE << "Initialize the main event loop in the main thread";
});
});
static void godaemon(void)
{
printf("Initializing daemon mode\n");
@ -212,9 +219,9 @@ void HttpAppFrameworkImpl::run()
//go daemon!
godaemon();
#ifdef __linux__
loop()->resetTimerQueue();
getLoop()->resetTimerQueue();
#endif
loop()->resetAfterFork();
getLoop()->resetAfterFork();
}
//set relaunching
if (_relaunchOnError)
@ -237,7 +244,7 @@ void HttpAppFrameworkImpl::run()
sleep(1);
LOG_INFO << "start new process";
}
loop()->resetAfterFork();
getLoop()->resetAfterFork();
}
//set logger
@ -271,7 +278,7 @@ void HttpAppFrameworkImpl::run()
if (!_libFilePaths.empty())
{
_sharedLibManagerPtr = std::unique_ptr<SharedLibManager>(new SharedLibManager(loop(), _libFilePaths));
_sharedLibManagerPtr = std::unique_ptr<SharedLibManager>(new SharedLibManager(getLoop(), _libFilePaths));
}
std::vector<std::shared_ptr<HttpServer>> servers;
std::vector<std::shared_ptr<EventLoopThread>> loopThreads;
@ -399,21 +406,21 @@ void HttpAppFrameworkImpl::run()
tmpTimeout = tmpTimeout / 100;
}
}
_sessionMapPtr = std::unique_ptr<CacheMap<std::string, SessionPtr>>(new CacheMap<std::string, SessionPtr>(loop(), 1.0, wheelNum, bucketNum));
_sessionMapPtr = std::unique_ptr<CacheMap<std::string, SessionPtr>>(new CacheMap<std::string, SessionPtr>(getLoop(), 1.0, wheelNum, bucketNum));
}
else if (_sessionTimeout == 0)
{
_sessionMapPtr = std::unique_ptr<CacheMap<std::string, SessionPtr>>(new CacheMap<std::string, SessionPtr>(loop(), 0, 0, 0));
_sessionMapPtr = std::unique_ptr<CacheMap<std::string, SessionPtr>>(new CacheMap<std::string, SessionPtr>(getLoop(), 0, 0, 0));
}
}
_responseCachingMap = std::unique_ptr<CacheMap<std::string, HttpResponsePtr>>(new CacheMap<std::string, HttpResponsePtr>(loop(), 1.0, 4, 50)); //Max timeout up to about 70 days;
_responseCachingMap = std::unique_ptr<CacheMap<std::string, HttpResponsePtr>>(new CacheMap<std::string, HttpResponsePtr>(getLoop(), 1.0, 4, 50)); //Max timeout up to about 70 days;
// Let listener event loops run when everything is ready.
for (auto &loopTh : loopThreads)
{
loopTh->run();
}
loop()->loop();
getLoop()->loop();
}
#if USE_ORM
void HttpAppFrameworkImpl::createDbClients(const std::vector<trantor::EventLoop *> &ioloops)
@ -745,7 +752,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
_httpSimpleCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(sessionId));
}
trantor::EventLoop *HttpAppFrameworkImpl::loop()
trantor::EventLoop *HttpAppFrameworkImpl::getLoop()
{
static trantor::EventLoop loop;
return &loop;

View File

@ -37,6 +37,13 @@
namespace drogon
{
struct InitBeforeMainFunction
{
InitBeforeMainFunction(const std::function<void()> &func)
{
func();
}
};
class HttpAppFrameworkImpl : public HttpAppFramework
{
public:
@ -112,12 +119,12 @@ class HttpAppFrameworkImpl : public HttpAppFramework
return _running;
}
trantor::EventLoop *loop();
virtual trantor::EventLoop *getLoop() override;
virtual void quit() override
{
if (loop()->isRunning())
loop()->quit();
if (getLoop()->isRunning())
getLoop()->quit();
}
virtual void setServerHeaderField(const std::string &server) override
@ -126,7 +133,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework
assert(server.find("\r\n") == std::string::npos);
_serverHeader = "Server: " + server + "\r\n";
}
const std::string &getServerHeaderString() const
{
return _serverHeader;
@ -237,6 +244,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework
std::map<std::string, std::map<trantor::EventLoop *, orm::DbClientPtr>> _dbFastClientsMap;
void createDbClients(const std::vector<trantor::EventLoop *> &ioloops);
#endif
static InitBeforeMainFunction _initFirst;
};
} // namespace drogon

View File

@ -304,10 +304,10 @@ void HttpClientImpl::onRecvMessage(const trantor::TcpConnectionPtr &connPtr, tra
HttpClientPtr HttpClient::newHttpClient(const std::string &ip, uint16_t port, bool useSSL, trantor::EventLoop *loop)
{
bool isIpv6 = ip.find(":") == std::string::npos ? false : true;
return std::make_shared<HttpClientImpl>(loop == nullptr ? HttpAppFrameworkImpl::instance().loop() : loop, trantor::InetAddress(ip, port, isIpv6), useSSL);
return std::make_shared<HttpClientImpl>(loop == nullptr ? HttpAppFrameworkImpl::instance().getLoop() : loop, trantor::InetAddress(ip, port, isIpv6), useSSL);
}
HttpClientPtr HttpClient::newHttpClient(const std::string &hostString, trantor::EventLoop *loop)
{
return std::make_shared<HttpClientImpl>(loop == nullptr ? HttpAppFrameworkImpl::instance().loop() : loop, hostString);
return std::make_shared<HttpClientImpl>(loop == nullptr ? HttpAppFrameworkImpl::instance().getLoop() : loop, hostString);
}

View File

@ -9,4 +9,5 @@ add_executable(view_data_test HttpViewDataTest.cc)
add_executable(md5_test Md5Test.cc ../src/ssl_funcs/Md5.cc)
add_executable(http_full_date_test HttpFullDateTest.cc)
add_executable(gzip_test GzipTest.cc)
add_executable(url_codec_test UrlCodecTest.cc)
add_executable(url_codec_test UrlCodecTest.cc)
add_executable(main_loop_test MainLoopTest.cc)

14
lib/tests/MainLoopTest.cc Normal file
View File

@ -0,0 +1,14 @@
#include <drogon/drogon.h>
#include <thread>
#include <unistd.h>
int main()
{
std::thread([]() {
drogon::app().getLoop()->runEvery(1, []() {
std::cout << "!" << std::endl;
});
})
.detach();
drogon::app().run();
}