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