more doxy -> .h
[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 #undef S
128
129 struct eina_desc_setup
130 {
131    const char *name;
132    Eina_Bool (*init)(void);
133    Eina_Bool (*shutdown)(void);
134 };
135
136 static const struct eina_desc_setup _eina_desc_setup[] = {
137 #define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
138    /* log is a special case as it needs printf */
139    S(error),
140    S(safety_checks),
141    S(magic_string),
142    S(iterator),
143    S(accessor),
144    S(array),
145    S(module),
146    S(mempool),
147    S(list),
148    S(binshare),
149    S(stringshare),
150    S(ustringshare),
151    S(matrixsparse),
152    S(convert),
153    S(counter),
154    S(benchmark),
155    S(rectangle),
156    S(strbuf),
157    S(ustrbuf),
158    S(quadtree),
159    S(simple_xml)
160 #undef S
161 };
162 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
163    sizeof(_eina_desc_setup[0]);
164
165 static void
166 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
167 {
168    for (itr--; itr >= _eina_desc_setup; itr--)
169      {
170         if (!itr->shutdown())
171            ERR("Problems shutting down eina module '%s', ignored.", itr->name);
172      }
173
174    eina_log_domain_unregister(_eina_log_dom);
175    _eina_log_dom = -1;
176    eina_log_shutdown();
177 }
178
179 /**
180  * @endcond
181  */
182
183 /*============================================================================*
184 *                                 Global                                     *
185 *============================================================================*/
186
187
188 /*============================================================================*
189 *                                   API                                      *
190 *============================================================================*/
191
192 /**
193  * @var eina_version
194  * @brief Eina version (defined at configuration time)
195  */
196 EAPI Eina_Version *eina_version = &_version;
197
198 EAPI int
199 eina_init(void)
200 {
201    const struct eina_desc_setup *itr, *itr_end;
202
203    if (EINA_LIKELY(_eina_main_count > 0))
204       return ++_eina_main_count;
205
206    if (!eina_log_init())
207      {
208         fprintf(stderr, "Could not initialize eina logging system.\n");
209         return 0;
210      }
211
212    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
213    if (_eina_log_dom < 0)
214      {
215         EINA_LOG_ERR("Could not register log domain: eina");
216         eina_log_shutdown();
217         return 0;
218      }
219
220    itr = _eina_desc_setup;
221    itr_end = itr + _eina_desc_setup_len;
222    for (; itr < itr_end; itr++)
223      {
224         if (!itr->init())
225           {
226              ERR("Could not initialize eina module '%s'.", itr->name);
227              _eina_shutdown_from_desc(itr);
228              return 0;
229           }
230      }
231
232    _eina_main_count = 1;
233    return 1;
234 }
235
236 EAPI int
237 eina_shutdown(void)
238 {
239    _eina_main_count--;
240    if (EINA_UNLIKELY(_eina_main_count == 0))
241              _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
242
243    return _eina_main_count;
244 }
245
246
247 EAPI int
248 eina_threads_init(void)
249 {
250 #ifdef EFL_HAVE_THREADS
251    int ret;
252
253 # ifdef EFL_HAVE_WIN32_THREADS
254    if (!_mutex)
255       _mutex = CreateMutex(NULL, FALSE, NULL);
256
257    if (!_mutex)
258       return 0;
259
260 # endif
261
262    LOCK();
263    ++_eina_main_thread_count;
264    ret = _eina_main_thread_count;
265
266    if(_eina_main_thread_count > 1)
267      {
268         UNLOCK();
269         return ret;
270      }
271
272    eina_share_common_threads_init();
273    eina_log_threads_init();
274    _threads_activated = EINA_TRUE;
275
276    return ret;
277 #else
278    return 0;
279 #endif
280 }
281
282 EAPI int
283 eina_threads_shutdown(void)
284 {
285 #ifdef EFL_HAVE_THREADS
286    int ret;
287
288    LOCK();
289    ret = --_eina_main_thread_count;
290    if(_eina_main_thread_count > 0)
291      {
292         UNLOCK();
293         return ret;
294      }
295
296    eina_share_common_threads_shutdown();
297    eina_log_threads_shutdown();
298
299    _threads_activated = EINA_FALSE;
300
301    UNLOCK_FORCE();
302
303 # ifdef EFL_HAVE_WIN32_THREADS
304    if (_mutex)
305       CloseHandle(_mutex);
306
307 # endif
308
309    return ret;
310 #else
311    return 0;
312 #endif
313 }
314
315 /**
316  * @}
317  */