Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TPluginManager.h
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Fons Rademakers 26/1/2002
3
4/*************************************************************************
5 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#ifndef ROOT_TPluginManager
13#define ROOT_TPluginManager
14
15
16//////////////////////////////////////////////////////////////////////////
17// //
18// TPluginManager //
19// //
20// This class implements a plugin library manager. It keeps track of //
21// a list of plugin handlers. A plugin handler knows which plugin //
22// library to load to get a specific class that is used to extend the //
23// functionality of a specific base class and how to create an object //
24// of this class. For example, to extend the base class TFile to be //
25// able to read SQLite files one needs to load the plugin library //
26// libRSQLite.so which defines the TSQLiteServer class. This loading //
27// should be triggered when a given URI contains a regular expression //
28// defined by the handler. //
29// Plugin handlers can be defined via macros in a list of plugin //
30// directories. With $ROOTSYS/etc/plugins the default top plugin //
31// directory specified in $ROOTSYS/etc/system.rootrc. Additional //
32// directories can be specified by adding them to the end of the list. //
33// Macros for identical plugin handlers in later directories will //
34// override previous ones (the inverse of normal search path behavior). //
35// The macros must have names like <BaseClass>/PX0_<PluginClass>.C, //
36// e.g.: //
37// TSQLServer/P20_TMySQLServer.C, etc. //
38// to allow easy sorting and grouping. If the BaseClass is in a //
39// namespace the directory must have the name NameSpace@@BaseClass as //
40// : is a reserved pathname character on some operating systems. //
41// Macros not beginning with 'P' and ending with ".C" are ignored. //
42// These macros typically look like: //
43// //
44// void P10_TDCacheFile() //
45// { //
46// gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile", //
47// "DCache", "TDCacheFile(const char*,Option_t*)"); //
48// } //
49// //
50// Plugin handlers can also be defined via resources in the .rootrc //
51// file. Although now deprecated this method still works for backward //
52// compatibility, e.g.: //
53// //
54// Plugin.TSQLServer: ^mysql: TMySQLServer MySQL "<constructor>" //
55// +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL "<constructor>" //
56// Plugin.TVirtualFitter: * TFitter Minuit "TFitter(Int_t)" //
57// //
58// Where the + in front of Plugin.TSQLServer says that it extends the //
59// existing definition of TSQLServer, useful when there is more than //
60// one plugin that can extend the same base class. The "<constructor>" //
61// should be the constructor or a static method that generates an //
62// instance of the specified class. Global methods should start with //
63// "::" in their name, like "::CreateFitter()". //
64// Instead of being a shared library a plugin can also be a CINT //
65// script, so instead of libDialog.so one can have Dialog.C. //
66// The * is a placeholder in case there is no need for a URI to //
67// differentiate between different plugins for the same base class. //
68// For the default plugins see $ROOTSYS/etc/system.rootrc. //
69// //
70// Plugin handlers can also be registered at run time, e.g.: //
71// //
72// gPluginMgr->AddHandler("TSQLServer", "^sqlite:", //
73// "TSQLiteServer", "RSQLite", //
74// "TSQLiteServer(const char*,const char*,const char*)"); //
75// //
76// A list of currently defined handlers can be printed using: //
77// //
78// gPluginMgr->Print(); // use option="a" to see ctors //
79// //
80// The use of the plugin library manager removes all textual references //
81// to hard-coded class and library names and the resulting dependencies //
82// in the base classes. The plugin manager is used to extend a.o. //
83// TFile, TSQLServer, TGrid, etc. functionality. //
84// //
85//////////////////////////////////////////////////////////////////////////
86
87#include "TObject.h"
88#include "TString.h"
89#include "TMethodCall.h"
90#include "TVirtualMutex.h"
91#include "TInterpreter.h"
92#include "TClass.h"
93
94class TEnv;
95class TList;
96class THashTable;
97class TFunction;
98class TPluginManager;
99
100#include <atomic>
101#include <mutex>
102
103class TPluginHandler : public TObject {
104
105friend class TPluginManager;
106
107private:
108 using AtomicInt_t = std::atomic<Int_t>;
109
110 TString fBase; // base class which will be extended by plugin
111 TString fRegexp; // regular expression which must be matched in URI
112 TString fClass; // class to be loaded from plugin library
113 TString fPlugin; // plugin library which should contain fClass
114 TString fCtor; // ctor used to instantiate object of fClass
115 TString fOrigin; // origin of plugin handler definition
116 TMethodCall *fCallEnv; //!ctor method call environment
117 TFunction *fMethod; //!ctor method or global function
118 std::vector<std::string> fArgTupleTypeInfo; // Cached type_info name for fast comparison
119 AtomicInt_t fCanCall; //!if 1 fCallEnv is ok, -1 fCallEnv is not ok, 0 fCallEnv not setup yet.
120 Bool_t fIsMacro; // plugin is a macro and not a library
121 Bool_t fIsGlobal; // plugin ctor is a global function
122 std::once_flag fLoadStatusFlag; // plugin is loaded
123 Int_t fLoadStatus; // cached plugin load status
124
126 fBase(), fRegexp(), fClass(), fPlugin(), fCtor(), fOrigin(),
127 fCallEnv(nullptr), fMethod(nullptr), fCanCall(0), fIsMacro(kTRUE), fIsGlobal(kTRUE) { }
128 TPluginHandler(const char *base, const char *regexp,
129 const char *className, const char *pluginName,
130 const char *ctor, const char *origin);
133
135
136 const char *GetBase() const { return fBase; }
137 const char *GetRegexp() const { return fRegexp; }
138 const char *GetPlugin() const { return fPlugin; }
139 const char *GetCtor() const { return fCtor; }
140 const char *GetOrigin() const { return fOrigin; }
141
142 Bool_t CanHandle(const char *base, const char *uri);
143 void SetupCallEnv();
144
146 void LoadPluginImpl();
147
148 bool CheckNameMatch(int iarg, const std::type_info &ti);
149
150 template <typename T0>
151 bool CheckExactMatch(int iarg, const T0&)
152 {
153 return CheckNameMatch(iarg, typeid(T0));
154 }
155
156 template <typename T0, typename... T>
157 bool CheckExactMatch(int iarg, const T0&, const T&... params)
158 {
159 if (CheckNameMatch(iarg, typeid(T0)))
160 return CheckExactMatch(iarg + 1, params...);
161 else
162 return false;
163 }
164
165 template <typename... T>
166 bool ExactArgMatch(const T&... params)
167 {
168 constexpr auto nargs = sizeof...(T);
169 auto name = typeid(std::tuple<T...>).name();
170 if (!fArgTupleTypeInfo[nargs - 1].empty())
171 return name == fArgTupleTypeInfo[nargs - 1];
172
174 if (!CheckExactMatch<T...>(0, params...))
175 return false;
176 fArgTupleTypeInfo[nargs - 1] = name;
177 return true;
178 }
179
180 template <typename... T> Longptr_t ExecPluginImpl(const T&... params)
181 {
182 constexpr auto nargs = sizeof...(params);
183 if (!CheckForExecPlugin((Int_t)nargs)) return 0;
184
185 Longptr_t ret;
186
187 // check if types match such that function can be called directly
188 if (ExactArgMatch<T...>(params...)) {
189 const void *args[nargs] = {&params...};
190 // locking is handled within this call, but will only be needed
191 // on the first call for initialization
192 fCallEnv->Execute(nullptr, args, nargs, &ret);
193
194 return ret;
195 }
196
197 // Fallback to slow path with type conversion for arguments.
198
199 // The fCallEnv object is shared, since the PluginHandler is a global
200 // resource ... and both SetParams and Execute ends up taking the lock
201 // individually anyway ...
202
204 fCallEnv->SetParams(params...);
205
206 fCallEnv->Execute(ret);
207
208 return ret;
209 }
210
211public:
212 const char *GetClass() const { return fClass; }
213 Int_t CheckPlugin() const;
215
216 // zero arguments case
218 {
219 if (!CheckForExecPlugin(0))
220 return 0;
221
222 Longptr_t ret;
223 // locking is handled within this call, but will only be needed
224 // on the first call for initialization
225 fCallEnv->Execute(nullptr, nullptr, 0, &ret);
226
227 return ret;
228 }
229
230 // zero arguments case
232 {
233 // For backward compatibility.
234 if ((gDebug > 1) && (nargs != 0)) {
235 Warning("ExecPlugin", "Announced number of args different from the real number of argument passed %d vs 0",
236 nargs);
237 }
238
239 return ExecPluginImpl();
240 }
241
242 template <typename... T> Longptr_t ExecPlugin(int nargs, const T&... params)
243 {
244 // For backward compatibility.
245 if ((gDebug > 1) && (nargs != (int)sizeof...(params))) {
246 Warning("ExecPlugin","Announced number of args different from the real number of argument passed %d vs %lu",
247 nargs, (unsigned long)sizeof...(params) );
248 }
249 return ExecPluginImpl<T...>(params...);
250 }
251
252 void Print(Option_t *opt = "") const override;
253
254 ClassDefOverride(TPluginHandler,3) // Handler for plugin libraries
255};
256
257
258class TPluginManager : public TObject {
259
260private:
261 TList *fHandlers; // list of plugin handlers
262 THashTable *fBasesLoaded; //! table of base classes already checked or loaded
263 Bool_t fReadingDirs; //! true if we are running LoadHandlersFromPluginDirs
264
267 void LoadHandlerMacros(const char *path);
268
269public:
272
273 void LoadHandlersFromEnv(TEnv *env);
274 void LoadHandlersFromPluginDirs(const char *base = nullptr);
275 void AddHandler(const char *base, const char *regexp,
276 const char *className, const char *pluginName,
277 const char *ctor = nullptr, const char *origin = nullptr);
278 void RemoveHandler(const char *base, const char *regexp = nullptr);
279
280 TPluginHandler *FindHandler(const char *base, const char *uri = nullptr);
281
282 void Print(Option_t *opt = "") const override;
283 Int_t WritePluginMacros(const char *dir, const char *plugin = nullptr) const;
284 Int_t WritePluginRecords(const char *envFile, const char *plugin = nullptr) const;
285
286 ClassDefOverride(TPluginManager,1) // Manager for plugin handlers
287};
288
290
291#endif
#define R__EXTERN
Definition DllImport.h:26
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
long Longptr_t
Definition RtypesCore.h:82
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassDefOverride(name, id)
Definition Rtypes.h:341
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
R__EXTERN TPluginManager * gPluginMgr
Int_t gDebug
Definition TROOT.cxx:595
#define R__LOCKGUARD(mutex)
The TEnv class reads config files, by default named .rootrc.
Definition TEnv.h:124
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
THashTable implements a hash table to store TObject's.
Definition THashTable.h:35
A doubly linked list.
Definition TList.h:38
Method or function calling interface.
Definition TMethodCall.h:37
void Execute(const char *, const char *, int *=nullptr) override
Execute method on this object with the given parameter string, e.g.
Definition TMethodCall.h:64
void SetParams(const T &... params)
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
bool CheckExactMatch(int iarg, const T0 &, const T &... params)
bool CheckNameMatch(int iarg, const std::type_info &ti)
Return true if the name of the iarg-th argument's type match type_name
const char * GetClass() const
Int_t CheckPlugin() const
Check if the plugin library for this handler exits.
Longptr_t ExecPlugin(int nargs)
TFunction * fMethod
ctor method call environment
AtomicInt_t fCanCall
const char * GetOrigin() const
std::atomic< Int_t > AtomicInt_t
void Print(Option_t *opt="") const override
Print info about the plugin handler.
Bool_t CanHandle(const char *base, const char *uri)
Check if regular expression appears in the URI, if so return kTRUE.
TPluginHandler(const TPluginHandler &)=delete
const char * GetRegexp() const
const char * GetBase() const
~TPluginHandler()
Cleanup plugin handler object.
Bool_t CheckForExecPlugin(Int_t nargs)
Check that we can properly run ExecPlugin.
Longptr_t ExecPlugin(int nargs, const T &... params)
const char * GetPlugin() const
Bool_t fIsMacro
if 1 fCallEnv is ok, -1 fCallEnv is not ok, 0 fCallEnv not setup yet.
void SetupCallEnv()
Setup ctor or static method call environment.
void LoadPluginImpl()
Load the plugin library for this handler.
bool ExactArgMatch(const T &... params)
bool CheckExactMatch(int iarg, const T0 &)
Longptr_t ExecPluginImpl()
Longptr_t ExecPluginImpl(const T &... params)
TMethodCall * fCallEnv
TPluginHandler & operator=(const TPluginHandler &)=delete
std::vector< std::string > fArgTupleTypeInfo
ctor method or global function
const char * GetCtor() const
Int_t LoadPlugin()
Load the plugin library for this handler.
std::once_flag fLoadStatusFlag
This class implements a plugin library manager.
Int_t WritePluginMacros(const char *dir, const char *plugin=nullptr) const
Write in the specified directory the plugin macros.
void AddHandler(const char *base, const char *regexp, const char *className, const char *pluginName, const char *ctor=nullptr, const char *origin=nullptr)
Add plugin handler to the list of handlers.
void Print(Option_t *opt="") const override
Print list of registered plugin handlers.
~TPluginManager()
Clean up the plugin manager.
void RemoveHandler(const char *base, const char *regexp=nullptr)
Remove handler for the specified base class and the specified regexp.
TPluginManager(const TPluginManager &)=delete
true if we are running LoadHandlersFromPluginDirs
void LoadHandlersFromEnv(TEnv *env)
Load plugin handlers specified in config file, like:
Bool_t fReadingDirs
table of base classes already checked or loaded
TPluginManager & operator=(const TPluginManager &)=delete
THashTable * fBasesLoaded
void LoadHandlerMacros(const char *path)
Load all plugin macros from the specified path/base directory.
Int_t WritePluginRecords(const char *envFile, const char *plugin=nullptr) const
Write in the specified environment config file the plugin records.
TPluginHandler * FindHandler(const char *base, const char *uri=nullptr)
Returns the handler if there exists a handler for the specified URI.
TPluginManager()
Constructor.
void LoadHandlersFromPluginDirs(const char *base=nullptr)
Load plugin handlers specified via macros in a list of plugin directories.
Basic string class.
Definition TString.h:139