SourceMod SDK  1.7
IForwardSys.h
Go to the documentation of this file.
1 
32 #ifndef _INCLUDE_SOURCEMOD_FORWARDINTERFACE_H_
33 #define _INCLUDE_SOURCEMOD_FORWARDINTERFACE_H_
34 
47 #include <IPluginSys.h>
48 #include <sp_vm_api.h>
49 
50 using namespace SourcePawn;
51 
52 #define SMINTERFACE_FORWARDMANAGER_NAME "IForwardManager"
53 #define SMINTERFACE_FORWARDMANAGER_VERSION 3
54 
55 /*
56  * There is some very important documentation at the bottom of this file.
57  * Readers interested in knowing more about the forward system, scrolling down is a must!
58  */
59 
60 namespace SourceMod
61 {
65  enum ResultType
66  {
67  Pl_Continue = 0,
68  Pl_Changed = 1,
69  Pl_Handled = 3,
70  Pl_Stop = 4,
71  };
72 
76  enum ExecType
77  {
78  ET_Ignore = 0,
79  ET_Single = 1,
80  ET_Event = 2,
81  ET_Hook = 3,
82  ET_LowEvent = 4,
83  };
84 
85  #define SP_PARAMTYPE_ANY 0
86  #define SP_PARAMFLAG_BYREF (1<<0)
87  #define SP_PARAMTYPE_CELL (1<<1)
88  #define SP_PARAMTYPE_FLOAT (2<<1)
89  #define SP_PARAMTYPE_STRING (3<<1)|SP_PARAMFLAG_BYREF
90  #define SP_PARAMTYPE_ARRAY (4<<1)|SP_PARAMFLAG_BYREF
91  #define SP_PARAMTYPE_VARARG (5<<1)
92 
96  enum ParamType
97  {
98  Param_Any = SP_PARAMTYPE_ANY,
99  Param_Cell = SP_PARAMTYPE_CELL,
100  Param_Float = SP_PARAMTYPE_FLOAT,
101  Param_String = SP_PARAMTYPE_STRING,
102  Param_Array = SP_PARAMTYPE_ARRAY,
103  Param_VarArgs = SP_PARAMTYPE_VARARG,
104  Param_CellByRef = SP_PARAMTYPE_CELL|SP_PARAMFLAG_BYREF,
105  Param_FloatByRef = SP_PARAMTYPE_FLOAT|SP_PARAMFLAG_BYREF,
106  };
107 
108  struct ByrefInfo
109  {
110  unsigned int cells;
111  cell_t *orig_addr;
112  int flags;
113  int sz_flags;
114  };
115 
117  {
118  cell_t val;
119  ByrefInfo byref;
120  ParamType pushedas;
121  };
122 
124  {
125  public:
126  virtual void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
127  {
128  }
129  };
130 
138  class IForward : public ICallable
139  {
140  public:
142  virtual ~IForward()
143  {
144  }
145  public:
151  virtual const char *GetForwardName() =0;
152 
158  virtual unsigned int GetFunctionCount() =0;
159 
165  virtual ExecType GetExecType() =0;
166 
174  virtual int Execute(cell_t *result, IForwardFilter *filter=NULL) =0;
175 
185  virtual int PushArray(cell_t *inarray, unsigned int cells, int flags=0) =0;
186  };
187 
192  {
193  public:
201  virtual bool RemoveFunction(IPluginFunction *func) =0;
202 
209  virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin) =0;
210 
220  virtual bool AddFunction(IPluginFunction *func) =0;
221 
231  virtual bool AddFunction(IPluginContext *ctx, funcid_t index) =0;
232 
241  virtual bool RemoveFunction(IPluginContext *ctx, funcid_t index) =0;
242  };
243 
248  {
249  public:
250  virtual const char *GetInterfaceName()
251  {
252  return SMINTERFACE_FORWARDMANAGER_NAME;
253  }
254  virtual unsigned int GetInterfaceVersion()
255  {
256  return SMINTERFACE_FORWARDMANAGER_VERSION;
257  }
258  virtual bool IsVersionCompatible(unsigned int version)
259  {
260  if (version < 2 || version > GetInterfaceVersion())
261  {
262  return false;
263  }
264  return true;
265  }
266  public:
282  virtual IForward *CreateForward(const char *name,
283  ExecType et,
284  unsigned int num_params,
285  const ParamType *types,
286  ...) =0;
287 
302  virtual IChangeableForward *CreateForwardEx(const char *name,
303  ExecType et,
304  int num_params,
305  const ParamType *types,
306  ...) =0;
307 
316  virtual IForward *FindForward(const char *name, IChangeableForward **ifchng) =0;
317 
323  virtual void ReleaseForward(IForward *forward) =0;
324  };
325 }
326 
327 /*
328  * In the AMX Mod X model of forwarding, each forward contained a list of pairs, each pair containing
329  * a function ID and an AMX structure. The forward structure itself did very little but hold parameter types.
330  * An execution call worked like this:
331  * - executeForward() took in a function id and a list of parameters
332  * - for each contained plugin:
333  * - the list of parameters was preprocessed and pushed
334  * - the call was made
335  * - the list was freed and copybacks were made
336  * - return
337  *
338  * The advantages to this is that the system is very easy to implement, and it's fast. The disadvantage is
339  * varargs tend to be very unforgiving and inflexible, and thus weird problems arose with casting. You also
340  * lose flexibility, type checking, and the ability to reasonably use variable arguments lists in the VM.
341  *
342  * SourceMod replaces this forward system with a far more advanced, but a bit bulkier one. The idea is that
343  * each plugin has a table of functions, and each function is an ICallable object. As well as being an ICallable,
344  * each function is an IPluginFunction. An ICallable simply describes the process of adding parameters to a
345  * function call. An IPluginFunction describes the process of actually calling a function and performing allocation,
346  * copybacks, and deallocations.
347  *
348  * A very powerful forward system emerges: a Forward is just a collection of IPluginFunctions. Thus, the same
349  * API can be easily wrapped around a simple list, and it will look transparent to the user.
350  * Advantages:
351  * 1) "SP Forwards" from AMX Mod X are simply IPluginFunctions without a collection.
352  * 2) Forwards are function based, rather than plugin based, and are thus far more flexible at runtime..
353  * 3) [2] Individual functions can be paused and more than one function from the same plugin can be hooked.
354  * 4) [2] One hook type that used to map to many SP Forwards can now be centralized as one Forward.
355  * This helps alleviate messes like Fakemeta.
356  * 5) Parameter pushing is type-checked and allows for variable arguments.
357  *
358  * Note that while #2,3,4 could be added to AMX Mod X, the real binding property is #1, which makes the system
359  * object oriented, rather than AMX Mod X, which hides the objects behind static functions. It is entirely a design
360  * issue, rather than a usability one. The interesting part is when it gets to implementation, which has to cache
361  * parameter pushing until execution. Without this, multiple function calls can be started across one plugin, which
362  * will result in heap corruption given SourcePawn's implementation.
363  *
364  * Observe the new calling process:
365  * - Each parameter is pushed into a local cache using the ICallable interface.
366  * - For each function in the collection:
367  * - Each parameter is decoded and -pushed into the function.
368  * - The call is made.
369  * - Return
370  *
371  * Astute readers will note the (minor) problems:
372  * 1) More memory is used. Specifically, rather than N params of memory, you now have N params * M plugins.
373  * This is because, again, parameters are cached both per-function and per-forward.
374  * 2) There are slightly more calls going around: one extra call for each parameter, since each push is manual.
375  *
376  * HISTORICAL NOTES:
377  * There used to be a # about copy backs.
378  * Note that originally, the Forward implementation was a thin wrapper around IForwards. It did not cache pushes,
379  * and instead immediately fired them to each internal plugin. This was to allow users to know that pointers would
380  * be immediately resolved. Unfortunately, this became extremely burdensome on the API and exposed many problems,
381  * the major (and breaking) one was that two separate Function objects cannot be in a calling process on the same
382  * plugin at once. (:TODO: perhaps prevent that in the IPlugin object?) This is because heap functions lose their order
383  * and become impossible to re-arrange without some global heap tracking mechanism. It also made iterative copy backs
384  * for arrays/references overwhelmingly complex, since each plugin had to have its memory back-patched for each copy.
385  * Therefore, this was scrapped for cached parameters (current implementation), which is the implementation AMX Mod X
386  * uses. It is both faster and works better.
387  */
388 
389 #endif //_INCLUDE_SOURCEMOD_FORWARDINTERFACE_H_
Managed Forward, same as IForward, except the collection can be modified.
Definition: IForwardSys.h:191
virtual ~IForward()
Definition: IForwardSys.h:142
Defines the interface for the Plugin System, which manages loaded plugins.
virtual unsigned int GetInterfaceVersion()
Must return an integer defining the interface's version.
Definition: IForwardSys.h:254
Defines the base functionality required by a shared interface.
Definition: IShareSys.h:92
Unmanaged Forward, abstracts calling multiple functions as "forwards," or collections of functions...
Definition: IForwardSys.h:138
Encapsulates a run-time plugin as maintained by SourceMod.
Definition: IPluginSys.h:101
Provides functions for creating/destroying managed and unmanaged forwards.
Definition: IForwardSys.h:247
virtual const char * GetInterfaceName()
Must return a string defining the interface's unique name.
Definition: IForwardSys.h:250
Definition: IForwardSys.h:123
Definition: IAdminSystem.h:63
virtual bool IsVersionCompatible(unsigned int version)
Must return whether the requested version number is backwards compatible. Note: This can be overridde...
Definition: IForwardSys.h:258
Definition: IForwardSys.h:108
Definition: IForwardSys.h:116