Threaded execution support interface added. Optional built-in threading implementatio...
[ode.git] / ode / src / threading_atomics_provs.h
blobb12af00358a6dd1699b66387e286f56674b9960e
1 /*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
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") *
9 * *
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 *
16 * file LICENSE.TXT. *
17 * (2) The BSD-style license that is included with this library in *
18 * the file LICENSE-BSD.TXT. *
19 * *
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. *
24 * *
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
50 public:
51 typedef unsigned long atomicord_t;
52 typedef void *atomicptr_t;
54 public:
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;
91 template<>
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;
101 template<>
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 /************************************************************************/
118 #if !dOU_ENABLED
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
122 #endif
123 #include "odeou.h"
125 class dxOUAtomicsProvider
127 public:
128 typedef _OU_NAMESPACE::atomicord32 atomicord_t;
129 typedef _OU_NAMESPACE::atomicptr atomicptr_t;
131 public:
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;
152 return result_value;
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);
165 template<>
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);
171 template<>
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;
176 while (true)
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))
183 break;
187 return (size_t)original_value;
191 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
194 #endif // #ifndef _ODE_THREADING_ATOMICS_PROVS_H_