aboutsummaryrefslogtreecommitdiffstats
path: root/include/plugins.h
blob: 6d4a87de8e13c68db26eaaee046d2e36ce771479 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef PTX_PLUGINS_H_INCLUDED
#define PTX_PLUGINS_H_INCLUDED

#include <stddef.h>
#include "macros.h"

typedef struct ptx__plugin_manager_tag ptx_plugin_manager_t;
typedef struct ptx__plugin_handle_tag ptx_plugin_t;

/* returns:
 * - < 0 for plugin loading error (plugin will be unloaded)
 * - 0 for successful plugin startup
 * - (don't return values greater than 0 at this time)
 * usage:
 * Function will be called with this plugin instance and the "resume" pointer.
 *
 * The "resume" pointer will be NULL if the plugin is not being resumed. For this reason, it is not advised
 * to use NULL as a flag value in the restart function itself.
 */
typedef int (ptx_plugin_init_proc_t)(ptx_plugin_t * /*plugin*/, void * /*resume*/);

enum {
  /* This plugin cannot be resumed at this time. The plugin manager will not unload it if it expects a "seamless" reload.
   * The plugin is expected to act as if this function was not called. */
  DEINIT_ERR_RESUME_UNSUPPORTED = -1,

  /* The plugin supports being resumed, but due to a transient error condition (malloc failure?) the plugin could not set itself up for
   * resuming. If a plugin returns this value to the plugin manager, it is expected to act as if the function was not called. */
  DEINIT_ERR_RESUME_FAILURE = -2,

  /* The plugin supports being resumed, but due to a transient error condition, the plugin could not set itself up for resuming.
   * Additionally, as a part of preparing to be reloaded, the plugin performed operations it could not roll back. Likely, an error
   * will be reported to the user, and the plugin will be unloaded. The plugin manager makes no assumptions about the behavior of the
   * plugin at this time. */
  DEINIT_ERR_RESUME_UNRECOVERABLE = -3,

  /* The plugin is ready to be resumed/unloaded. */
  DEINIT_OK = 0
};

/* returns:
 * - one of the values in the above enum. if the return value is anything else, the plugin manager's behavior is not defined.
 */
typedef int (ptx_plugin_deinit_proc_t)(ptx_plugin_t * /*plugin*/, void ** /*presume*/);

#define PTX_CUR_PLUGIN_VERSION (1u)

/* the fields of this struct are public. ABI changes should be marked by incrementing PTX_CUR_PLUGIN_VERSION */
struct ptx_plugin_desc
{
  size_t desc_len;
  unsigned desc_ver;
  unsigned reserved;

  ptx_plugin_init_proc_t *init_proc;
  ptx_plugin_deinit_proc_t *deinit_proc;

  const char *name;
  const char *description;
  const char *version;
};

/* for testing */
#ifdef _CLANGD
#undef PTX_PLUGIN
#define PTX_PLUGIN 1
#endif

#define PTX__INTERNAL_PLUGIN_DESC_SYM ptx__plugin_spec

#ifdef PTX_PLUGIN
#define PTX_PLUGIN_DESC_START PTX_EXPORT \
  const struct ptx_plugin_desc PTX__INTERNAL_PLUGIN_DESC_SYM = { \
    .desc_len = sizeof(struct ptx_plugin_desc), \
    .desc_ver = PTX_CUR_PLUGIN_VERSION,

#define PTX_PLUGIN_NAME(_x)        .name = _x,
#define PTX_PLUGIN_DESCRIPTION(_x) .description = _x,
#define PTX_PLUGIN_VERSION(_x)     .version = _x,

#define PTX_PLUGIN_INIT(_x)        .init_proc = _x,
#define PTX_PLUGIN_RESTART(_x)     .restart_proc = _x,

#define PTX_PLUGIN_DESC_END };
#endif

PTX_INTERNAL(ptx_plugin_manager_t *ptx_plugin_manager_new(void) ATTR_MALLOC() ATTR_MALLOC((ptx_plugin_manager_free, 1)) ATTR_WUR);
PTX_INTERNAL(void ptx_plugin_manager_free(ptx_plugin_manager_t *mgr));

PTX_INTERNAL(int ptx_plugin_manager_load_dir(ptx_plugin_manager_t *mgr, const char *dir));

/* initializes plugins which have not yet been initialized. returns the number of plugins which have been initialized and are still loaded
 * (plugins can return a failure from their initialization function, at which point the plugin will be unloaded.) */
PTX_INTERNAL(int ptx_plugin_manager_init_plugins(ptx_plugin_manager_t *mgr));

PTX_API void ptx_plugin_set_mainloop_func(ptx_plugin_t *plugin, void *func);

#endif