Eina: Add Eina_UStringshare and Eina_Binshare.
[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(quadtree);
122 #undef S
123
124 struct eina_desc_setup
125 {
126    const char *name;
127    Eina_Bool (*init)(void);
128    Eina_Bool (*shutdown)(void);
129 };
130
131 static const struct eina_desc_setup _eina_desc_setup[] = {
132 #define S(x) {#x, eina_##x##_init, eina_##x##_shutdown}
133   /* log is a special case as it needs printf */
134   S(error),
135   S(safety_checks),
136   S(magic_string),
137   S(iterator),
138   S(accessor),
139   S(array),
140   S(module),
141   S(mempool),
142   S(list),
143   S(stringshare),
144   S(ustringshare),
145   S(matrixsparse),
146   S(convert),
147   S(counter),
148   S(benchmark),
149   S(rectangle),
150   S(strbuf),
151   S(quadtree)
152 #undef S
153 };
154 static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) / sizeof(_eina_desc_setup[0]);
155
156 static void
157 _eina_shutdown_from_desc(const struct eina_desc_setup *itr)
158 {
159    for (itr--; itr >= _eina_desc_setup; itr--)
160      {
161         if (!itr->shutdown())
162           ERR("Problems shutting down eina module '%s', ignored.", itr->name);
163      }
164
165    eina_log_domain_unregister(_eina_log_dom);
166    _eina_log_dom = -1;
167    eina_log_shutdown();
168 }
169
170 /**
171  * @endcond
172  */
173
174 /*============================================================================*
175  *                                 Global                                     *
176  *============================================================================*/
177
178 /*============================================================================*
179  *                                   API                                      *
180  *============================================================================*/
181
182 /**
183  * @addtogroup Eina_Main_Group Main
184  *
185  * @brief These functions provide general initialisation and shut down
186  * functions.
187  *
188  * @{
189  */
190
191 /**
192  * @brief Initialize the Eina library.
193  *
194  * @return 1 or greater on success, 0 on error.
195  *
196  * This function sets up all the eina modules. It returns 0 on
197  * failure (that is, when one of the module fails to initialize),
198  * otherwise it returns the number of times it has already been
199  * called.
200  *
201  * When Eina is not used anymore, call eina_shutdown() to shut down
202  * the Eina library.
203  */
204 EAPI int
205 eina_init(void)
206 {
207    const struct eina_desc_setup *itr, *itr_end;
208
209    if (EINA_LIKELY(_eina_main_count > 0))
210      return ++_eina_main_count;
211
212    if (!eina_log_init())
213      {
214         fprintf(stderr, "Could not initialize eina logging system.\n");
215         return 0;
216      }
217    _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT);
218    if (_eina_log_dom < 0)
219      {
220         EINA_LOG_ERR("Could not register log domain: eina");
221         eina_log_shutdown();
222         return 0;
223      }
224
225    itr = _eina_desc_setup;
226    itr_end = itr + _eina_desc_setup_len;
227    for (; itr < itr_end; itr++)
228      {
229         if (!itr->init())
230           {
231              ERR("Could not initialize eina module '%s'.", itr->name);
232              _eina_shutdown_from_desc(itr);
233              return 0;
234           }
235      }
236
237    _eina_main_count = 1;
238    return 1;
239 }
240
241 /**
242  * @brief Shut down the Eina library.
243  *
244  * @return 0 when all the modules is completely shut down, 1 or
245  * greater otherwise.
246  *
247  * This function shuts down the Eina library. It returns 0 when it has
248  * been called the same number of times than eina_init(). In that case
249  * it shut down all the Eina modules.
250  *
251  * Once this function succeeds (that is, @c 0 is returned), you must
252  * not call any of the Eina function anymore. You must call
253  * eina_init() again to use the Eina functions again.
254  */
255 EAPI int
256 eina_shutdown(void)
257 {
258    _eina_main_count--;
259    if (EINA_UNLIKELY(_eina_main_count == 0))
260      _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
261    return _eina_main_count;
262 }
263
264
265 /**
266  * @brief Initialize the mutexs of the Eina library.
267  *
268  * @return 1 or greater on success, 0 on error.
269  *
270  * This function sets up all the mutexs in all eina modules. It returns 0 on
271  * failure (that is, when one of the module fails to initialize),
272  * otherwise it returns the number of times it has already been
273  * called.
274  *
275  * When the mutexs are not used anymore, call eina_thread_shutdown() to shut down
276  * the mutexs.
277  */
278 EAPI int
279 eina_threads_init(void)
280 {
281 #ifdef EFL_HAVE_THREADS
282     int ret;
283
284 # ifdef EFL_HAVE_WIN32_THREADS
285     if (!_mutex)
286       _mutex = CreateMutex(NULL, FALSE, NULL);
287     if (!_mutex) return 0;
288 # endif
289     
290     LOCK();
291     ++_eina_main_thread_count;
292     ret = _eina_main_thread_count;
293
294     if(_eina_main_thread_count > 1)
295     {
296         UNLOCK();
297         return ret;
298     }
299
300     eina_share_common_threads_init();
301     eina_log_threads_init();
302     _threads_activated = EINA_TRUE;
303
304     return ret;
305 #else
306     return 0;
307 #endif
308 }
309
310 /**
311  * @brief Shut down mutexs in the Eina library.
312  *
313  * @return 0 when all mutexs are completely shut down, 1 or
314  * greater otherwise.
315  *
316  * This function shuts down the mutexs in the Eina library. It returns 0 when it has
317  * been called the same number of times than eina_thread_init(). In that case
318  * it shut down all the mutexs.
319  *
320  * Once this function succeeds (that is, @c 0 is returned), you must
321  * not call any of the Eina function in a thread anymore. You must call
322  * eina_thread_init() again to use the Eina functions in a thread again.
323  */
324 EAPI int
325 eina_threads_shutdown(void)
326 {
327 #ifdef EFL_HAVE_THREADS
328     int ret;
329
330     LOCK();
331     ret = --_eina_main_thread_count;
332     if(_eina_main_thread_count > 0) 
333     {
334         UNLOCK();
335         return ret; 
336     }
337
338     eina_share_common_threads_shutdown();
339     eina_log_threads_shutdown();
340
341     _threads_activated = EINA_FALSE;
342
343     UNLOCK_FORCE();
344
345 # ifdef EFL_HAVE_WIN32_THREADS
346     if (_mutex) CloseHandle(_mutex);
347 # endif
348
349     return ret;
350 #else
351     return 0;
352 #endif
353 }
354
355 /**
356  * @}
357  */