eina: correct guard of thread code.
[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_lock.h"
32 #include "eina_config.h"
33 #include "eina_private.h"
34 #include "eina_types.h"
35 #include "eina_main.h"
36 #include "eina_error.h"
37 #include "eina_log.h"
38 #include "eina_hash.h"
39 #include "eina_binshare.h"
40 #include "eina_stringshare.h"
41 #include "eina_ustringshare.h"
42 #include "eina_list.h"
43 #include "eina_matrixsparse.h"
44 #include "eina_array.h"
45 #include "eina_counter.h"
46 #include "eina_benchmark.h"
47 #include "eina_magic.h"
48 #include "eina_rectangle.h"
49 #include "eina_safety_checks.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_THREADS
80 # ifdef _WIN32_WCE
81 #  warning "no way to know the main loop thread id yet on Windows CE !"
82 # elif defined(_WIN32)
83 #  warning "no way to know the main loop thread id yet on Windows !"
84 # else
85 EAPI pthread_t _eina_main_loop;;
86 # endif
87 #endif
88
89 #ifdef EINA_HAVE_DEBUG_THREADS
90 EAPI int _eina_threads_debug = 0;
91 EAPI pthread_mutex_t _eina_tracking_lock;
92 EAPI Eina_Inlist *_eina_tracking = NULL;
93 #endif
94
95 /* place module init/shutdown functions here to avoid other modules
96  * calling them by mistake.
97  */
98 #define S(x) extern Eina_Bool eina_ ## x ## _init(void); \
99    extern Eina_Bool eina_ ## x ## _shutdown(void)
100    S(log);
101    S(error);
102    S(safety_checks);
103    S(magic_string);
104    S(iterator);
105    S(accessor);
106    S(array);
107    S(module);
108    S(mempool);
109    S(list);
110    S(binshare);
111    S(stringshare);
112    S(ustringshare);
113    S(matrixsparse);
114    S(convert);
115    S(counter);
116    S(benchmark);
117    S(rectangle);
118    S(strbuf);
119    S(ustrbuf);
120    S(quadtree);
121    S(simple_xml);
122    S(file);
123 #undef S
124
125 struct eina_desc_setup
126 {
127    const char *name;
128    Eina_Bool (*init)(void);
129    Eina_Bool (*shutdown)(void);
130 };
131
132 static const struct eina_desc_setup _eina_desc_setup[] = {
133 #define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
134    /* log is a special case as it needs printf */
135    S(error),
136    S(safety_checks),
137    S(magic_string),
138    S(iterator),
139    S(accessor),
140    S(array),
141    S(module),
142    S(mempool),
143    S(list),
144    S(binshare),
145    S(stringshare),
146    S(ustringshare),
147    S(matrixsparse),
148    S(convert),
149    S(counter),
150    S(benchmark),
151    S(rectangle),
152    S(strbuf),
153    S(ustrbuf),
154    S(quadtree),
155    S(simple_xml),
156    S(file)
157 #undef S
158 };
159 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
160    sizeof(_eina_desc_setup[0]);
161
162 static void
163 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
164 {
165    for (itr--; itr >= _eina_desc_setup; itr--)
166      {
167         if (!itr->shutdown())
168            ERR("Problems shutting down eina module '%s', ignored.", itr->name);
169      }
170
171    eina_log_domain_unregister(_eina_log_dom);
172    _eina_log_dom = -1;
173    eina_log_shutdown();
174 }
175
176 /**
177  * @endcond
178  */
179
180 /*============================================================================*
181 *                                 Global                                     *
182 *============================================================================*/
183
184
185 /*============================================================================*
186 *                                   API                                      *
187 *============================================================================*/
188
189 /**
190  * @var eina_version
191  * @brief Eina version (defined at configuration time)
192  */
193 EAPI Eina_Version *eina_version = &_version;
194
195 EAPI int
196 eina_init(void)
197 {
198    const struct eina_desc_setup *itr, *itr_end;
199
200    if (EINA_LIKELY(_eina_main_count > 0))
201       return ++_eina_main_count;
202
203    if (!eina_log_init())
204      {
205         fprintf(stderr, "Could not initialize eina logging system.\n");
206         return 0;
207      }
208
209    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
210    if (_eina_log_dom < 0)
211      {
212         EINA_LOG_ERR("Could not register log domain: eina");
213         eina_log_shutdown();
214         return 0;
215      }
216
217 #ifdef EINA_HAVE_THREADS
218 # if !(defined(_WIN32_WCE)) && !(defined(_WIN32))
219    _eina_main_loop = pthread_self();
220 # endif
221 #endif
222
223 #ifdef EINA_HAVE_DEBUG_THREADS
224    pthread_mutex_init(&_eina_tracking_lock, NULL);
225
226    if (getenv("EINA_DEBUG_THREADS"))
227      _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS"));
228 #endif
229
230    itr = _eina_desc_setup;
231    itr_end = itr + _eina_desc_setup_len;
232    for (; itr < itr_end; itr++)
233      {
234         if (!itr->init())
235           {
236              ERR("Could not initialize eina module '%s'.", itr->name);
237              _eina_shutdown_from_desc(itr);
238              return 0;
239           }
240      }
241
242    _eina_main_count = 1;
243    return 1;
244 }
245
246 EAPI int
247 eina_shutdown(void)
248 {
249    _eina_main_count--;
250    if (EINA_UNLIKELY(_eina_main_count == 0))
251      {
252         _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
253
254 #ifdef EINA_HAVE_DEBUG_THREADS
255         pthread_mutex_destroy(&_eina_tracking_lock);
256 #endif
257      }
258
259    return _eina_main_count;
260 }
261
262
263 EAPI int
264 eina_threads_init(void)
265 {
266 #ifdef EFL_HAVE_THREADS
267    int ret;
268
269 #ifdef EINA_HAVE_DEBUG_THREADS
270    assert(pthread_equal(_eina_main_loop, pthread_self()));
271 #endif
272
273    ++_eina_main_thread_count;
274    ret = _eina_main_thread_count;
275
276    if(_eina_main_thread_count > 1)
277      return ret;
278
279    eina_share_common_threads_init();
280    eina_log_threads_init();
281    _eina_threads_activated = EINA_TRUE;
282
283    return ret;
284 #else
285    return 0;
286 #endif
287 }
288
289 EAPI int
290 eina_threads_shutdown(void)
291 {
292 #ifdef EFL_HAVE_THREADS
293    int ret;
294
295 #ifdef EINA_HAVE_DEBUG_THREADS
296    const Eina_Lock *lk;
297
298    assert(pthread_equal(_eina_main_loop, pthread_self()));
299    assert(_eina_main_thread_count > 0);
300 #endif
301
302    ret = --_eina_main_thread_count;
303    if(_eina_main_thread_count > 0)
304      return ret;
305
306 #ifdef EINA_HAVE_DEBUG_THREADS
307    pthread_mutex_lock(&_eina_tracking_lock);
308    if (_eina_tracking)
309      {
310        fprintf(stderr, "*************************\n");
311        fprintf(stderr, "* The IMPOSSIBLE HAPPEN *\n");
312        fprintf(stderr, "* LOCK STILL TAKEN :    *\n");
313        fprintf(stderr, "*************************\n");
314        EINA_INLIST_FOREACH(_eina_tracking, lk)
315          eina_lock_debug(lk);
316        fprintf(stderr, "*************************\n");
317        abort();
318      }
319    pthread_mutex_unlock(&_eina_tracking_lock);
320 #endif
321
322    eina_share_common_threads_shutdown();
323    eina_log_threads_shutdown();
324
325    _eina_threads_activated = EINA_FALSE;
326
327    return ret;
328 #else
329    return 0;
330 #endif
331 }
332
333 EAPI Eina_Bool
334 eina_main_loop_is(void)
335 {
336 #ifdef EINA_HAVE_THREADS
337    /* FIXME: need to check how to do this on windows */
338 # ifdef _WIN32_CE
339    return EINA_FALSE;
340 # elif defined(_WIN32)
341    return EINA_FALSE;
342 # else
343    if (pthread_equal(_eina_main_loop, pthread_self()))
344      return EINA_TRUE;
345 # endif
346 #endif
347    return EINA_FALSE;
348 }
349
350 /**
351  * @}
352  */