Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / service / protocol-plugin / lib / cpluff / libcpluff / serial.c
1 /*-------------------------------------------------------------------------
2  * C-Pluff, a plug-in framework for C
3  * Copyright 2007 Johannes Lehtinen
4  * 
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:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
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  *-----------------------------------------------------------------------*/
23
24 /** @file
25  * Serial execution implementation
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include "cpluff.h"
31 #include "internal.h"
32
33
34 /* ------------------------------------------------------------------------
35  * Data types
36  * ----------------------------------------------------------------------*/
37
38 /// A holder structure for a run function.
39 typedef struct run_func_t {
40         
41         /// The run function
42         cp_run_func_t runfunc;
43         
44         /// The registering plug-in instance
45         cp_plugin_t *plugin;
46         
47         /// Whether currently in execution
48         int in_execution;
49         
50 } run_func_t;
51
52 CP_C_API cp_status_t cp_run_function(cp_context_t *ctx, cp_run_func_t runfunc) {
53         lnode_t *node = NULL;
54         run_func_t *rf = NULL;
55         cp_status_t status = CP_OK;
56         
57         CHECK_NOT_NULL(ctx);
58         CHECK_NOT_NULL(runfunc);
59         if (ctx->plugin == NULL) {
60                 cpi_fatalf(_("Only plug-ins can register run functions."));
61         }
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."));
65         }
66         
67         cpi_lock_context(ctx);
68         cpi_check_invocation(ctx, CPI_CF_STOP | CPI_CF_LOGGER, __func__);
69         do {
70                 int found = 0;
71                 lnode_t *n;
72         
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) {
78                                 found = 1;
79                         }
80                         n = list_next(ctx->env->run_funcs, n);
81                 }
82                 if (found) {
83                         break;
84                 }
85
86                 // Allocate memory for a new run function entry
87                 if ((rf = malloc(sizeof(run_func_t))) == NULL) {
88                         status = CP_ERR_RESOURCE;
89                         break;
90                 }
91                 if ((node = lnode_create(rf)) == NULL) {
92                         status = CP_ERR_RESOURCE;
93                         break;
94                 }
95                 
96                 // Initialize run function entry
97                 memset(rf, 0, sizeof(run_func_t));
98                 rf->runfunc = runfunc;
99                 rf->plugin = ctx->plugin;
100                 
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;
105                 }
106
107         } while (0);
108
109         // Log error
110         if (status == CP_ERR_RESOURCE) {
111                 cpi_error(ctx, N_("Could not register a run function due to insufficient memory."));
112         }       
113         cpi_unlock_context(ctx);
114         
115         // Free resources on error
116         if (status != CP_OK) {
117                 if (node != NULL) {
118                         lnode_destroy(node);
119                 }
120                 if (rf != NULL) {
121                         free(rf);
122                 }
123         }
124         
125         return status;
126 }
127
128 CP_C_API void cp_run_plugins(cp_context_t *ctx) {
129         while (cp_run_plugins_step(ctx));
130 }
131
132 CP_C_API int cp_run_plugins_step(cp_context_t *ctx) {
133         int runnables;
134         
135         CHECK_NOT_NULL(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);
140                 int rerun;
141                 
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);
149                 if (rerun) {
150                         list_append(ctx->env->run_funcs, node);
151                         if (ctx->env->run_wait == NULL) {
152                                 ctx->env->run_wait = node;
153                         }
154                 } else {
155                         lnode_destroy(node);
156                         free(rf);
157                 }
158                 cpi_signal_context(ctx);
159         }
160         runnables = (ctx->env->run_wait != NULL);
161         cpi_unlock_context(ctx);
162         return runnables;
163 }
164
165 CP_HIDDEN void cpi_stop_plugin_run(cp_plugin_t *plugin) {
166         int stopped = 0;
167         cp_context_t *ctx;
168         
169         CHECK_NOT_NULL(plugin);
170         ctx = plugin->context;
171         assert(cpi_is_context_locked(ctx));
172         while (!stopped) {
173                 lnode_t *node;
174                 
175                 stopped = 1;
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);
180                         
181                         if (rf->plugin == plugin) {
182                                 if (rf->in_execution) {
183                                         stopped = 0;
184                                 } else {
185                                         if (ctx->env->run_wait == node) {
186                                                 ctx->env->run_wait = list_next(ctx->env->run_funcs, node);
187                                         }
188                                         list_delete(ctx->env->run_funcs, node);
189                                         lnode_destroy(node);
190                                         free(rf);
191                                 }
192                         }
193                         node = next_node;
194                 }
195                 
196                 // If some run functions were in execution, wait for them to finish
197                 if (!stopped) {
198                         cpi_wait_context(ctx);
199                 }
200         }
201 }