Eina: Added Eina_UStrbuf.
[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 #include <stdio.h>
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #ifdef EFL_HAVE_POSIX_THREADS
26 # include <pthread.h>
27 #endif
28
29 #ifdef EFL_HAVE_WIN32_THREADS
30 # define WIN32_LEAN_AND_MEAN
31 # include <windows.h>
32 # undef WIN32_LEAN_AND_MEAN
33 #endif
34
35 #include "eina_config.h"
36 #include "eina_private.h"
37 #include "eina_types.h"
38 #include "eina_main.h"
39 #include "eina_error.h"
40 #include "eina_log.h"
41 #include "eina_hash.h"
42 #include "eina_stringshare.h"
43 #include "eina_ustringshare.h"
44 #include "eina_list.h"
45 #include "eina_matrixsparse.h"
46 #include "eina_array.h"
47 #include "eina_counter.h"
48 #include "eina_benchmark.h"
49 #include "eina_magic.h"
50 #include "eina_rectangle.h"
51 #include "eina_safety_checks.h"
52
53 static Eina_Version _version = { VMAJ, VMIN, VMIC, VREV };
54 EAPI Eina_Version *eina_version = &_version;
55
56 /*============================================================================*
57  *                                  Local                                     *
58  *============================================================================*/
59
60 /**
61  * @cond LOCAL
62  */
63
64 static int _eina_main_count = 0;
65 #ifdef EFL_HAVE_THREADS
66 static int _eina_main_thread_count = 0;
67 #endif
68 static int _eina_log_dom = -1;
69
70 #ifdef ERR
71 #undef ERR
72 #endif
73 #define ERR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__)
74
75 #ifdef DBG
76 #undef DBG
77 #endif
78 #define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__)
79
80 #ifdef EFL_HAVE_THREADS
81 static Eina_Bool _threads_activated = EINA_FALSE;
82 # ifdef EFL_HAVE_POSIX_THREADS
83 static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
84 #  define LOCK() if(_threads_activated) pthread_mutex_lock(&_mutex)
85 #  define UNLOCK() if(_threads_activated) pthread_mutex_unlock(&_mutex)
86 #  define UNLOCK_FORCE() pthread_mutex_unlock(&_mutex)
87 # else /* EFL_HAVE_WIN32_THREADS */
88 static HANDLE _mutex = NULL;
89 #  define LOCK() if(_threads_activated) WaitForSingleObject(_mutex, INFINITE)
90 #  define UNLOCK() if(_threads_activated) ReleaseMutex(_mutex)
91 #  define UNLOCK_FORCE() ReleaseMutex(_mutex)
92 # endif
93 #else
94 # define LOCK() do {} while (0)
95 # define UNLOCK() do {} while (0)
96 # define UNLOCK_FORCE() do {} while (0)
97 #endif
98
99 /* place module init/shutdown functions here to avoid other modules
100  * calling them by mistake.
101  */
102 #define S(x) extern Eina_Bool eina_##x##_init(void); extern Eina_Bool eina_##x##_shutdown(void)
103 S(log);
104 S(error);
105 S(safety_checks);
106 S(magic_string);
107 S(iterator);
108 S(accessor);
109 S(array);
110 S(module);
111 S(mempool);
112 S(list);
113 S(stringshare);
114 S(ustringshare);
115 S(matrixsparse);
116 S(convert);
117 S(counter);
118 S(benchmark);
119 S(rectangle);
120 S(strbuf);
121 S(ustrbuf);
122 S(quadtree);
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(stringshare),
145   S(ustringshare),
146   S(matrixsparse),
147   S(convert),
148   S(counter),
149   S(benchmark),
150   S(rectangle),
151   S(strbuf),
152   S(ustrbuf),
153   S(quadtree)
154 #undef S
155 };
156 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) / sizeof(_eina_desc_setup[0]);
157
158 static void
159 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
160 {
161    for (itr--; itr >= _eina_desc_setup; itr--)
162      {
163         if (!itr->shutdown())
164           ERR("Problems shutting down eina module '%s', ignored.", itr->name);
165      }
166
167    eina_log_domain_unregister(_eina_log_dom);
168    _eina_log_dom = -1;
169    eina_log_shutdown();
170 }
171
172 /**
173  * @endcond
174  */
175
176 /*============================================================================*
177  *                                 Global                                     *
178  *============================================================================*/
179
180 /*============================================================================*
181  *                                   API                                      *
182  *============================================================================*/
183
184 /**
185  * @addtogroup Eina_Main_Group Main
186  *
187  * @brief These functions provide general initialisation and shut down
188  * functions.
189  *
190  * @{
191  */
192
193 /**
194  * @brief Initialize the Eina library.
195  *
196  * @return 1 or greater on success, 0 on error.
197  *
198  * This function sets up all the eina modules. It returns 0 on
199  * failure (that is, when one of the module fails to initialize),
200  * otherwise it returns the number of times it has already been
201  * called.
202  *
203  * When Eina is not used anymore, call eina_shutdown() to shut down
204  * the Eina library.
205  */
206 EAPI int
207 eina_init(void)
208 {
209    const struct eina_desc_setup *itr, *itr_end;
210
211    if (EINA_LIKELY(_eina_main_count > 0))
212      return ++_eina_main_count;
213
214    if (!eina_log_init())
215      {
216         fprintf(stderr, "Could not initialize eina logging system.\n");
217         return 0;
218      }
219    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
220    if (_eina_log_dom < 0)
221      {
222         EINA_LOG_ERR("Could not register log domain: eina");
223         eina_log_shutdown();
224         return 0;
225      }
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 /**
244  * @brief Shut down the Eina library.
245  *
246  * @return 0 when all the modules is completely shut down, 1 or
247  * greater otherwise.
248  *
249  * This function shuts down the Eina library. It returns 0 when it has
250  * been called the same number of times than eina_init(). In that case
251  * it shut down all the Eina modules.
252  *
253  * Once this function succeeds (that is, @c 0 is returned), you must
254  * not call any of the Eina function anymore. You must call
255  * eina_init() again to use the Eina functions again.
256  */
257 EAPI int
258 eina_shutdown(void)
259 {
260    _eina_main_count--;
261    if (EINA_UNLIKELY(_eina_main_count == 0))
262      _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
263    return _eina_main_count;
264 }
265
266
267 /**
268  * @brief Initialize the mutexs of the Eina library.
269  *
270  * @return 1 or greater on success, 0 on error.
271  *
272  * This function sets up all the mutexs in all eina modules. It returns 0 on
273  * failure (that is, when one of the module fails to initialize),
274  * otherwise it returns the number of times it has already been
275  * called.
276  *
277  * When the mutexs are not used anymore, call eina_thread_shutdown() to shut down
278  * the mutexs.
279  */
280 EAPI int
281 eina_threads_init(void)
282 {
283 #ifdef EFL_HAVE_THREADS
284     int ret;
285
286 # ifdef EFL_HAVE_WIN32_THREADS
287     if (!_mutex)
288       _mutex = CreateMutex(NULL, FALSE, NULL);
289     if (!_mutex) return 0;
290 # endif
291     
292     LOCK();
293     ++_eina_main_thread_count;
294     ret = _eina_main_thread_count;
295
296     if(_eina_main_thread_count > 1)
297     {
298         UNLOCK();
299         return ret;
300     }
301
302     eina_share_common_threads_init();
303     eina_log_threads_init();
304     _threads_activated = EINA_TRUE;
305
306     return ret;
307 #else
308     return 0;
309 #endif
310 }
311
312 /**
313  * @brief Shut down mutexs in the Eina library.
314  *
315  * @return 0 when all mutexs are completely shut down, 1 or
316  * greater otherwise.
317  *
318  * This function shuts down the mutexs in the Eina library. It returns 0 when it has
319  * been called the same number of times than eina_thread_init(). In that case
320  * it shut down all the mutexs.
321  *
322  * Once this function succeeds (that is, @c 0 is returned), you must
323  * not call any of the Eina function in a thread anymore. You must call
324  * eina_thread_init() again to use the Eina functions in a thread again.
325  */
326 EAPI int
327 eina_threads_shutdown(void)
328 {
329 #ifdef EFL_HAVE_THREADS
330     int ret;
331
332     LOCK();
333     ret = --_eina_main_thread_count;
334     if(_eina_main_thread_count > 0) 
335     {
336         UNLOCK();
337         return ret; 
338     }
339
340     eina_share_common_threads_shutdown();
341     eina_log_threads_shutdown();
342
343     _threads_activated = EINA_FALSE;
344
345     UNLOCK_FORCE();
346
347 # ifdef EFL_HAVE_WIN32_THREADS
348     if (_mutex) CloseHandle(_mutex);
349 # endif
350
351     return ret;
352 #else
353     return 0;
354 #endif
355 }
356
357 /**
358  * @}
359  */