Commit 32946009 authored by Peter Eastman's avatar Peter Eastman
Browse files

Changed how plugin initialization is done to avoid initialization order problems

parent 61eed805
...@@ -229,6 +229,11 @@ private: ...@@ -229,6 +229,11 @@ private:
std::map<std::string, KernelFactory*> kernelFactories; std::map<std::string, KernelFactory*> kernelFactories;
std::map<std::string, std::string> defaultProperties; std::map<std::string, std::string> defaultProperties;
static std::vector<Platform*>& getPlatforms(); static std::vector<Platform*>& getPlatforms();
#ifdef WIN32
static std::vector<HMODULE>& getPlugins();
#else
static std::vector<void*>& getPlugins();
#endif
}; };
} // namespace OpenMM } // namespace OpenMM
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2008 Stanford University and the Authors. * * Portions copyright (c) 2009 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -33,27 +33,28 @@ ...@@ -33,27 +33,28 @@
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/** /**
* This file should be included once in each dynamic library that contains an OpenMM * This file contains declarations for initialization functions that may be defined
* plugin. The library should define a function with the signature * by plugins, and that are invoked after the plugins have been loaded. There are
* * two such functions: one for registering new Platforms, and one for adding new
* extern "C" void initOpenMMPlugin(); * KernelFactories to existing Platforms. Each of these functions is optional; most
* * plugins implement one or the other of them, but not both.
* that registers any Platforms and KernelFactories it contains. Including this file
* will cause that function to be invoked when the library is loaded.
*/ */
#if defined(OPENMM_BUILDING_SHARED_LIBRARY) /**
#if defined(WIN32) * If a plugin defines a new Platform, it should define this function. It will be
#include <windows.h> * invoked after the plugin is loaded, and should register the new Platform by
extern "C" void initOpenMMPlugin(); * calling Platform::registerPlatform().
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { */
if (ul_reason_for_call == DLL_PROCESS_ATTACH) extern "C" void registerPlatforms();
initOpenMMPlugin();
return TRUE; /**
} * If a plugin defines a new KernelFactory for an existing Platform, it should define
#else * this function. It will be invoked after the plugin is loaded, and should register
extern "C" void __attribute__((constructor)) initOpenMMPlugin(); * the new factory by calling registerKernelFactory() on the appropriate Platform object.
#endif * It is not invoked until after registerPlatforms() has been called on every plugin,
#endif * thus avoiding initialization order problems when one plugin adds a KernelFactory
* to a Platform defined by another plugin.
*/
extern "C" void registerKernelFactories();
#endif /*OPENMM_PLUGININITIALIZER_H_*/ #endif /*OPENMM_PLUGININITIALIZER_H_*/
...@@ -115,10 +115,57 @@ Kernel Platform::createKernel(const string& name, ContextImpl& context) const { ...@@ -115,10 +115,57 @@ Kernel Platform::createKernel(const string& name, ContextImpl& context) const {
} }
vector<Platform*>& Platform::getPlatforms() { vector<Platform*>& Platform::getPlatforms() {
if (getPlugins().size() > 0) {
// Initialize plugins before returning the list of platforms.
#ifdef WIN32
vector<HMODULE> plugins = getPlugins();
getPlugins().clear();
for (int i = 0; i < (int) plugins.size(); i++) {
void (*init)();
*(void **)(&init) = GetProcAddress(plugins[i], "registerPlatforms");
if (init != NULL)
(*init)();
}
for (int i = 0; i < (int) plugins.size(); i++) {
void (*init)();
*(void **)(&init) = GetProcAddress(plugins[i], "registerKernelFactories");
if (init != NULL)
(*init)();
}
#else
vector<void*> plugins = getPlugins();
getPlugins().clear();
for (int i = 0; i < (int) plugins.size(); i++) {
void (*init)();
*(void **)(&init) = dlsym(plugins[i], "registerPlatforms");
if (init != NULL)
(*init)();
}
for (int i = 0; i < (int) plugins.size(); i++) {
void (*init)();
*(void **)(&init) = dlsym(plugins[i], "registerKernelFactories");
if (init != NULL)
(*init)();
}
#endif
}
static vector<Platform*> platforms; static vector<Platform*> platforms;
return platforms; return platforms;
} }
#ifdef WIN32
vector<HMODULE>& Platform::getPlugins() {
static vector<HMODULE> plugins;
return plugins;
}
#else
vector<void*>& Platform::getPlugins() {
static vector<void*> plugins;
return plugins;
}
#endif
void Platform::registerPlatform(Platform* platform) { void Platform::registerPlatform(Platform* platform) {
getPlatforms().push_back(platform); getPlatforms().push_back(platform);
} }
...@@ -169,6 +216,7 @@ void Platform::loadPluginLibrary(const string& file) { ...@@ -169,6 +216,7 @@ void Platform::loadPluginLibrary(const string& file) {
if (handle == NULL) if (handle == NULL)
throw OpenMMException("Error loading library "+file+": "+dlerror()); throw OpenMMException("Error loading library "+file+": "+dlerror());
#endif #endif
getPlugins().push_back(handle);
} }
vector<string> Platform::loadPluginsFromDirectory(const string& directory) { vector<string> Platform::loadPluginsFromDirectory(const string& directory) {
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "CudaPlatform.h" #include "CudaPlatform.h"
#include "CudaKernelFactory.h" #include "CudaKernelFactory.h"
#include "CudaKernels.h" #include "CudaKernels.h"
#include "openmm/PluginInitializer.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
#include "kernels/gputypes.h" #include "kernels/gputypes.h"
#include "openmm/Context.h" #include "openmm/Context.h"
...@@ -39,7 +38,7 @@ using std::map; ...@@ -39,7 +38,7 @@ using std::map;
using std::string; using std::string;
using std::stringstream; using std::stringstream;
extern "C" void initOpenMMPlugin() { extern "C" void registerPlatforms() {
if (gpuIsAvailable()) if (gpuIsAvailable())
Platform::registerPlatform(new CudaPlatform()); Platform::registerPlatform(new CudaPlatform());
} }
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "OpenCLPlatform.h" #include "OpenCLPlatform.h"
#include "OpenCLKernelFactory.h" #include "OpenCLKernelFactory.h"
#include "OpenCLKernels.h" #include "OpenCLKernels.h"
#include "openmm/PluginInitializer.h"
#include "openmm/internal/ContextImpl.h" #include "openmm/internal/ContextImpl.h"
#include "openmm/Context.h" #include "openmm/Context.h"
#include "openmm/System.h" #include "openmm/System.h"
...@@ -39,7 +38,7 @@ using std::map; ...@@ -39,7 +38,7 @@ using std::map;
using std::string; using std::string;
using std::stringstream; using std::stringstream;
extern "C" void initOpenMMPlugin() { extern "C" void registerPlatforms() {
Platform::registerPlatform(new OpenCLPlatform()); Platform::registerPlatform(new OpenCLPlatform());
} }
......
...@@ -36,24 +36,7 @@ ...@@ -36,24 +36,7 @@
using namespace OpenMM; using namespace OpenMM;
// using PluginInitializer.h and initOpenMMPlugin() does not seem to work extern "C" void registerKernelFactories() {
//#include "openmm/PluginInitializer.h"
#if defined(OPENMM_BUILDING_SHARED_LIBRARY)
#if defined(WIN32)
#include <windows.h>
extern "C" void initOpenMMReferenceFreeEnergyPlugin();
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
initOpenMMReferenceFreeEnergyPlugin();
return TRUE;
}
#else
extern "C" void __attribute__((constructor)) initOpenMMReferenceFreeEnergyPlugin();
#endif
#endif
extern "C" void initOpenMMReferenceFreeEnergyPlugin() {
for( int ii = 0; ii < Platform::getNumPlatforms(); ii++ ){ for( int ii = 0; ii < Platform::getNumPlatforms(); ii++ ){
Platform& platform = Platform::getPlatform(ii); Platform& platform = Platform::getPlatform(ii);
if( platform.getName().compare( "Reference" ) == 0 ){ if( platform.getName().compare( "Reference" ) == 0 ){
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
using namespace OpenMM; using namespace OpenMM;
using namespace std; using namespace std;
extern "C" void initOpenMMPlugin() { extern "C" void registerKernelFactories() {
cout << "Initializing Normal Mode Langevin OpenMM plugin..." << endl; cout << "Initializing Normal Mode Langevin OpenMM plugin..." << endl;
// for (int p = 0; p < Platform::getNumPlatforms(); ++p) { // for (int p = 0; p < Platform::getNumPlatforms(); ++p) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment