mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 18:13:46 +01:00
Fix local server startup and shutdown blocking the main thread
Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
parent
c3893064a3
commit
f572266f19
@ -64,6 +64,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "sky.h"
|
#include "sky.h"
|
||||||
|
#include "threading/lambda.h"
|
||||||
#include "translation.h"
|
#include "translation.h"
|
||||||
#include "util/basic_macros.h"
|
#include "util/basic_macros.h"
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
@ -1056,12 +1057,6 @@ Game::Game() :
|
|||||||
|
|
||||||
Game::~Game()
|
Game::~Game()
|
||||||
{
|
{
|
||||||
delete client;
|
|
||||||
delete soundmaker;
|
|
||||||
sound_manager.reset();
|
|
||||||
|
|
||||||
delete server; // deleted first to stop all server threads
|
|
||||||
|
|
||||||
delete hud;
|
delete hud;
|
||||||
delete camera;
|
delete camera;
|
||||||
delete quicktune;
|
delete quicktune;
|
||||||
@ -1314,6 +1309,28 @@ void Game::shutdown()
|
|||||||
sleep_ms(100);
|
sleep_ms(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete client;
|
||||||
|
delete soundmaker;
|
||||||
|
sound_manager.reset();
|
||||||
|
|
||||||
|
auto stop_thread = runInThread([=] {
|
||||||
|
delete server;
|
||||||
|
}, "ServerStop");
|
||||||
|
|
||||||
|
FpsControl fps_control;
|
||||||
|
fps_control.reset();
|
||||||
|
|
||||||
|
while (stop_thread->isRunning()) {
|
||||||
|
m_rendering_engine->run();
|
||||||
|
f32 dtime;
|
||||||
|
fps_control.limit(device, &dtime);
|
||||||
|
showOverlayMessage(N_("Shutting down..."), dtime, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_thread->rethrow();
|
||||||
|
|
||||||
|
// to be continued in Game::~Game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1419,11 +1436,33 @@ bool Game::createSingleplayerServer(const std::string &map_dir,
|
|||||||
|
|
||||||
server = new Server(map_dir, gamespec, simple_singleplayer_mode, bind_addr,
|
server = new Server(map_dir, gamespec, simple_singleplayer_mode, bind_addr,
|
||||||
false, nullptr, error_message);
|
false, nullptr, error_message);
|
||||||
server->start();
|
|
||||||
|
|
||||||
copyServerClientCache();
|
auto start_thread = runInThread([=] {
|
||||||
|
server->start();
|
||||||
|
copyServerClientCache();
|
||||||
|
}, "ServerStart");
|
||||||
|
|
||||||
return true;
|
input->clear();
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
FpsControl fps_control;
|
||||||
|
fps_control.reset();
|
||||||
|
|
||||||
|
while (start_thread->isRunning()) {
|
||||||
|
if (!m_rendering_engine->run() || input->cancelPressed())
|
||||||
|
success = false;
|
||||||
|
f32 dtime;
|
||||||
|
fps_control.limit(device, &dtime);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
showOverlayMessage(N_("Creating server..."), dtime, 5);
|
||||||
|
else
|
||||||
|
showOverlayMessage(N_("Shutting down..."), dtime, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
start_thread->rethrow();
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::copyServerClientCache()
|
void Game::copyServerClientCache()
|
||||||
|
@ -19,7 +19,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
|
64
src/threading/lambda.h
Normal file
64
src/threading/lambda.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Minetest
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include "debug.h"
|
||||||
|
#include "threading/thread.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class returned by `runInThread`.
|
||||||
|
*
|
||||||
|
* Provides the usual thread methods along with `rethrow()`.
|
||||||
|
*/
|
||||||
|
class LambdaThread : public Thread
|
||||||
|
{
|
||||||
|
friend std::unique_ptr<LambdaThread> runInThread(
|
||||||
|
const std::function<void()> &, const std::string &);
|
||||||
|
public:
|
||||||
|
/// Re-throw a caught exception, if any. Can only be called after thread exit.
|
||||||
|
void rethrow()
|
||||||
|
{
|
||||||
|
sanity_check(!isRunning());
|
||||||
|
if (m_exptr)
|
||||||
|
std::rethrow_exception(m_exptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// hide methods
|
||||||
|
LambdaThread(const std::string &name="") : Thread(name) {}
|
||||||
|
using Thread::start;
|
||||||
|
|
||||||
|
std::function<void()> m_fn;
|
||||||
|
std::exception_ptr m_exptr;
|
||||||
|
|
||||||
|
void *run()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
m_fn();
|
||||||
|
} catch(...) {
|
||||||
|
m_exptr = std::current_exception();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a lambda in a separate thread.
|
||||||
|
*
|
||||||
|
* Exceptions will be caught.
|
||||||
|
* @param fn function to run
|
||||||
|
* @param thread_name name for thread
|
||||||
|
* @return thread object of type `LambdaThread`
|
||||||
|
*/
|
||||||
|
std::unique_ptr<LambdaThread> runInThread(const std::function<void()> &fn,
|
||||||
|
const std::string &thread_name = "")
|
||||||
|
{
|
||||||
|
std::unique_ptr<LambdaThread> t(new LambdaThread(thread_name));
|
||||||
|
t->m_fn = fn;
|
||||||
|
t->start();
|
||||||
|
return t;
|
||||||
|
}
|
@ -59,6 +59,7 @@ public:
|
|||||||
Thread(const std::string &name="");
|
Thread(const std::string &name="");
|
||||||
virtual ~Thread();
|
virtual ~Thread();
|
||||||
DISABLE_CLASS_COPY(Thread)
|
DISABLE_CLASS_COPY(Thread)
|
||||||
|
// Note: class cannot be moved since other references exist
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Begins execution of a new thread at the pure virtual method Thread::run().
|
* Begins execution of a new thread at the pure virtual method Thread::run().
|
||||||
|
Loading…
Reference in New Issue
Block a user