/* This file is part of Jflib.
Jflib is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jflib is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jflib. If not, see .
*/
#ifndef _JFLIB_COMPARE_AND_SWAP_H_
#define _JFLIB_COMPARE_AND_SWAP_H_
#include
#include
namespace jflib {
// // Atomic load (get) and store (set). For now assume that the
// // architecture does this based on the virtual key word (true for
// // x86_64). TODO: improve on other architectures.
// template
// T a_get(const T &x) { return *(volatile T*)&x; }
// template
// T &a_set(T &lhs, const U &rhs) {
// *(volatile T*)&lhs = rhs;
// return lhs;
// }
// Numeric type of length rounded up to the size of a
// word. Undefined, and raise a compilation error, if the length is
// not a machine word size
template union word_t;
template union word_t { typedef uint8_t w_t; T v; w_t w; };
template union word_t { typedef uint16_t w_t; T v; w_t w; };
template union word_t { typedef uint32_t w_t; T v; w_t w; };
template union word_t { typedef uint64_t w_t; T v; w_t w; };
/** Type safe version of CAS.
* @param [in] ptr Memory location.
* @param [in] ov Presumed value at location.
* @param [in] nv Value to write.
* @param [out] cv Value at location at time of call.
* @return true if CAS is successful.
*
* The CAS operation is successful if, at the time of call, ov is
* equal to *ptr, the value at the memory location. In that case, nv
* is written to *ptr, and when the call returns, cv == ov.
*
* If it fails, cv contains *ptr at the time of call.
*/
template
bool cas(T *ptr, const T &ov, const T &nv, T *cv) {
typedef word_t val_t;
val_t _cv, _ov, _nv;
_ov.v = ov;
_nv.v = nv;
_cv.w = __sync_val_compare_and_swap((typename val_t::w_t *)ptr, _ov.w, _nv.w);
*cv = _cv.v;
return _cv.w == _ov.w;
}
/** Type safe version of CAS. Identical to 4 argument version,
* except does not return the previous value.
*/
template
bool cas(T *ptr, const T &ov, const T &nv) {
T cv;
return cas(ptr, ov, nv, &cv);
}
}
#endif /* _JFLIB_COMPARE_AND_SWAP_H_ */