1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * Threading atomics providers file. *
7 * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. *
8 * e-mail: odar@eleks.com (change all "a" to "e") *
10 * This library is free software; you can redistribute it and/or *
11 * modify it under the terms of EITHER: *
12 * (1) The GNU Lesser General Public License as published by the Free *
13 * Software Foundation; either version 2.1 of the License, or (at *
14 * your option) any later version. The text of the GNU Lesser *
15 * General Public License is included with this library in the *
17 * (2) The BSD-style license that is included with this library in *
18 * the file LICENSE-BSD.TXT. *
20 * This library is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
23 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
25 *************************************************************************/
28 * Fake atomics provider for built-in threading support provider.
29 * OU-based atomics provider for built-in threading support provider.
31 * The classes have been moved into a separate header as they are to be used
32 * in both WIN and POSIX implementations.
36 #ifndef _ODE_THREADING_ATOMICS_PROVS_H_
37 #define _ODE_THREADING_ATOMICS_PROVS_H_
40 #include <ode/odeconfig.h>
41 #include <ode/error.h>
44 /************************************************************************/
45 /* Fake atomics provider class implementation */
46 /************************************************************************/
48 class dxFakeAtomicsProvider
51 typedef unsigned long atomicord_t
;
52 typedef void *atomicptr_t
;
55 static void IncrementTargetNoRet(volatile atomicord_t
*value_accumulator_ptr
)
57 ++(*value_accumulator_ptr
);
60 static void DecrementTargetNoRet(volatile atomicord_t
*value_accumulator_ptr
)
62 --(*value_accumulator_ptr
);
65 static atomicord_t
QueryTargetValue(volatile atomicord_t
*value_storage_ptr
)
67 return *value_storage_ptr
;
70 template<unsigned type_size
>
71 static size_t AddValueToTarget(volatile void *value_accumulator_ptr
, ptrdiff_t value_addend
);
73 static bool CompareExchangeTargetPtr(volatile atomicptr_t
*pointer_storage_ptr
,
74 atomicptr_t comparand_value
, atomicptr_t new_value
)
76 bool exchange_result
= false;
78 atomicptr_t original_value
= *pointer_storage_ptr
;
80 if (original_value
== comparand_value
)
82 *pointer_storage_ptr
= new_value
;
84 exchange_result
= true;
87 return exchange_result
;
92 inline size_t dxFakeAtomicsProvider::AddValueToTarget
<sizeof(dxFakeAtomicsProvider::atomicord_t
)>(volatile void *value_accumulator_ptr
, ptrdiff_t value_addend
)
94 atomicord_t original_value
= *(volatile atomicord_t
*)value_accumulator_ptr
;
96 *(volatile atomicord_t
*)value_accumulator_ptr
= original_value
+ (atomicord_t
)value_addend
;
98 return original_value
;
102 inline size_t dxFakeAtomicsProvider::AddValueToTarget
<2 * sizeof(dxFakeAtomicsProvider::atomicord_t
)>(volatile void *value_accumulator_ptr
, ptrdiff_t value_addend
)
104 atomicptr_t original_value
= *(volatile atomicptr_t
*)value_accumulator_ptr
;
106 *(volatile atomicptr_t
*)value_accumulator_ptr
= (atomicptr_t
)((size_t)original_value
+ (size_t)value_addend
);
108 return (size_t)original_value
;
112 #if dBUILTIN_THREADING_IMPL_ENABLED
114 /************************************************************************/
115 /* dxOUAtomicsProvider class implementation */
116 /************************************************************************/
119 #error OU library must be enabled for this to compile
120 #elif !dATOMICS_ENABLED
121 #error OU Atomics must be enabled for this to compile
125 class dxOUAtomicsProvider
128 typedef _OU_NAMESPACE::atomicord32 atomicord_t
;
129 typedef _OU_NAMESPACE::atomicptr atomicptr_t
;
132 static void IncrementTargetNoRet(volatile atomicord_t
*value_accumulator_ptr
)
134 _OU_NAMESPACE::AtomicIncrementNoResult(value_accumulator_ptr
);
137 static void DecrementTargetNoRet(volatile atomicord_t
*value_accumulator_ptr
)
139 _OU_NAMESPACE::AtomicDecrementNoResult(value_accumulator_ptr
);
142 static atomicord_t
QueryTargetValue(volatile atomicord_t
*value_storage_ptr
)
144 // Query value with memory barrier before
145 atomicord_t result_value
= *value_storage_ptr
;
147 if (!_OU_NAMESPACE::AtomicCompareExchange(value_storage_ptr
, result_value
, result_value
))
149 result_value
= *value_storage_ptr
;
155 template<unsigned type_size
>
156 static size_t AddValueToTarget(volatile void *value_accumulator_ptr
, ptrdiff_t value_addend
);
158 static bool CompareExchangeTargetPtr(volatile atomicptr_t
*pointer_storage_ptr
,
159 atomicptr_t comparand_value
, atomicptr_t new_value
)
161 return _OU_NAMESPACE::AtomicCompareExchangePointer(pointer_storage_ptr
, comparand_value
, new_value
);
166 inline size_t dxOUAtomicsProvider::AddValueToTarget
<sizeof(dxOUAtomicsProvider::atomicord_t
)>(volatile void *value_accumulator_ptr
, ptrdiff_t value_addend
)
168 return _OU_NAMESPACE::AtomicExchangeAdd((volatile atomicord_t
*)value_accumulator_ptr
, (atomicord_t
)value_addend
);
172 inline size_t dxOUAtomicsProvider::AddValueToTarget
<2 * sizeof(dxOUAtomicsProvider::atomicord_t
)>(volatile void *value_accumulator_ptr
, ptrdiff_t value_addend
)
174 atomicptr_t original_value
;
178 original_value
= *(volatile atomicptr_t
*)value_accumulator_ptr
;
180 atomicptr_t new_value
= (atomicptr_t
)((size_t)original_value
+ (size_t)value_addend
);
181 if (_OU_NAMESPACE::AtomicCompareExchangePointer((volatile atomicptr_t
*)value_accumulator_ptr
, original_value
, new_value
))
187 return (size_t)original_value
;
191 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
194 #endif // #ifndef _ODE_THREADING_ATOMICS_PROVS_H_