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