interlocked_variable.h
1 /*
2 ** ClanLib SDK
3 ** Copyright (c) 1997-2013 The ClanLib Team
4 **
5 ** This software is provided 'as-is', without any express or implied
6 ** warranty. In no event will the authors be held liable for any damages
7 ** arising from the use of this software.
8 **
9 ** Permission is granted to anyone to use this software for any purpose,
10 ** including commercial applications, and to alter it and redistribute it
11 ** freely, subject to the following restrictions:
12 **
13 ** 1. The origin of this software must not be misrepresented; you must not
14 ** claim that you wrote the original software. If you use this software
15 ** in a product, an acknowledgment in the product documentation would be
16 ** appreciated but is not required.
17 ** 2. Altered source versions must be plainly marked as such, and must not be
18 ** misrepresented as being the original software.
19 ** 3. This notice may not be removed or altered from any source distribution.
20 **
21 ** Note: Some of the libraries ClanLib may link to may have additional
22 ** requirements or restrictions.
23 **
24 ** File Author(s):
25 **
26 ** Magnus Norddahl
27 */
28 
29 
30 #pragma once
31 
32 #include "../api_core.h"
33 #include "system.h"
34 
35 #ifdef WIN32
36 #include <windows.h>
37 #else
38 #include "../System/cl_platform.h"
39 #endif
40 
41 namespace clan
42 {
45 
46 // __sync_val_compare_and_swap was not introduced until gcc 4.1
47 #if defined(WIN32) || __GNUC__ > 4 || (__GNUC__ == 4 & __GNUC_MINOR__ >= 1)
48 
50 class InterlockedVariable
51 {
52 public:
53 #ifdef WIN32
54  InterlockedVariable()
55  : val((LONG*)System::aligned_alloc(sizeof(LONG), 4))
56  {
57  set(0);
58  }
59 
60  InterlockedVariable(const InterlockedVariable &src)
61  : val((LONG*)System::aligned_alloc(sizeof(LONG), 4))
62  {
63  set(src.get());
64  }
65 
66  ~InterlockedVariable()
67  {
68  System::aligned_free((void*)val);
69  }
70 
71  InterlockedVariable &operator =(const InterlockedVariable &src)
72  {
73  set(src.get());
74  return *this;
75  }
76 
77  LONG get() const
78  {
79  return InterlockedCompareExchange(val, 0, 0);
80  }
81 
82  void set(LONG new_value)
83  {
84  InterlockedExchange(val, new_value);
85  }
86 
87  LONG increment()
88  {
89  return InterlockedIncrement(val);
90  }
91 
92  LONG decrement()
93  {
94  return InterlockedDecrement(val);
95  }
96 
97  bool compare_and_swap(LONG expected_value, LONG new_value)
98  {
99  return InterlockedCompareExchange(val, new_value, expected_value) == expected_value;
100  }
101 
102 private:
103  volatile LONG *val;
104 
105 #else
106  InterlockedVariable()
107  : val((byte32*)System::aligned_alloc(sizeof(byte32), 4))
108  {
109  set(0);
110  }
111 
112  InterlockedVariable(const InterlockedVariable &src)
113  : val((byte32*)System::aligned_alloc(sizeof(byte32), 4))
114  {
115  set(src.get());
116  }
117 
118  ~InterlockedVariable()
119  {
120  System::aligned_free((void*)val);
121  }
122 
123  InterlockedVariable &operator =(const InterlockedVariable &src)
124  {
125  set(src.get());
126  return *this;
127  }
128 
129  int get() const
130  {
131  return __sync_val_compare_and_swap(val, 0, 0);
132  }
133 
134  void set(int new_value)
135  {
136  __sync_lock_test_and_set(val, new_value);
137  }
138 
139  int increment()
140  {
141  return __sync_add_and_fetch(val, 1);
142  }
143 
144  int decrement()
145  {
146  return __sync_sub_and_fetch(val, 1);
147  }
148 
149  bool compare_and_swap(int expected_value, int new_value)
150  {
151  return __sync_bool_compare_and_swap(val, expected_value, new_value);
152  }
153 
154 private:
155  volatile byte32 *val;
156 
157 #endif
158 };
159 
160 #endif
161 
162 }
163 
static void aligned_free(void *ptr)
Frees aligned memory.
int byte32
Definition: cl_platform.h:63