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