/* * ModuleManager.cpp * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #include #include "ModuleManager.h" #include "Application.h" #include #include #include #include #ifndef _WIN32 # include #endif namespace Mad { namespace Common { const ModuleManager::ModuleHandle ModuleManager::STATIC_MODULE = 0; ModuleManager::ModuleManager(Application *application0) : application(application0) { application->getConfigManager()->registerConfigurable(this); } ModuleManager::~ModuleManager() { application->getConfigManager()->unregisterConfigurable(this); boost::shared_lock lock(mutex); while(!moduleOrder.empty()) { std::string mod = moduleOrder.top(); lock.unlock(); unloadModule(mod); lock.lock(); moduleOrder.pop(); } } void ModuleManager::configure() { std::vector entries = application->getConfigManager()->getEntries("LoadModule"); for(std::vector::iterator entry = entries.begin(); entry != entries.end(); ++entry) { if(!loadModule((*entry)->getValue().toLocale())) application->log(Core::Logger::LOG_ERROR, Core::Format("Can't load module '%1%'.") % (*entry)->getValue()); } } bool ModuleManager::loadModule(const std::string &name) { { boost::shared_lock lock(mutex); if(modules.find(name) != modules.end()) return true; } ModuleHandle handle = STATIC_MODULE; Module *mod = Modules::loadStaticModule(application, name); std::string libname = name + MODULE_SUFFIX; if(!mod) { #ifdef WIN32 handle = LoadLibrary(libname.c_str()); #else handle = dlopen(libname.c_str(), RTLD_NOW | RTLD_GLOBAL); #endif if(!handle) { #ifdef WIN32 application->log(Core::Logger::LOG_VERBOSE, Core::Format("loadModule: Can't open module: Error %1%") % GetLastError()); #else application->log(Core::Logger::LOG_VERBOSE, Core::Format("loadModule: Can't open module: %1%") % dlerror()); #endif return false; } ModuleLoadFunc loader; std::string loadername = name + "_create"; #ifdef WIN32 loader = (ModuleLoadFunc)GetProcAddress(handle, loadername.c_str()); #else *(void**)&loader = dlsym(handle, loadername.c_str()); #endif if(!loader) { application->log(Core::Logger::LOG_VERBOSE, "loadModule: Can't open module: Invalid module"); return false; } Module *mod = loader(application); if(!mod) { application->log(Core::Logger::LOG_VERBOSE, "loadModule: Can't open module: Internal module error"); return false; } } modules.insert(std::make_pair(name, std::make_pair(handle, mod))).first; moduleOrder.push(name); return true; } void ModuleManager::unloadModule(const std::string &name) { boost::upgrade_lock lock(mutex); std::map >::iterator mod = modules.find(name); if(mod == modules.end()) return; boost::upgrade_to_unique_lock upgradeLock(lock); delete mod->second.second; if(mod->second.first != STATIC_MODULE) { #ifdef WIN32 FreeLibrary(mod->second.first); #else dlclose(mod->second.first); #endif } modules.erase(mod); } } }