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