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