Main: allocate Instance on the stack

This commit is contained in:
Max Kellermann 2019-05-29 21:22:25 +02:00
parent 620a39afb4
commit 71a5c8b819
5 changed files with 89 additions and 86 deletions

View File

@ -33,5 +33,5 @@ idle_add(unsigned flags)
{
assert(flags != 0);
instance->EmitIdle(flags);
global_instance->EmitIdle(flags);
}

View File

@ -129,7 +129,7 @@ Context *context;
LogListener *logListener;
#endif
Instance *instance;
Instance *global_instance;
struct Config {
ReplayGainConfig replay_gain;
@ -166,14 +166,15 @@ glue_mapper_init(const ConfigData &config)
#ifdef ENABLE_DATABASE
static void
InitStorage(const ConfigData &config, EventLoop &event_loop)
InitStorage(Instance &instance, EventLoop &event_loop,
const ConfigData &config)
{
auto storage = CreateConfiguredStorage(config, event_loop);
if (storage == nullptr)
return;
CompositeStorage *composite = new CompositeStorage();
instance->storage = composite;
instance.storage = composite;
composite->Mount("", std::move(storage));
}
@ -183,18 +184,19 @@ InitStorage(const ConfigData &config, EventLoop &event_loop)
* process has been daemonized.
*/
static bool
glue_db_init_and_load(const ConfigData &config)
glue_db_init_and_load(Instance &instance, const ConfigData &config)
{
auto db = CreateConfiguredDatabase(config, instance->event_loop,
instance->io_thread.GetEventLoop(),
*instance);
auto db = CreateConfiguredDatabase(config, instance.event_loop,
instance.io_thread.GetEventLoop(),
instance);
if (!db)
return true;
if (db->GetPlugin().RequireStorage()) {
InitStorage(config, instance->io_thread.GetEventLoop());
InitStorage(instance, instance.io_thread.GetEventLoop(),
config);
if (instance->storage == nullptr) {
if (instance.storage == nullptr) {
LogDefault(config_domain,
"Found database setting without "
"music_directory - disabling database");
@ -213,25 +215,25 @@ glue_db_init_and_load(const ConfigData &config)
std::throw_with_nested(std::runtime_error("Failed to open database plugin"));
}
instance->database = std::move(db);
instance.database = std::move(db);
auto *sdb = dynamic_cast<SimpleDatabase *>(instance->database.get());
auto *sdb = dynamic_cast<SimpleDatabase *>(instance.database.get());
if (sdb == nullptr)
return true;
instance->update = new UpdateService(config,
instance->event_loop, *sdb,
static_cast<CompositeStorage &>(*instance->storage),
*instance);
instance.update = new UpdateService(config,
instance.event_loop, *sdb,
static_cast<CompositeStorage &>(*instance.storage),
instance);
/* run database update after daemonization? */
return sdb->FileExists();
}
static bool
InitDatabaseAndStorage(const ConfigData &config)
InitDatabaseAndStorage(Instance &instance, const ConfigData &config)
{
const bool create_db = !glue_db_init_and_load(config);
const bool create_db = !glue_db_init_and_load(instance, config);
return create_db;
}
@ -255,23 +257,24 @@ LoadStickerDatabase(const ConfigData &config)
#endif
static void
glue_state_file_init(const ConfigData &raw_config)
glue_state_file_init(Instance &instance, const ConfigData &raw_config)
{
StateFileConfig config(raw_config);
if (!config.IsEnabled())
return;
instance->state_file = new StateFile(std::move(config),
instance->partitions.front(),
instance->event_loop);
instance->state_file->Read();
instance.state_file = new StateFile(std::move(config),
instance.partitions.front(),
instance.event_loop);
instance.state_file->Read();
}
/**
* Initialize the decoder and player core, including the music pipe.
*/
static void
initialize_decoder_and_player(const ConfigData &config,
initialize_decoder_and_player(Instance &instance,
const ConfigData &config,
const ReplayGainConfig &replay_gain_config)
{
const ConfigParam *param;
@ -318,13 +321,13 @@ initialize_decoder_and_player(const ConfigData &config,
}
}
instance->partitions.emplace_back(*instance,
"default",
max_length,
buffered_chunks,
configured_audio_format,
replay_gain_config);
auto &partition = instance->partitions.back();
instance.partitions.emplace_back(instance,
"default",
max_length,
buffered_chunks,
configured_audio_format,
replay_gain_config);
auto &partition = instance.partitions.back();
try {
param = config.GetParam(ConfigOption::REPLAYGAIN);
@ -386,7 +389,8 @@ main(int argc, char *argv[]) noexcept
#endif
static void
mpd_main_after_fork(const ConfigData &raw_config,
mpd_main_after_fork(Instance &instance,
const ConfigData &raw_config,
const Config &config);
static inline void
@ -422,29 +426,27 @@ MainConfigured(const struct options &options, const ConfigData &raw_config)
log_init(raw_config, options.verbose, options.log_stderr);
instance = new Instance();
AtScopeExit() {
delete instance;
instance = nullptr;
};
Instance instance;
global_instance = &instance;
#ifdef ENABLE_NEIGHBOR_PLUGINS
instance->neighbors = std::make_unique<NeighborGlue>();
instance->neighbors->Init(raw_config,
instance->io_thread.GetEventLoop(),
*instance);
instance.neighbors = std::make_unique<NeighborGlue>();
instance.neighbors->Init(raw_config,
instance.io_thread.GetEventLoop(),
instance);
if (instance->neighbors->IsEmpty())
instance->neighbors.reset();
if (instance.neighbors->IsEmpty())
instance.neighbors.reset();
#endif
const unsigned max_clients =
raw_config.GetPositive(ConfigOption::MAX_CONN, 10);
instance->client_list = new ClientList(max_clients);
instance.client_list = new ClientList(max_clients);
initialize_decoder_and_player(raw_config, config.replay_gain);
initialize_decoder_and_player(instance,
raw_config, config.replay_gain);
listen_global_init(raw_config, *instance->partitions.front().listener);
listen_global_init(raw_config, *instance.partitions.front().listener);
#ifdef ENABLE_DAEMON
daemonize_set_user();
@ -452,7 +454,7 @@ MainConfigured(const struct options &options, const ConfigData &raw_config)
AtScopeExit() { daemonize_finish(); };
#endif
mpd_main_after_fork(raw_config, config);
mpd_main_after_fork(instance, raw_config, config);
}
#ifndef ANDROID
@ -484,7 +486,8 @@ int mpd_main(int argc, char *argv[]) noexcept
#endif /* !ANDROID */
static void
mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
mpd_main_after_fork(Instance &instance,
const ConfigData &raw_config, const Config &config)
{
ConfigureFS(raw_config);
AtScopeExit() { DeinitFS(); };
@ -502,17 +505,17 @@ mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
const ScopeDecoderPluginsInit decoder_plugins_init(raw_config);
#ifdef ENABLE_DATABASE
const bool create_db = InitDatabaseAndStorage(raw_config);
const bool create_db = InitDatabaseAndStorage(instance, raw_config);
#endif
#ifdef ENABLE_SQLITE
instance->sticker_database = LoadStickerDatabase(raw_config);
instance.sticker_database = LoadStickerDatabase(raw_config);
#endif
command_init();
for (auto &partition : instance->partitions) {
partition.outputs.Configure(instance->rtio_thread.GetEventLoop(),
for (auto &partition : instance.partitions) {
partition.outputs.Configure(instance.rtio_thread.GetEventLoop(),
raw_config,
config.replay_gain,
partition.pc);
@ -521,7 +524,7 @@ mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
client_manager_init(raw_config);
const ScopeInputPluginsInit input_plugins_init(raw_config,
instance->io_thread.GetEventLoop());
instance.io_thread.GetEventLoop());
const ScopePlaylistPluginsInit playlist_plugins_init(raw_config);
#ifdef ENABLE_DAEMON
@ -531,42 +534,42 @@ mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
#ifndef ANDROID
setup_log_output();
const ScopeSignalHandlersInit signal_handlers_init(instance->event_loop);
const ScopeSignalHandlersInit signal_handlers_init(instance.event_loop);
#endif
instance->io_thread.Start();
instance->rtio_thread.Start();
instance.io_thread.Start();
instance.rtio_thread.Start();
#ifdef ENABLE_NEIGHBOR_PLUGINS
if (instance->neighbors != nullptr)
instance->neighbors->Open();
if (instance.neighbors != nullptr)
instance.neighbors->Open();
AtScopeExit() {
if (instance->neighbors != nullptr)
instance->neighbors->Close();
AtScopeExit(&instance) {
if (instance.neighbors != nullptr)
instance.neighbors->Close();
};
#endif
ZeroconfInit(raw_config, instance->event_loop);
ZeroconfInit(raw_config, instance.event_loop);
#ifdef ENABLE_DATABASE
if (create_db) {
/* the database failed to load: recreate the
database */
instance->update->Enqueue("", true);
instance.update->Enqueue("", true);
}
#endif
glue_state_file_init(raw_config);
glue_state_file_init(instance, raw_config);
#ifdef ENABLE_DATABASE
if (raw_config.GetBool(ConfigOption::AUTO_UPDATE, false)) {
#ifdef ENABLE_INOTIFY
if (instance->storage != nullptr &&
instance->update != nullptr)
mpd_inotify_init(instance->event_loop,
*instance->storage,
*instance->update,
if (instance.storage != nullptr &&
instance.update != nullptr)
mpd_inotify_init(instance.event_loop,
*instance.storage,
*instance.update,
raw_config.GetUnsigned(ConfigOption::AUTO_UPDATE_DEPTH,
INT_MAX));
#else
@ -580,7 +583,7 @@ mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
/* enable all audio outputs (if not already done by
playlist_state_restore() */
for (auto &partition : instance->partitions)
for (auto &partition : instance.partitions)
partition.pc.LockUpdateAudio();
#ifdef _WIN32
@ -596,7 +599,7 @@ mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
#endif
/* run the main loop */
instance->event_loop.Run();
instance.event_loop.Run();
#ifdef _WIN32
win32_app_stopping();
@ -604,18 +607,18 @@ mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
/* cleanup */
instance->BeginShutdownUpdate();
instance.BeginShutdownUpdate();
if (instance->state_file != nullptr) {
instance->state_file->Write();
delete instance->state_file;
if (instance.state_file != nullptr) {
instance.state_file->Write();
delete instance.state_file;
}
ZeroconfDeinit();
instance->BeginShutdownPartitions();
instance.BeginShutdownPartitions();
delete instance->client_list;
delete instance.client_list;
}
#ifdef ANDROID
@ -665,8 +668,8 @@ gcc_visibility_default
JNIEXPORT void JNICALL
Java_org_musicpd_Bridge_shutdown(JNIEnv *, jclass)
{
if (instance != nullptr)
instance->Break();
if (global_instance != nullptr)
global_instance->Break();
}
#endif

View File

@ -31,7 +31,7 @@ extern Context *context;
extern LogListener *logListener;
#endif
extern Instance *instance;
extern Instance *global_instance;
#ifndef ANDROID

View File

@ -66,10 +66,10 @@ map_uri_fs(const char *uri) noexcept
assert(uri != nullptr);
assert(*uri != '/');
if (instance->storage == nullptr)
if (global_instance->storage == nullptr)
return nullptr;
const auto music_dir_fs = instance->storage->MapFS("");
const auto music_dir_fs = global_instance->storage->MapFS("");
if (music_dir_fs.IsNull())
return nullptr;
@ -84,10 +84,10 @@ std::string
map_fs_to_utf8(Path path_fs) noexcept
{
if (path_fs.IsAbsolute()) {
if (instance->storage == nullptr)
if (global_instance->storage == nullptr)
return std::string();
const auto music_dir_fs = instance->storage->MapFS("");
const auto music_dir_fs = global_instance->storage->MapFS("");
if (music_dir_fs.IsNull())
return std::string();

View File

@ -70,7 +70,7 @@ service_dispatcher(gcc_unused DWORD control, gcc_unused DWORD event_type,
switch (control) {
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
instance->Break();
global_instance->Break();
return NO_ERROR;
default:
return NO_ERROR;
@ -106,7 +106,7 @@ console_handler(DWORD event)
// regardless our thread is still active.
// If this did not happen within 3 seconds
// let's shutdown anyway.
instance->Break();
global_instance->Break();
// Under debugger it's better to wait indefinitely
// to allow debugging of shutdown code.
Sleep(IsDebuggerPresent() ? INFINITE : 3000);