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