eina: put global into namespace and add lock abort
[profile/ivi/eina.git] / src / lib / eina_main.c
1 /* EINA - EFL data type library
2  * Copyright (C) 2008 Cedric Bail
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library;
16  * if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include <stdio.h>
24
25 #ifdef EFL_HAVE_WIN32_THREADS
26 # define WIN32_LEAN_AND_MEAN
27 # include <windows.h>
28 # undef WIN32_LEAN_AND_MEAN
29 #endif
30
31 #include "eina_config.h"
32 #include "eina_private.h"
33 #include "eina_types.h"
34 #include "eina_main.h"
35 #include "eina_error.h"
36 #include "eina_log.h"
37 #include "eina_hash.h"
38 #include "eina_binshare.h"
39 #include "eina_stringshare.h"
40 #include "eina_ustringshare.h"
41 #include "eina_list.h"
42 #include "eina_matrixsparse.h"
43 #include "eina_array.h"
44 #include "eina_counter.h"
45 #include "eina_benchmark.h"
46 #include "eina_magic.h"
47 #include "eina_rectangle.h"
48 #include "eina_safety_checks.h"
49 #include "eina_lock.h"
50
51 /*============================================================================*
52 *                                  Local                                     *
53 *============================================================================*/
54
55 /**
56  * @cond LOCAL
57  */
58
59 static Eina_Version _version = { VMAJ, VMIN, VMIC, VREV };
60
61 static int _eina_main_count = 0;
62 #ifdef EFL_HAVE_THREADS
63 static int _eina_main_thread_count = 0;
64 #endif
65 static int _eina_log_dom = -1;
66
67 #ifdef ERR
68 #undef ERR
69 #endif
70 #define ERR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__)
71
72 #ifdef DBG
73 #undef DBG
74 #endif
75 #define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__)
76
77 EAPI Eina_Bool _eina_threads_activated = EINA_FALSE;
78
79 #ifdef EINA_HAVE_DEBUG_THREADS
80 EAPI int _eina_threads_debug = 0;
81 #endif
82
83 static Eina_Lock _mutex;
84
85 /* place module init/shutdown functions here to avoid other modules
86  * calling them by mistake.
87  */
88 #define S(x) extern Eina_Bool eina_ ## x ## _init(void); \
89    extern Eina_Bool eina_ ## x ## _shutdown(void)
90    S(log);
91    S(error);
92    S(safety_checks);
93    S(magic_string);
94    S(iterator);
95    S(accessor);
96    S(array);
97    S(module);
98    S(mempool);
99    S(list);
100    S(binshare);
101    S(stringshare);
102    S(ustringshare);
103    S(matrixsparse);
104    S(convert);
105    S(counter);
106    S(benchmark);
107    S(rectangle);
108    S(strbuf);
109    S(ustrbuf);
110    S(quadtree);
111    S(simple_xml);
112    S(file);
113 #undef S
114
115 struct eina_desc_setup
116 {
117    const char *name;
118    Eina_Bool (*init)(void);
119    Eina_Bool (*shutdown)(void);
120 };
121
122 static const struct eina_desc_setup _eina_desc_setup[] = {
123 #define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
124    /* log is a special case as it needs printf */
125    S(error),
126    S(safety_checks),
127    S(magic_string),
128    S(iterator),
129    S(accessor),
130    S(array),
131    S(module),
132    S(mempool),
133    S(list),
134    S(binshare),
135    S(stringshare),
136    S(ustringshare),
137    S(matrixsparse),
138    S(convert),
139    S(counter),
140    S(benchmark),
141    S(rectangle),
142    S(strbuf),
143    S(ustrbuf),
144    S(quadtree),
145    S(simple_xml),
146    S(file)
147 #undef S
148 };
149 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
150    sizeof(_eina_desc_setup[0]);
151
152 static void
153 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
154 {
155    for (itr--; itr >= _eina_desc_setup; itr--)
156      {
157         if (!itr->shutdown())
158            ERR("Problems shutting down eina module '%s', ignored.", itr->name);
159      }
160
161    eina_log_domain_unregister(_eina_log_dom);
162    _eina_log_dom = -1;
163    eina_log_shutdown();
164 }
165
166 /**
167  * @endcond
168  */
169
170 /*============================================================================*
171 *                                 Global                                     *
172 *============================================================================*/
173
174
175 /*============================================================================*
176 *                                   API                                      *
177 *============================================================================*/
178
179 /**
180  * @var eina_version
181  * @brief Eina version (defined at configuration time)
182  */
183 EAPI Eina_Version *eina_version = &_version;
184
185 EAPI int
186 eina_init(void)
187 {
188    const struct eina_desc_setup *itr, *itr_end;
189
190    if (EINA_LIKELY(_eina_main_count > 0))
191       return ++_eina_main_count;
192
193    if (!eina_log_init())
194      {
195         fprintf(stderr, "Could not initialize eina logging system.\n");
196         return 0;
197      }
198
199    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
200    if (_eina_log_dom < 0)
201      {
202         EINA_LOG_ERR("Could not register log domain: eina");
203         eina_log_shutdown();
204         return 0;
205      }
206
207    itr = _eina_desc_setup;
208    itr_end = itr + _eina_desc_setup_len;
209    for (; itr < itr_end; itr++)
210      {
211         if (!itr->init())
212           {
213              ERR("Could not initialize eina module '%s'.", itr->name);
214              _eina_shutdown_from_desc(itr);
215              return 0;
216           }
217      }
218
219    eina_lock_new(&_mutex);
220 #ifdef EINA_HAVE_DEBUG_THREADS
221    if (getenv("EINA_DEBUG_THREADS"))
222      _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS");
223 #endif
224
225    _eina_main_count = 1;
226    return 1;
227 }
228
229 EAPI int
230 eina_shutdown(void)
231 {
232    _eina_main_count--;
233    if (EINA_UNLIKELY(_eina_main_count == 0))
234      {
235         _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
236
237         eina_lock_free(&_mutex);
238      }
239
240    return _eina_main_count;
241 }
242
243
244 EAPI int
245 eina_threads_init(void)
246 {
247 #ifdef EFL_HAVE_THREADS
248    int ret;
249
250
251    eina_lock_take(&_mutex);
252    ++_eina_main_thread_count;
253    ret = _eina_main_thread_count;
254
255    if(_eina_main_thread_count > 1)
256      {
257         eina_lock_release(&_mutex);
258         return ret;
259      }
260
261    eina_share_common_threads_init();
262    eina_log_threads_init();
263    _eina_threads_activated = EINA_TRUE;
264
265    eina_lock_release(&_mutex);
266
267    return ret;
268 #else
269    return 0;
270 #endif
271 }
272
273 EAPI int
274 eina_threads_shutdown(void)
275 {
276 #ifdef EFL_HAVE_THREADS
277    int ret;
278
279    eina_lock_take(&_mutex);
280    ret = --_eina_main_thread_count;
281    if(_eina_main_thread_count > 0)
282      {
283         eina_lock_release(&_mutex);
284         return ret;
285      }
286
287    eina_share_common_threads_shutdown();
288    eina_log_threads_shutdown();
289
290    eina_lock_release(&_mutex);
291
292    _eina_threads_activated = EINA_FALSE;
293
294    return ret;
295 #else
296    return 0;
297 #endif
298 }
299
300 /**
301  * @}
302  */