1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #ifndef _h_atomic32_
28 #define _h_atomic32_
29
30 #define WIN32_LEAN_AND_MEAN
31 #include <WINDOWS.H>
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 typedef struct atomic32_t atomic32_t;
38 struct atomic32_t
39 {
40 volatile LONG counter;
41 };
42
43 /* int atomic32_read ( const atomic32_t *v ); */
44 #define atomic32_read( v ) \
45 ( ( v ) -> counter )
46
47 /* void atomic32_set ( atomic32_t *v, int i ); */
48 #define atomic32_set( v, i ) \
49 ( ( void ) ( ( ( v ) -> counter ) = ( i ) ) )
50
51 /* add to v -> counter and return the prior value */
52 /* int atomic32_read_and_add ( atomic32_t *v, int i ) */
53 #define atomic32_read_and_add( v, i ) \
54 InterlockedExchangeAdd ( & ( v ) -> counter, ( i ) )
55
56 /* if no read is needed, define the least expensive atomic add */
57 #define atomic32_add( v, i ) \
58 atomic32_read_and_add ( v, i )
59
60 /* add to v -> counter and return the result */
atomic32_add_and_read(atomic32_t * v,int i)61 static __inline int atomic32_add_and_read ( atomic32_t *v, int i )
62 {
63 return atomic32_read_and_add ( v, i ) + i;
64 }
65
66 /* void atomic32_inc ( atomic32_t *v ) */
67 #define atomic32_inc( v ) \
68 InterlockedIncrement ( & ( v ) -> counter )
69
70 /* void atomic32_dec ( atomic32_t *v ) */
71 #define atomic32_dec( v ) \
72 InterlockedDecrement ( & ( v ) -> counter )
73
74 /* decrement by one and test result for 0 */
75 /* int atomic32_dec_and_test ( atomic32_t *v ) */
76 #define atomic32_dec_and_test( v ) \
77 ( InterlockedDecrement ( & ( v ) -> counter ) == 0 )
78
79 /* when atomic32_dec_and_test uses predecrement, you want
80 postincrement to this function. so it isn't very useful */
81 /* int atomic32_inc_and_test ( atomic32_t *v ) */
82 #define atomic32_inc_and_test( v ) \
83 ( InterlockedIncrement ( & ( v ) -> counter ) == 0 )
84
85 /* HERE's useful */
86 #define atomic32_test_and_inc( v ) \
87 ( atomic32_read_and_add ( v, 1 ) == 0 )
88
89 /* int atomic32_test_and_set ( atomic32_t *v, int s, int t ) */
90 #define atomic32_test_and_set( v, s, t ) \
91 InterlockedCompareExchange ( & ( v ) -> counter, ( s ), ( t ) )
92
93 /* conditional modifications */
atomic32_read_and_add_lt(atomic32_t * v,int i,int t)94 static __inline int atomic32_read_and_add_lt ( atomic32_t *v, int i, int t )
95 {
96 LONG val, val_intern;
97 for ( val = atomic32_read ( v ); val < t; val = val_intern )
98 {
99 val_intern = atomic32_test_and_set ( v, val + i, val );
100 if ( val_intern == val )
101 break;
102 }
103 return val;
104 }
105
atomic32_read_and_add_le(atomic32_t * v,int i,int t)106 static __inline int atomic32_read_and_add_le ( atomic32_t *v, int i, int t )
107 {
108 LONG val, val_intern;
109 for ( val = atomic32_read ( v ); val <= t; val = val_intern )
110 {
111 val_intern = atomic32_test_and_set ( v, val + i, val );
112 if ( val_intern == val )
113 break;
114 }
115 return val;
116 }
117
atomic32_read_and_add_eq(atomic32_t * v,int i,int t)118 static __inline int atomic32_read_and_add_eq ( atomic32_t *v, int i, int t )
119 {
120 LONG val, val_intern;
121 for ( val = atomic32_read ( v ); val == t; val = val_intern )
122 {
123 val_intern = atomic32_test_and_set ( v, val + i, val );
124 if ( val_intern == val )
125 break;
126 }
127 return val;
128 }
129
atomic32_read_and_add_ne(atomic32_t * v,int i,int t)130 static __inline int atomic32_read_and_add_ne ( atomic32_t *v, int i, int t )
131 {
132 LONG val, val_intern;
133 for ( val = atomic32_read ( v ); val != t; val = val_intern )
134 {
135 val_intern = atomic32_test_and_set ( v, val + i, val );
136 if ( val_intern == val )
137 break;
138 }
139 return val;
140 }
141
atomic32_read_and_add_ge(atomic32_t * v,int i,int t)142 static __inline int atomic32_read_and_add_ge ( atomic32_t *v, int i, int t )
143 {
144 LONG val, val_intern;
145 for ( val = atomic32_read ( v ); val >= t; val = val_intern )
146 {
147 val_intern = atomic32_test_and_set ( v, val + i, val );
148 if ( val_intern == val )
149 break;
150 }
151 return val;
152 }
153
atomic32_read_and_add_gt(atomic32_t * v,int i,int t)154 static __inline int atomic32_read_and_add_gt ( atomic32_t *v, int i, int t )
155 {
156 LONG val, val_intern;
157 for ( val = atomic32_read ( v ); val > t; val = val_intern )
158 {
159 val_intern = atomic32_test_and_set ( v, val + i, val );
160 if ( val_intern == val )
161 break;
162 }
163 return val;
164 }
165
atomic32_read_and_add_odd(atomic32_t * v,int i)166 static __inline int atomic32_read_and_add_odd ( atomic32_t *v, int i )
167 {
168 LONG val, val_intern;
169 for ( val = atomic32_read ( v ); ( val & 1 ) != 0; val = val_intern )
170 {
171 val_intern = atomic32_test_and_set ( v, val + i, val );
172 if ( val_intern == val )
173 break;
174 }
175 return val;
176 }
177
atomic32_read_and_add_even(atomic32_t * v,int i)178 static __inline int atomic32_read_and_add_even ( atomic32_t *v, int i )
179 {
180 LONG val, val_intern;
181 for ( val = atomic32_read ( v ); ( val & 1 ) == 0; val = val_intern )
182 {
183 val_intern = atomic32_test_and_set ( v, val + i, val );
184 if ( val_intern == val )
185 break;
186 }
187 return val;
188 }
189
190 #ifdef __cplusplus
191 }
192 #endif
193
194 #endif /* _h_atomic32_ */
195