Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2006 Lennart Poettering
5 : :
6 : : PulseAudio is free software; you can redistribute it and/or modify
7 : : it under the terms of the GNU Lesser General Public License as published
8 : : by the Free Software Foundation; either version 2.1 of the License,
9 : : or (at your option) any later version.
10 : :
11 : : PulseAudio is distributed in the hope that it will be useful, but
12 : : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU Lesser General Public License
17 : : along with PulseAudio; if not, write to the Free Software
18 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 : : USA.
20 : : ***/
21 : :
22 : : #ifdef HAVE_CONFIG_H
23 : : #include <config.h>
24 : : #endif
25 : :
26 : : #include <pulsecore/macro.h>
27 : :
28 : : #include "once.h"
29 : :
30 : : /* See http://www.hpl.hp.com/research/linux/atomic_ops/example.php4 for the
31 : : * reference algorithm used here. */
32 : :
33 : 214305 : pa_bool_t pa_once_begin(pa_once *control) {
34 : : pa_mutex *m;
35 : :
36 [ - + ]: 214305 : pa_assert(control);
37 : :
38 [ + + ]: 214305 : if (pa_atomic_load(&control->done))
39 : : return FALSE;
40 : :
41 : : /* Caveat: We have to make sure that the once func has completed
42 : : * before returning, even if the once func is not actually
43 : : * executed by us. Hence the awkward locking. */
44 : :
45 : 1467 : m = pa_static_mutex_get(&control->mutex, FALSE, FALSE);
46 : 1451 : pa_mutex_lock(m);
47 : :
48 [ + + ]: 1483 : if (pa_atomic_load(&control->done)) {
49 : 937 : pa_mutex_unlock(m);
50 : 214314 : return FALSE;
51 : : }
52 : :
53 : : return TRUE;
54 : : }
55 : :
56 : 546 : void pa_once_end(pa_once *control) {
57 : : pa_mutex *m;
58 : :
59 [ - + ]: 546 : pa_assert(control);
60 : :
61 [ - + ]: 546 : pa_assert(!pa_atomic_load(&control->done));
62 : 546 : pa_atomic_store(&control->done, 1);
63 : :
64 : 546 : m = pa_static_mutex_get(&control->mutex, FALSE, FALSE);
65 : 546 : pa_mutex_unlock(m);
66 : 546 : }
67 : :
68 : : /* Not reentrant -- how could it be? */
69 : 99434 : void pa_run_once(pa_once *control, pa_once_func_t func) {
70 [ - + ]: 99434 : pa_assert(control);
71 [ - + ]: 99434 : pa_assert(func);
72 : :
73 [ + + ]: 99434 : if (pa_once_begin(control)) {
74 : 517 : func();
75 : 517 : pa_once_end(control);
76 : : }
77 : 100167 : }
|