Line data Source code
1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 : /*
3 : * lt-atomic.h
4 : * Copyright (C) 2011-2012 Akira TAGOH
5 : *
6 : * Authors:
7 : * Akira TAGOH <akira@tagoh.org>
8 : *
9 : * You may distribute under the terms of either the GNU
10 : * Lesser General Public License or the Mozilla Public
11 : * License, as specified in the README file.
12 : */
13 : #ifndef __LT_ATOMIC_H__
14 : #define __LT_ATOMIC_H__
15 :
16 : #ifdef HAVE_CONFIG_H
17 : #include "config.h"
18 : #endif
19 :
20 : #if !defined(LT_HAVE_ATOMIC_BUILTINS) && !defined(_WIN32)
21 : #include <pthread.h>
22 : #elif defined(_WIN32)
23 : #include <windows.h>
24 : #endif
25 : #include "lt-messages.h"
26 :
27 : LT_BEGIN_DECLS
28 :
29 : LT_INLINE_FUNC int lt_atomic_int_get (volatile int *v);
30 : LT_INLINE_FUNC int lt_atomic_int_inc (volatile int *v);
31 : LT_INLINE_FUNC lt_bool_t lt_atomic_int_dec_and_test(volatile int *v);
32 :
33 : #if !defined(LT_HAVE_ATOMIC_BUILTINS) && !defined(_WIN32)
34 : static pthread_mutex_t __lt_atomic_lock = PTHREAD_MUTEX_INITIALIZER;
35 : #endif
36 :
37 : /*< private >*/
38 :
39 : /*< public >*/
40 : #ifdef _WIN32
41 : LT_INLINE_FUNC int
42 : lt_atomic_int_get(volatile int *v)
43 : {
44 : lt_return_val_if_fail (v != NULL, 0);
45 :
46 : return (int)InterlockedExchange((LONG*)v, (LONG)*v);
47 : }
48 :
49 : LT_INLINE_FUNC int
50 : lt_atomic_int_inc(volatile int *v)
51 : {
52 : lt_return_val_if_fail (v != NULL, 0);
53 :
54 : return (int)InterlockedIncrement((LONG*)v);
55 : }
56 :
57 : lt_bool_t
58 : lt_atomic_int_dec_and_test(volatile int *v)
59 : {
60 : lt_return_val_if_fail (v != NULL, FALSE);
61 :
62 : return !InterlockedDecrement((LONG*)v);
63 : }
64 :
65 :
66 : #elif defined(LT_HAVE_ATOMIC_BUILTINS)
67 : LT_INLINE_FUNC int
68 0 : lt_atomic_int_get(volatile int *v)
69 : {
70 0 : lt_return_val_if_fail (v != NULL, 0);
71 :
72 0 : __sync_synchronize();
73 0 : return *v;
74 : }
75 :
76 : LT_INLINE_FUNC int
77 35314 : lt_atomic_int_inc(volatile int *v)
78 : {
79 35314 : lt_return_val_if_fail (v != NULL, 0);
80 :
81 35314 : return __sync_fetch_and_add(v, 1);
82 : }
83 :
84 : lt_bool_t
85 112444 : lt_atomic_int_dec_and_test(volatile int *v)
86 : {
87 112444 : lt_return_val_if_fail (v != NULL, FALSE);
88 :
89 112444 : return __sync_fetch_and_sub(v, 1) == 1;
90 : }
91 :
92 : #else /* !LT_HAVE_ATOMIC_BUILTINS */
93 : LT_INLINE_FUNC int
94 : lt_atomic_int_get(volatile int *v)
95 : {
96 : volatile int retval;
97 :
98 : lt_return_val_if_fail (v != NULL, 0);
99 :
100 : pthread_mutex_lock(&__lt_atomic_lock);
101 : retval = *v;
102 : pthread_mutex_unlock(&__lt_atomic_lock);
103 :
104 : return retval;
105 : }
106 :
107 : LT_INLINE_FUNC int
108 : lt_atomic_int_inc(volatile int *v)
109 : {
110 : int retval;
111 :
112 : lt_return_val_if_fail (v != NULL, 0);
113 :
114 : pthread_mutex_lock(&__lt_atomic_lock);
115 : retval = (*v)++;
116 : pthread_mutex_unlock(&__lt_atomic_lock);
117 :
118 : return retval;
119 : }
120 :
121 : LT_INLINE_FUNC lt_bool_t
122 : lt_atomic_int_dec_and_test(volatile int *v)
123 : {
124 : lt_bool_t retval;
125 :
126 : lt_return_val_if_fail (v != NULL, FALSE);
127 :
128 : pthread_mutex_lock(&__lt_atomic_lock);
129 : retval = --(*v) == 0;
130 : pthread_mutex_unlock(&__lt_atomic_lock);
131 :
132 : return retval;
133 : }
134 : #endif /* LT_HAVE_ATOMIC_BUILTINS */
135 :
136 : LT_END_DECLS
137 :
138 : #endif /* __LT_ATOMIC_H__ */
|