1 /*-------------------------------------------------------------------------
2 * C-Pluff, a plug-in framework for C
3 * Copyright 2007 Johannes Lehtinen
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *-----------------------------------------------------------------------*/
25 * Serial execution implementation
34 /* ------------------------------------------------------------------------
36 * ----------------------------------------------------------------------*/
38 /// A holder structure for a run function.
39 typedef struct run_func_t {
42 cp_run_func_t runfunc;
44 /// The registering plug-in instance
47 /// Whether currently in execution
52 CP_C_API cp_status_t cp_run_function(cp_context_t *ctx, cp_run_func_t runfunc) {
54 run_func_t *rf = NULL;
55 cp_status_t status = CP_OK;
58 CHECK_NOT_NULL(runfunc);
59 if (ctx->plugin == NULL) {
60 cpi_fatalf(_("Only plug-ins can register run functions."));
62 if (ctx->plugin->state != CP_PLUGIN_ACTIVE
63 && ctx->plugin->state != CP_PLUGIN_STARTING) {
64 cpi_fatalf(_("Only starting or active plug-ins can register run functions."));
67 cpi_lock_context(ctx);
68 cpi_check_invocation(ctx, CPI_CF_STOP | CPI_CF_LOGGER, __func__);
73 // Check if already registered
74 n = list_first(ctx->env->run_funcs);
75 while (n != NULL && !found) {
76 run_func_t *r = lnode_get(n);
77 if (runfunc == r->runfunc && ctx->plugin == r->plugin) {
80 n = list_next(ctx->env->run_funcs, n);
86 // Allocate memory for a new run function entry
87 if ((rf = malloc(sizeof(run_func_t))) == NULL) {
88 status = CP_ERR_RESOURCE;
91 if ((node = lnode_create(rf)) == NULL) {
92 status = CP_ERR_RESOURCE;
96 // Initialize run function entry
97 memset(rf, 0, sizeof(run_func_t));
98 rf->runfunc = runfunc;
99 rf->plugin = ctx->plugin;
101 // Append the run function to queue
102 list_append(ctx->env->run_funcs, node);
103 if (ctx->env->run_wait == NULL) {
104 ctx->env->run_wait = node;
110 if (status == CP_ERR_RESOURCE) {
111 cpi_error(ctx, N_("Could not register a run function due to insufficient memory."));
113 cpi_unlock_context(ctx);
115 // Free resources on error
116 if (status != CP_OK) {
128 CP_C_API void cp_run_plugins(cp_context_t *ctx) {
129 while (cp_run_plugins_step(ctx));
132 CP_C_API int cp_run_plugins_step(cp_context_t *ctx) {
136 cpi_lock_context(ctx);
137 if (ctx->env->run_wait != NULL) {
138 lnode_t *node = ctx->env->run_wait;
139 run_func_t *rf = lnode_get(node);
142 ctx->env->run_wait = list_next(ctx->env->run_funcs, node);
143 rf->in_execution = 1;
144 cpi_unlock_context(ctx);
145 rerun = rf->runfunc(rf->plugin->plugin_data);
146 cpi_lock_context(ctx);
147 rf->in_execution = 0;
148 list_delete(ctx->env->run_funcs, node);
150 list_append(ctx->env->run_funcs, node);
151 if (ctx->env->run_wait == NULL) {
152 ctx->env->run_wait = node;
158 cpi_signal_context(ctx);
160 runnables = (ctx->env->run_wait != NULL);
161 cpi_unlock_context(ctx);
165 CP_HIDDEN void cpi_stop_plugin_run(cp_plugin_t *plugin) {
169 CHECK_NOT_NULL(plugin);
170 ctx = plugin->context;
171 assert(cpi_is_context_locked(ctx));
176 node = list_first(ctx->env->run_funcs);
177 while (node != NULL) {
178 run_func_t *rf = lnode_get(node);
179 lnode_t *next_node = list_next(ctx->env->run_funcs, node);
181 if (rf->plugin == plugin) {
182 if (rf->in_execution) {
185 if (ctx->env->run_wait == node) {
186 ctx->env->run_wait = list_next(ctx->env->run_funcs, node);
188 list_delete(ctx->env->run_funcs, node);
196 // If some run functions were in execution, wait for them to finish
198 cpi_wait_context(ctx);