iotivity 0.9.0
[platform/upstream/iotivity.git] / service / protocol-plugin / lib / cpluff / libcpluff / cpluff.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  * Core framework functions
26  */ 
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <assert.h>
33 #ifdef DLOPEN_LIBTOOL
34 #include <ltdl.h>
35 #endif
36 #include "cpluff.h"
37 #include "defines.h"
38 #include "util.h"
39 #ifdef CP_THREADS
40 #include "thread.h"
41 #endif
42 #include "internal.h"
43
44
45 /* ------------------------------------------------------------------------
46  * Variables
47  * ----------------------------------------------------------------------*/
48
49 /// Number of initializations 
50 static int initialized = 0;
51
52 #ifdef CP_THREADS
53
54 /// Framework mutex
55 static cpi_mutex_t *framework_mutex = NULL;
56
57 #elif !defined(NDEBUG)
58
59 /// Framework locking count
60 static int framework_locked = 0;
61
62 #endif
63
64 /// Fatal error handler, or NULL for default 
65 static cp_fatal_error_func_t fatal_error_handler = NULL;
66
67
68 /* ------------------------------------------------------------------------
69  * Function definitions
70  * ----------------------------------------------------------------------*/
71
72 CP_C_API const char *cp_get_version(void) {
73         return CP_VERSION;
74 }
75
76 CP_C_API const char *cp_get_host_type(void) {
77         return CP_HOST;
78 }
79
80 CP_HIDDEN void cpi_lock_framework(void) {
81 #if defined(CP_THREADS)
82         cpi_lock_mutex(framework_mutex);
83 #elif !defined(NDEBUG)
84         framework_locked++;
85 #endif
86 }
87
88 CP_HIDDEN void cpi_unlock_framework(void) {
89 #if defined(CP_THREADS)
90         cpi_unlock_mutex(framework_mutex);
91 #elif !defined(NDEBUG)
92         assert(framework_locked > 0);
93         framework_locked--;
94 #endif
95 }
96
97 static void reset(void) {
98 #ifdef CP_THREADS
99         if (framework_mutex != NULL) {
100                 cpi_destroy_mutex(framework_mutex);
101                 framework_mutex = NULL;
102         }
103 #endif
104 }
105
106 CP_C_API cp_status_t cp_init(void) {
107         cp_status_t status = CP_OK;
108         
109         // Initialize if necessary
110         do {
111                 if (!initialized) {
112                         bindtextdomain(PACKAGE, CP_DATADIR CP_FNAMESEP_STR "locale");
113 #ifdef CP_THREADS
114                         if ((framework_mutex = cpi_create_mutex()) == NULL) {
115                                 status = CP_ERR_RESOURCE;
116                                 break;
117                         }
118 #endif
119 #ifdef DLOPEN_LIBTOOL
120                         if (lt_dlinit()) {
121                                 status = CP_ERR_RESOURCE;
122                                 break;
123                         }
124 #endif
125                 }
126                 initialized++;
127         } while (0);
128         
129         // Rollback on failure
130         if (status != CP_OK) {
131                 reset();
132         }
133         
134         return status;
135 }
136
137 CP_C_API void cp_destroy(void) {
138         assert(initialized > 0);
139         initialized--;
140         if (!initialized) {
141 #ifdef CP_THREADS
142                 assert(framework_mutex == NULL || !cpi_is_mutex_locked(framework_mutex));
143 #else
144                 assert(!framework_locked);
145 #endif
146                 cpi_destroy_all_contexts();
147 #ifdef DLOPEN_LIBTOOL
148                 lt_dlexit();
149 #endif
150                 reset();
151         }
152 }
153
154 CP_C_API void cp_set_fatal_error_handler(cp_fatal_error_func_t error_handler) {
155         fatal_error_handler = error_handler;
156 }
157
158 CP_HIDDEN void cpi_fatalf(const char *msg, ...) {
159         va_list params;
160         char fmsg[256];
161                 
162         // Format message 
163         assert(msg != NULL);
164         va_start(params, msg);
165         vsnprintf(fmsg, sizeof(fmsg), msg, params);
166         va_end(params);
167         fmsg[sizeof(fmsg)/sizeof(char) - 1] = '\0';
168
169         // Call error handler or print the error message
170         if (fatal_error_handler != NULL) {
171                 fatal_error_handler(fmsg);
172         } else {
173                 fprintf(stderr, _("C-Pluff: FATAL ERROR: %s\n"), fmsg);
174         }
175         
176         // Abort if still alive 
177         abort();
178 }
179
180 CP_HIDDEN void cpi_fatal_null_arg(const char *arg, const char *func) {
181         cpi_fatalf(_("Argument %s has illegal NULL value in call to function %s."), arg, func);
182 }