PLUGINS: switched plugin manager to inheritance rather than #defines

The reason for this was that I found issues where the wrong functions were called in EngineManager for single plugin operation. Rather than inserting more messy #defines, I preferred to change the PluginManager to use virtual functions, which also makes EngineManager simpler.

svn-id: r55024
This commit is contained in:
Yotam Barnoy 2010-12-23 13:38:37 +00:00
parent 401a8c355d
commit ee2b1092ab
5 changed files with 69 additions and 50 deletions

View file

@ -107,11 +107,7 @@ static const EnginePlugin *detectPlugin() {
printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str()); printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str());
printf("%s", " Looking for a plugin supporting this gameid... "); printf("%s", " Looking for a plugin supporting this gameid... ");
#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
GameDescriptor game = EngineMan.findGameOnePluginAtATime(gameid, &plugin);
#else
GameDescriptor game = EngineMan.findGame(gameid, &plugin); GameDescriptor game = EngineMan.findGame(gameid, &plugin);
#endif
if (plugin == 0) { if (plugin == 0) {
printf("failed\n"); printf("failed\n");
@ -342,14 +338,9 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
settings.erase("debugflags"); settings.erase("debugflags");
} }
#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES) PluginManager::instance().init();
// Only load non-engine plugins and first engine plugin initially in this case. PluginManager::instance().loadAllPlugins(); // load plugins for cached plugin manager
PluginManager::instance().loadNonEnginePluginsAndEnumerate();
#else
// Load the plugins.
PluginManager::instance().loadPlugins();
#endif
// If we received an invalid music parameter via command line we check this here. // If we received an invalid music parameter via command line we check this here.
// We can't check this before loading the music plugins. // We can't check this before loading the music plugins.
// On the other hand we cannot load the plugins before we know the file paths (in case of external plugins). // On the other hand we cannot load the plugins before we know the file paths (in case of external plugins).
@ -463,11 +454,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// Clear the active config domain // Clear the active config domain
ConfMan.setActiveDomain(""); ConfMan.setActiveDomain("");
// PluginManager::instance().unloadPlugins(); PluginManager::instance().loadAllPlugins(); // only for cached manager
#if !defined(ONE_PLUGIN_AT_A_TIME)
PluginManager::instance().loadPlugins();
#endif
} else { } else {
GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game")); GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game"));
} }
@ -476,7 +464,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
setupGraphics(system); setupGraphics(system);
launcherDialog(); launcherDialog();
} }
PluginManager::instance().unloadPlugins(); PluginManager::instance().unloadAllPlugins();
PluginManager::destroy(); PluginManager::destroy();
GUI::GuiManager::destroy(); GUI::GuiManager::destroy();
Common::ConfigManager::destroy(); Common::ConfigManager::destroy();

View file

@ -300,7 +300,19 @@ void FilePluginProvider::addCustomDirectories(Common::FSList &dirs) const {
#pragma mark - #pragma mark -
DECLARE_SINGLETON(PluginManager); PluginManager *PluginManager::_instance = NULL;
PluginManager &PluginManager::instance() {
if (_instance)
return *_instance;
#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
_instance = new PluginManagerUncached();
#else
_instance = new PluginManager();
#endif
return *_instance;
}
PluginManager::PluginManager() { PluginManager::PluginManager() {
// Always add the static plugin provider. // Always add the static plugin provider.
@ -309,7 +321,7 @@ PluginManager::PluginManager() {
PluginManager::~PluginManager() { PluginManager::~PluginManager() {
// Explicitly unload all loaded plugins // Explicitly unload all loaded plugins
unloadPlugins(); unloadAllPlugins();
// Delete the plugin providers // Delete the plugin providers
for (ProviderList::iterator pp = _providers.begin(); for (ProviderList::iterator pp = _providers.begin();
@ -325,8 +337,8 @@ void PluginManager::addPluginProvider(PluginProvider *pp) {
// //
// This should only be run once // This should only be run once
void PluginManager::loadNonEnginePluginsAndEnumerate() { void PluginManagerUncached::init() {
unloadPlugins(); unloadAllPlugins();
_allEnginePlugins.clear(); _allEnginePlugins.clear();
// We need to resize our pluginsInMem list to prevent fragmentation // We need to resize our pluginsInMem list to prevent fragmentation
@ -359,7 +371,7 @@ void PluginManager::loadNonEnginePluginsAndEnumerate() {
} }
} }
void PluginManager::loadFirstPlugin() { void PluginManagerUncached::loadFirstPlugin() {
unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false);
// let's try to find one we can load // let's try to find one we can load
@ -371,7 +383,7 @@ void PluginManager::loadFirstPlugin() {
} }
} }
bool PluginManager::loadNextPlugin() { bool PluginManagerUncached::loadNextPlugin() {
unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false);
for (++_currentPlugin; _currentPlugin != _allEnginePlugins.end(); ++_currentPlugin) { for (++_currentPlugin; _currentPlugin != _allEnginePlugins.end(); ++_currentPlugin) {
@ -383,7 +395,7 @@ bool PluginManager::loadNextPlugin() {
return false; // no more in list return false; // no more in list
} }
void PluginManager::loadPlugins() { void PluginManager::loadAllPlugins() {
for (ProviderList::iterator pp = _providers.begin(); for (ProviderList::iterator pp = _providers.begin();
pp != _providers.end(); pp != _providers.end();
++pp) { ++pp) {
@ -392,7 +404,7 @@ void PluginManager::loadPlugins() {
} }
} }
void PluginManager::unloadPlugins() { void PluginManager::unloadAllPlugins() {
for (int i = 0; i < PLUGIN_TYPE_MAX; i++) for (int i = 0; i < PLUGIN_TYPE_MAX; i++)
unloadPluginsExcept((PluginType)i, NULL); unloadPluginsExcept((PluginType)i, NULL);
} }
@ -456,11 +468,12 @@ void PluginManager::addToPluginsInMemList(Plugin *plugin) {
DECLARE_SINGLETON(EngineManager); DECLARE_SINGLETON(EngineManager);
GameDescriptor EngineManager::findGameOnePluginAtATime(const Common::String &gameName, const EnginePlugin **plugin) const { GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const {
GameDescriptor result; GameDescriptor result;
PluginManager::instance().loadFirstPlugin(); PluginManager::instance().loadFirstPlugin();
do { do {
result = findGame(gameName, plugin); result = findGameInLoadedPlugins(gameName, plugin);
if (!result.gameid().empty()) { if (!result.gameid().empty()) {
break; break;
} }
@ -468,7 +481,10 @@ GameDescriptor EngineManager::findGameOnePluginAtATime(const Common::String &gam
return result; return result;
} }
GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const { /**
* Find the game within the plugins loaded in memory
**/
GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const EnginePlugin **plugin) const {
// Find the GameDescriptor for this target // Find the GameDescriptor for this target
const EnginePlugin::List &plugins = getPlugins(); const EnginePlugin::List &plugins = getPlugins();
GameDescriptor result; GameDescriptor result;
@ -493,19 +509,15 @@ GameList EngineManager::detectGames(const Common::FSList &fslist) const {
GameList candidates; GameList candidates;
EnginePlugin::List plugins; EnginePlugin::List plugins;
EnginePlugin::List::const_iterator iter; EnginePlugin::List::const_iterator iter;
#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
PluginManager::instance().loadFirstPlugin(); PluginManager::instance().loadFirstPlugin();
do { do {
#endif
plugins = getPlugins(); plugins = getPlugins();
// Iterate over all known games and for each check if it might be // Iterate over all known games and for each check if it might be
// the game in the presented directory. // the game in the presented directory.
for (iter = plugins.begin(); iter != plugins.end(); ++iter) { for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
candidates.push_back((**iter)->detectGames(fslist)); candidates.push_back((**iter)->detectGames(fslist));
} }
#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
} while (PluginManager::instance().loadNextPlugin()); } while (PluginManager::instance().loadNextPlugin());
#endif
return candidates; return candidates;
} }

View file

@ -298,35 +298,58 @@ protected:
* Singleton class which manages all plugins, including loading them, * Singleton class which manages all plugins, including loading them,
* managing all Plugin class instances, and unloading them. * managing all Plugin class instances, and unloading them.
*/ */
class PluginManager : public Common::Singleton<PluginManager> { class PluginManager {
protected:
typedef Common::Array<PluginProvider *> ProviderList; typedef Common::Array<PluginProvider *> ProviderList;
private:
PluginList _pluginsInMem[PLUGIN_TYPE_MAX]; PluginList _pluginsInMem[PLUGIN_TYPE_MAX];
ProviderList _providers; ProviderList _providers;
PluginList _allEnginePlugins;
PluginList::iterator _currentPlugin;
bool tryLoadPlugin(Plugin *plugin); bool tryLoadPlugin(Plugin *plugin);
void addToPluginsInMemList(Plugin *plugin); void addToPluginsInMemList(Plugin *plugin);
friend class Common::Singleton<SingletonBaseType>; static PluginManager *_instance;
PluginManager(); PluginManager();
public: public:
~PluginManager(); virtual ~PluginManager();
static void createInstance(bool cached);
static void destroy() { delete _instance; }
static PluginManager &instance();
void addPluginProvider(PluginProvider *pp); void addPluginProvider(PluginProvider *pp);
void loadNonEnginePluginsAndEnumerate(); virtual void init() {}
void loadFirstPlugin(); virtual void loadFirstPlugin() {}
bool loadNextPlugin(); virtual bool loadNextPlugin() { return false; }
void loadPlugins(); virtual void loadAllPlugins();
void unloadPlugins(); void unloadAllPlugins();
void unloadPluginsExcept(PluginType type, const Plugin *plugin, bool deletePlugin = true); void unloadPluginsExcept(PluginType type, const Plugin *plugin, bool deletePlugin = true);
const PluginList &getPlugins(PluginType t) { return _pluginsInMem[t]; } const PluginList &getPlugins(PluginType t) { return _pluginsInMem[t]; }
}; };
/**
* Uncached version of plugin manager
* Keeps only one dynamic plugin in memory at a time
**/
class PluginManagerUncached : public PluginManager {
protected:
friend class PluginManager;
PluginList _allEnginePlugins;
PluginList::iterator _currentPlugin;
PluginManagerUncached() {}
public:
virtual void init();
virtual void loadFirstPlugin();
virtual bool loadNextPlugin();
virtual void loadAllPlugins() {} // we don't allow this
};
#endif #endif

View file

@ -231,7 +231,7 @@ private:
friend class Common::Singleton<SingletonBaseType>; friend class Common::Singleton<SingletonBaseType>;
public: public:
GameDescriptor findGameOnePluginAtATime(const Common::String &gameName, const EnginePlugin **plugin = NULL) const; GameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const EnginePlugin **plugin = NULL) const;
GameDescriptor findGame(const Common::String &gameName, const EnginePlugin **plugin = NULL) const; GameDescriptor findGame(const Common::String &gameName, const EnginePlugin **plugin = NULL) const;
GameList detectGames(const Common::FSList &fslist) const; GameList detectGames(const Common::FSList &fslist) const;
const EnginePlugin::List &getPlugins() const; const EnginePlugin::List &getPlugins() const;

View file

@ -924,11 +924,7 @@ void LauncherDialog::loadGame(int item) {
const EnginePlugin *plugin = 0; const EnginePlugin *plugin = 0;
#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
EngineMan.findGameOnePluginAtATime(gameId, &plugin);
#else
EngineMan.findGame(gameId, &plugin); EngineMan.findGame(gameId, &plugin);
#endif
String target = _domains[item]; String target = _domains[item];
target.toLowercase(); target.toLowercase();