eina: fix api to actually work as expected.
[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 _threads_activated = EINA_FALSE;
78
79 static Eina_Lock _mutex;
80
81 /* place module init/shutdown functions here to avoid other modules
82  * calling them by mistake.
83  */
84 #define S(x) extern Eina_Bool eina_ ## x ## _init(void); \
85    extern Eina_Bool eina_ ## x ## _shutdown(void)
86    S(log);
87    S(error);
88    S(safety_checks);
89    S(magic_string);
90    S(iterator);
91    S(accessor);
92    S(array);
93    S(module);
94    S(mempool);
95    S(list);
96    S(binshare);
97    S(stringshare);
98    S(ustringshare);
99    S(matrixsparse);
100    S(convert);
101    S(counter);
102    S(benchmark);
103    S(rectangle);
104    S(strbuf);
105    S(ustrbuf);
106    S(quadtree);
107    S(simple_xml);
108    S(file);
109 #undef S
110
111 struct eina_desc_setup
112 {
113    const char *name;
114    Eina_Bool (*init)(void);
115    Eina_Bool (*shutdown)(void);
116 };
117
118 static const struct eina_desc_setup _eina_desc_setup[] = {
119 #define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
120    /* log is a special case as it needs printf */
121    S(error),
122    S(safety_checks),
123    S(magic_string),
124    S(iterator),
125    S(accessor),
126    S(array),
127    S(module),
128    S(mempool),
129    S(list),
130    S(binshare),
131    S(stringshare),
132    S(ustringshare),
133    S(matrixsparse),
134    S(convert),
135    S(counter),
136    S(benchmark),
137    S(rectangle),
138    S(strbuf),
139    S(ustrbuf),
140    S(quadtree),
141    S(simple_xml),
142    S(file)
143 #undef S
144 };
145 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
146    sizeof(_eina_desc_setup[0]);
147
148 static void
149 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
150 {
151    for (itr--; itr >= _eina_desc_setup; itr--)
152      {
153         if (!itr->shutdown())
154            ERR("Problems shutting down eina module '%s', ignored.", itr->name);
155      }
156
157    eina_log_domain_unregister(_eina_log_dom);
158    _eina_log_dom = -1;
159    eina_log_shutdown();
160 }
161
162 /**
163  * @endcond
164  */
165
166 /*============================================================================*
167 *                                 Global                                     *
168 *============================================================================*/
169
170
171 /*============================================================================*
172 *                                   API                                      *
173 *============================================================================*/
174
175 /**
176  * @var eina_version
177  * @brief Eina version (defined at configuration time)
178  */
179 EAPI Eina_Version *eina_version = &_version;
180
181 EAPI int
182 eina_init(void)
183 {
184    const struct eina_desc_setup *itr, *itr_end;
185
186    if (EINA_LIKELY(_eina_main_count > 0))
187       return ++_eina_main_count;
188
189    if (!eina_log_init())
190      {
191         fprintf(stderr, "Could not initialize eina logging system.\n");
192         return 0;
193      }
194
195    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
196    if (_eina_log_dom < 0)
197      {
198         EINA_LOG_ERR("Could not register log domain: eina");
199         eina_log_shutdown();
200         return 0;
201      }
202
203    itr = _eina_desc_setup;
204    itr_end = itr + _eina_desc_setup_len;
205    for (; itr < itr_end; itr++)
206      {
207         if (!itr->init())
208           {
209              ERR("Could not initialize eina module '%s'.", itr->name);
210              _eina_shutdown_from_desc(itr);
211              return 0;
212           }
213      }
214
215    eina_lock_new(&_mutex);
216
217    _eina_main_count = 1;
218    return 1;
219 }
220
221 EAPI int
222 eina_shutdown(void)
223 {
224    _eina_main_count--;
225    if (EINA_UNLIKELY(_eina_main_count == 0))
226      {
227         _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
228
229         eina_lock_free(&_mutex);
230      }
231
232    return _eina_main_count;
233 }
234
235
236 EAPI int
237 eina_threads_init(void)
238 {
239 #ifdef EFL_HAVE_THREADS
240    int ret;
241
242
243    eina_lock_take(&_mutex);
244    ++_eina_main_thread_count;
245    ret = _eina_main_thread_count;
246
247    if(_eina_main_thread_count > 1)
248      {
249         eina_lock_release(&_mutex);
250         return ret;
251      }
252
253    eina_share_common_threads_init();
254    eina_log_threads_init();
255    _threads_activated = EINA_TRUE;
256
257    eina_lock_release(&_mutex);
258
259    return ret;
260 #else
261    return 0;
262 #endif
263 }
264
265 EAPI int
266 eina_threads_shutdown(void)
267 {
268 #ifdef EFL_HAVE_THREADS
269    int ret;
270
271    eina_lock_take(&_mutex);
272    ret = --_eina_main_thread_count;
273    if(_eina_main_thread_count > 0)
274      {
275         eina_lock_release(&_mutex);
276         return ret;
277      }
278
279    eina_share_common_threads_shutdown();
280    eina_log_threads_shutdown();
281
282    eina_lock_release(&_mutex);
283
284    _threads_activated = EINA_FALSE;
285
286    return ret;
287 #else
288    return 0;
289 #endif
290 }
291
292 /**
293  * @}
294  */