eina: add Eina_File API.
[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_POSIX_THREADS
26 # include <pthread.h>
27 #endif
28
29 #ifdef EFL_HAVE_WIN32_THREADS
30 # define WIN32_LEAN_AND_MEAN
31 # include <windows.h>
32 # undef WIN32_LEAN_AND_MEAN
33 #endif
34
35 #include "eina_config.h"
36 #include "eina_private.h"
37 #include "eina_types.h"
38 #include "eina_main.h"
39 #include "eina_error.h"
40 #include "eina_log.h"
41 #include "eina_hash.h"
42 #include "eina_binshare.h"
43 #include "eina_stringshare.h"
44 #include "eina_ustringshare.h"
45 #include "eina_list.h"
46 #include "eina_matrixsparse.h"
47 #include "eina_array.h"
48 #include "eina_counter.h"
49 #include "eina_benchmark.h"
50 #include "eina_magic.h"
51 #include "eina_rectangle.h"
52 #include "eina_safety_checks.h"
53
54 /*============================================================================*
55 *                                  Local                                     *
56 *============================================================================*/
57
58 /**
59  * @cond LOCAL
60  */
61
62 static Eina_Version _version = { VMAJ, VMIN, VMIC, VREV };
63
64 static int _eina_main_count = 0;
65 #ifdef EFL_HAVE_THREADS
66 static int _eina_main_thread_count = 0;
67 #endif
68 static int _eina_log_dom = -1;
69
70 #ifdef ERR
71 #undef ERR
72 #endif
73 #define ERR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__)
74
75 #ifdef DBG
76 #undef DBG
77 #endif
78 #define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__)
79
80 Eina_Bool _threads_activated = EINA_FALSE;
81
82 #ifdef EFL_HAVE_THREADS
83 # ifdef EFL_HAVE_POSIX_THREADS
84 static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
85 #  define LOCK() if(_threads_activated) pthread_mutex_lock(&_mutex)
86 #  define UNLOCK() if(_threads_activated) pthread_mutex_unlock(&_mutex)
87 #  define UNLOCK_FORCE() pthread_mutex_unlock(&_mutex)
88 # else /* EFL_HAVE_WIN32_THREADS */
89 static HANDLE _mutex = NULL;
90 #  define LOCK() if(_threads_activated) WaitForSingleObject(_mutex, INFINITE)
91 #  define UNLOCK() if(_threads_activated) ReleaseMutex(_mutex)
92 #  define UNLOCK_FORCE() ReleaseMutex(_mutex)
93 # endif
94 #else
95 # define LOCK() do {} while (0)
96 # define UNLOCK() do {} while (0)
97 # define UNLOCK_FORCE() do {} while (0)
98 #endif
99
100 /* place module init/shutdown functions here to avoid other modules
101  * calling them by mistake.
102  */
103 #define S(x) extern Eina_Bool eina_ ## x ## _init(void); \
104    extern Eina_Bool eina_ ## x ## _shutdown(void)
105    S(log);
106    S(error);
107    S(safety_checks);
108    S(magic_string);
109    S(iterator);
110    S(accessor);
111    S(array);
112    S(module);
113    S(mempool);
114    S(list);
115    S(binshare);
116    S(stringshare);
117    S(ustringshare);
118    S(matrixsparse);
119    S(convert);
120    S(counter);
121    S(benchmark);
122    S(rectangle);
123    S(strbuf);
124    S(ustrbuf);
125    S(quadtree);
126    S(simple_xml);
127    S(file);
128 #undef S
129
130 struct eina_desc_setup
131 {
132    const char *name;
133    Eina_Bool (*init)(void);
134    Eina_Bool (*shutdown)(void);
135 };
136
137 static const struct eina_desc_setup _eina_desc_setup[] = {
138 #define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
139    /* log is a special case as it needs printf */
140    S(error),
141    S(safety_checks),
142    S(magic_string),
143    S(iterator),
144    S(accessor),
145    S(array),
146    S(module),
147    S(mempool),
148    S(list),
149    S(binshare),
150    S(stringshare),
151    S(ustringshare),
152    S(matrixsparse),
153    S(convert),
154    S(counter),
155    S(benchmark),
156    S(rectangle),
157    S(strbuf),
158    S(ustrbuf),
159    S(quadtree),
160    S(simple_xml),
161    S(file)
162 #undef S
163 };
164 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
165    sizeof(_eina_desc_setup[0]);
166
167 static void
168 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
169 {
170    for (itr--; itr >= _eina_desc_setup; itr--)
171      {
172         if (!itr->shutdown())
173            ERR("Problems shutting down eina module '%s', ignored.", itr->name);
174      }
175
176    eina_log_domain_unregister(_eina_log_dom);
177    _eina_log_dom = -1;
178    eina_log_shutdown();
179 }
180
181 /**
182  * @endcond
183  */
184
185 /*============================================================================*
186 *                                 Global                                     *
187 *============================================================================*/
188
189
190 /*============================================================================*
191 *                                   API                                      *
192 *============================================================================*/
193
194 /**
195  * @var eina_version
196  * @brief Eina version (defined at configuration time)
197  */
198 EAPI Eina_Version *eina_version = &_version;
199
200 EAPI int
201 eina_init(void)
202 {
203    const struct eina_desc_setup *itr, *itr_end;
204
205    if (EINA_LIKELY(_eina_main_count > 0))
206       return ++_eina_main_count;
207
208    if (!eina_log_init())
209      {
210         fprintf(stderr, "Could not initialize eina logging system.\n");
211         return 0;
212      }
213
214    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
215    if (_eina_log_dom < 0)
216      {
217         EINA_LOG_ERR("Could not register log domain: eina");
218         eina_log_shutdown();
219         return 0;
220      }
221
222    itr = _eina_desc_setup;
223    itr_end = itr + _eina_desc_setup_len;
224    for (; itr < itr_end; itr++)
225      {
226         if (!itr->init())
227           {
228              ERR("Could not initialize eina module '%s'.", itr->name);
229              _eina_shutdown_from_desc(itr);
230              return 0;
231           }
232      }
233
234    _eina_main_count = 1;
235    return 1;
236 }
237
238 EAPI int
239 eina_shutdown(void)
240 {
241    _eina_main_count--;
242    if (EINA_UNLIKELY(_eina_main_count == 0))
243              _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
244
245    return _eina_main_count;
246 }
247
248
249 EAPI int
250 eina_threads_init(void)
251 {
252 #ifdef EFL_HAVE_THREADS
253    int ret;
254
255 # ifdef EFL_HAVE_WIN32_THREADS
256    if (!_mutex)
257       _mutex = CreateMutex(NULL, FALSE, NULL);
258
259    if (!_mutex)
260       return 0;
261
262 # endif
263
264    LOCK();
265    ++_eina_main_thread_count;
266    ret = _eina_main_thread_count;
267
268    if(_eina_main_thread_count > 1)
269      {
270         UNLOCK();
271         return ret;
272      }
273
274    eina_share_common_threads_init();
275    eina_log_threads_init();
276    _threads_activated = EINA_TRUE;
277
278    return ret;
279 #else
280    return 0;
281 #endif
282 }
283
284 EAPI int
285 eina_threads_shutdown(void)
286 {
287 #ifdef EFL_HAVE_THREADS
288    int ret;
289
290    LOCK();
291    ret = --_eina_main_thread_count;
292    if(_eina_main_thread_count > 0)
293      {
294         UNLOCK();
295         return ret;
296      }
297
298    eina_share_common_threads_shutdown();
299    eina_log_threads_shutdown();
300
301    _threads_activated = EINA_FALSE;
302
303    UNLOCK_FORCE();
304
305 # ifdef EFL_HAVE_WIN32_THREADS
306    if (_mutex)
307       CloseHandle(_mutex);
308
309 # endif
310
311    return ret;
312 #else
313    return 0;
314 #endif
315 }
316
317 /**
318  * @}
319  */