eina_prefix: use log infrastructure.
[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 #ifdef EFL_HAVE_THREADS
32 # if !(defined(_WIN32_WCE)) && !(defined(_WIN32))
33 #  include <sys/types.h>
34 #  include <unistd.h>
35 # endif
36 #endif
37
38 #include "eina_lock.h"
39 #include "eina_config.h"
40 #include "eina_private.h"
41 #include "eina_types.h"
42 #include "eina_main.h"
43 #include "eina_error.h"
44 #include "eina_log.h"
45 #include "eina_hash.h"
46 #include "eina_binshare.h"
47 #include "eina_stringshare.h"
48 #include "eina_ustringshare.h"
49 #include "eina_list.h"
50 #include "eina_matrixsparse.h"
51 #include "eina_array.h"
52 #include "eina_counter.h"
53 #include "eina_benchmark.h"
54 #include "eina_magic.h"
55 #include "eina_rectangle.h"
56 #include "eina_safety_checks.h"
57
58 /*============================================================================*
59 *                                  Local                                     *
60 *============================================================================*/
61
62 /**
63  * @cond LOCAL
64  */
65
66 static Eina_Version _version = { VMAJ, VMIN, VMIC, VREV };
67
68 static int _eina_main_count = 0;
69 #ifdef EFL_HAVE_THREADS
70 static int _eina_main_thread_count = 0;
71 #endif
72 static int _eina_log_dom = -1;
73
74 #ifdef ERR
75 #undef ERR
76 #endif
77 #define ERR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__)
78
79 #ifdef DBG
80 #undef DBG
81 #endif
82 #define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__)
83
84 EAPI Eina_Bool _eina_threads_activated = EINA_FALSE;
85 EAPI Eina_Error EINA_ERROR_NOT_MAIN_LOOP = 0;
86
87 static const char EINA_ERROR_NOT_MAIN_LOOP_STR[] = "Main loop thread check failed.";
88
89 #ifdef EFL_HAVE_THREADS
90 # ifdef _WIN32
91 EAPI DWORD _eina_main_loop;
92 # else
93 EAPI pthread_t _eina_main_loop;
94 # endif
95 static pid_t _eina_pid;
96 #endif
97
98 #ifdef EINA_HAVE_DEBUG_THREADS
99 EAPI int _eina_threads_debug = 0;
100 EAPI pthread_mutex_t _eina_tracking_lock;
101 EAPI Eina_Inlist *_eina_tracking = NULL;
102 #endif
103
104 /* place module init/shutdown functions here to avoid other modules
105  * calling them by mistake.
106  */
107 #define S(x) extern Eina_Bool eina_ ## x ## _init(void); \
108    extern Eina_Bool eina_ ## x ## _shutdown(void)
109    S(log);
110    S(error);
111    S(safety_checks);
112    S(magic_string);
113    S(iterator);
114    S(accessor);
115    S(array);
116    S(module);
117    S(mempool);
118    S(list);
119    S(binshare);
120    S(stringshare);
121    S(ustringshare);
122    S(matrixsparse);
123    S(convert);
124    S(counter);
125    S(benchmark);
126    S(rectangle);
127    S(strbuf);
128    S(ustrbuf);
129    S(quadtree);
130    S(simple_xml);
131    S(file);
132    S(prefix);
133 #undef S
134
135 struct eina_desc_setup
136 {
137    const char *name;
138    Eina_Bool (*init)(void);
139    Eina_Bool (*shutdown)(void);
140 };
141
142 static const struct eina_desc_setup _eina_desc_setup[] = {
143 #define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
144    /* log is a special case as it needs printf */
145    S(error),
146    S(safety_checks),
147    S(magic_string),
148    S(iterator),
149    S(accessor),
150    S(array),
151    S(module),
152    S(mempool),
153    S(list),
154    S(binshare),
155    S(stringshare),
156    S(ustringshare),
157    S(matrixsparse),
158    S(convert),
159    S(counter),
160    S(benchmark),
161    S(rectangle),
162    S(strbuf),
163    S(ustrbuf),
164    S(quadtree),
165    S(simple_xml),
166    S(file),
167    S(prefix)
168 #undef S
169 };
170 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
171    sizeof(_eina_desc_setup[0]);
172
173 static void
174 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
175 {
176    for (itr--; itr >= _eina_desc_setup; itr--)
177      {
178         if (!itr->shutdown())
179            ERR("Problems shutting down eina module '%s', ignored.", itr->name);
180      }
181
182    eina_log_domain_unregister(_eina_log_dom);
183    _eina_log_dom = -1;
184    eina_log_shutdown();
185 }
186
187 /**
188  * @endcond
189  */
190
191 /*============================================================================*
192 *                                 Global                                     *
193 *============================================================================*/
194
195
196 /*============================================================================*
197 *                                   API                                      *
198 *============================================================================*/
199
200 /**
201  * @var eina_version
202  * @brief Eina version (defined at configuration time)
203  */
204 EAPI Eina_Version *eina_version = &_version;
205
206 EAPI int
207 eina_init(void)
208 {
209    const struct eina_desc_setup *itr, *itr_end;
210
211    if (EINA_LIKELY(_eina_main_count > 0))
212       return ++_eina_main_count;
213
214    if (!eina_log_init())
215      {
216         fprintf(stderr, "Could not initialize eina logging system.\n");
217         return 0;
218      }
219
220    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
221    if (_eina_log_dom < 0)
222      {
223         EINA_LOG_ERR("Could not register log domain: eina");
224         eina_log_shutdown();
225         return 0;
226      }
227
228    EINA_ERROR_NOT_MAIN_LOOP = eina_error_msg_static_register(
229          EINA_ERROR_NOT_MAIN_LOOP_STR);
230
231 #ifdef EFL_HAVE_THREADS
232 # ifdef _WIN32
233    _eina_main_loop = GetCurrentThreadId();
234 # else
235    _eina_main_loop = pthread_self();
236 # endif
237    _eina_pid = getpid();
238 #endif
239
240 #ifdef EINA_HAVE_DEBUG_THREADS
241    pthread_mutex_init(&_eina_tracking_lock, NULL);
242
243    if (getenv("EINA_DEBUG_THREADS"))
244      _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS"));
245 #endif
246
247    itr = _eina_desc_setup;
248    itr_end = itr + _eina_desc_setup_len;
249    for (; itr < itr_end; itr++)
250      {
251         if (!itr->init())
252           {
253              ERR("Could not initialize eina module '%s'.", itr->name);
254              _eina_shutdown_from_desc(itr);
255              return 0;
256           }
257      }
258
259    _eina_main_count = 1;
260    return 1;
261 }
262
263 EAPI int
264 eina_shutdown(void)
265 {
266    _eina_main_count--;
267    if (EINA_UNLIKELY(_eina_main_count == 0))
268      {
269         _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
270
271 #ifdef EINA_HAVE_DEBUG_THREADS
272         pthread_mutex_destroy(&_eina_tracking_lock);
273 #endif
274      }
275
276    return _eina_main_count;
277 }
278
279
280 EAPI int
281 eina_threads_init(void)
282 {
283 #ifdef EFL_HAVE_THREADS
284    int ret;
285
286 #ifdef EINA_HAVE_DEBUG_THREADS
287    assert(pthread_equal(_eina_main_loop, pthread_self()));
288 #endif
289
290    ++_eina_main_thread_count;
291    ret = _eina_main_thread_count;
292
293    if(_eina_main_thread_count > 1)
294      return ret;
295
296    eina_share_common_threads_init();
297    eina_log_threads_init();
298    _eina_threads_activated = EINA_TRUE;
299
300    return ret;
301 #else
302    return 0;
303 #endif
304 }
305
306 EAPI int
307 eina_threads_shutdown(void)
308 {
309 #ifdef EFL_HAVE_THREADS
310    int ret;
311
312 #ifdef EINA_HAVE_DEBUG_THREADS
313    const Eina_Lock *lk;
314
315    assert(pthread_equal(_eina_main_loop, pthread_self()));
316    assert(_eina_main_thread_count > 0);
317 #endif
318
319    ret = --_eina_main_thread_count;
320    if(_eina_main_thread_count > 0)
321      return ret;
322
323 #ifdef EINA_HAVE_DEBUG_THREADS
324    pthread_mutex_lock(&_eina_tracking_lock);
325    if (_eina_tracking)
326      {
327        fprintf(stderr, "*************************\n");
328        fprintf(stderr, "* The IMPOSSIBLE HAPPEN *\n");
329        fprintf(stderr, "* LOCK STILL TAKEN :    *\n");
330        fprintf(stderr, "*************************\n");
331        EINA_INLIST_FOREACH(_eina_tracking, lk)
332          eina_lock_debug(lk);
333        fprintf(stderr, "*************************\n");
334        abort();
335      }
336    pthread_mutex_unlock(&_eina_tracking_lock);
337 #endif
338
339    eina_share_common_threads_shutdown();
340    eina_log_threads_shutdown();
341
342    _eina_threads_activated = EINA_FALSE;
343
344    return ret;
345 #else
346    return 0;
347 #endif
348 }
349
350 EAPI Eina_Bool
351 eina_main_loop_is(void)
352 {
353 #ifdef EFL_HAVE_THREADS
354    pid_t pid = getpid();
355
356 # ifdef _WIN32
357    if (pid != _eina_pid)
358      {
359         _eina_pid = pid;
360         _eina_main_loop = GetCurrentThreadId();
361         return EINA_TRUE;
362      }
363    if (_eina_main_loop == GetCurrentThreadId())
364      return EINA_TRUE;
365 # else
366    if (pid != _eina_pid)
367      {
368         /* This is in case of a fork, but don't like the solution */
369         _eina_pid = pid;
370         _eina_main_loop = pthread_self();
371         return EINA_TRUE;
372      }
373
374    if (pthread_equal(_eina_main_loop, pthread_self()))
375      return EINA_TRUE;
376 # endif
377 #endif
378    return EINA_FALSE;
379 }
380
381 /** The purpose of this API should not be documented, it is used only by the one who know what they are doing. */
382 EAPI void
383 eina_main_loop_define(void)
384 {
385 #ifdef EFL_HAVE_THREADS
386    _eina_pid = getpid();
387 # ifdef _WIN32
388    _eina_main_loop = GetCurrentThreadId();
389 # else
390    _eina_main_loop = pthread_self();
391 # endif
392 #endif
393 }
394
395 /**
396  * @}
397  */