QAtomicInt
-
Why QAtomicInt doesn't have atomic operations like in std::atomic<int>::load/store? How i can assign and get int atomically if this operations not atomic?:
@
inline QAtomicInt(int value = 0) { _q_value = value; }
inline QAtomicInt(int value = 0)
{
#ifdef QT_ARCH_PARISC
this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
#endif
_q_value = value;
}
...
// Non-atomic API
inline bool operator==(int value) const
{
return _q_value == value;
}inline bool operator!=(int value) const { return _q_value != value; } inline bool operator!() const { return _q_value == 0; } inline operator int() const { return _q_value; }
@
-
The fetch and store command set, will set the value of the int atomically, it will just also return the value atomically.
To retrieve the int without setting it, may be trickier, it has an int conversion operator, but i am not sure if this is an atomic action This seems to be the only command to get the value without changing it though, although if the code is actually:
@inline operator int() const
{
return _q_value;
}@Then it should be atomic right??? (I'm not an expert in this area, but an inline function that returns a member should only be one operation right?)
-
But why boost use memory barrier?
@
// Rational for the implementation of the atomic read and write functions.
//
// 1. The Alpha Architecture Handbook requires that access to a byte,
// an aligned word, an aligned longword, or an aligned quadword is
// atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.)
//
// 2. The CXX User's Guide states that volatile quantities are accessed
// with single assembler instructions, and that a compilation error
// occurs when declaring a quantity as volatile which is not properly
// aligned.//! Atomically read an boost::uint32_t from memory
//! Acquire, memory barrier after load.
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
{ boost::uint32_t old_val = *mem; __MB(); return old_val; }//! Atomically set an boost::uint32_t in memory
//! "mem": pointer to the object
//! "param": val value that the object will assume
//! Release, memory barrier before store.
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
{ __MB(); *mem = val; }@
-
Or why QAtomicInt doesn't support memory order models for load and store operations like this:
@
mutex.store(0, std::memory_order_release);
mutex.store(0, std::memory_order_relaxed);
s->head($).load(rl::memory_order_relaxed);
local_count_.load(std::memory_order_acquire)
@ -
SABROG, are you sure you've read documentation properly?
@int fetchAndAddAcquire ( int valueToAdd )
int fetchAndAddOrdered ( int valueToAdd )
int fetchAndAddRelaxed ( int valueToAdd )
int fetchAndAddRelease ( int valueToAdd )
int fetchAndStoreAcquire ( int newValue )
int fetchAndStoreOrdered ( int newValue )
int fetchAndStoreRelaxed ( int newValue )
int fetchAndStoreRelease ( int newValue )
bool ref ()
bool testAndSetAcquire ( int expectedValue, int newValue )
bool testAndSetOrdered ( int expectedValue, int newValue )
bool testAndSetRelaxed ( int expectedValue, int newValue )
bool testAndSetRelease ( int expectedValue, int newValue )@Those functions do all you asked for, if I've understood you correctly.
-
SABROG, I don't understand you. XCHG is an atomic instruction. Thus it is exactly things your are searching for, isn't it?
About perfomance: Do you really think you would have noticeable overheads with using XCHG instead of MOV?
[quote]Atomic load on IA-32 must be ordinary “mov” with memory fence/barrier, on PowerPC – “ld” instruction.[/quote]
Why do you think so? XCHG has lock mechanism inside itself, but MOV doesn't. -
[quote author="ixSci" date="1278351439"]
About perfomance: Do you really think you would have noticeable overheads with using XCHG instead of MOV?
XCHG has lock mechanism inside itself, but MOV doesn't. [/quote]MOV is atomic for 8, 16, 32 bits variables with ordering memory on IA-32. I write call_once() function implementation on Qt with QAtomicInt class and my implementation slower than std::call_once() in 9 times. I use callgrind and found what problem in atomic operations like fetchAndStore()/testAndSet(). For test perfomance i remove all atomic operations and write native C++ code, only after this i get identical perfomance like with std::call_once.
-
I don't know what is in the guts of std::call_once, but Qt uses lock and it's a very heavy instruction(relative to other). Superficial analysis of Bing output show no implementations of the atomic read\write with mov. But all were with XCHG using. If you're using x86 it should be overkill to struggle for each CPU tick, though. Could you explain why you count each CPU tick and what the "9 times" would be in the time scale, please?
Also, I think you deepening in the premature optimization. But if you have such an insistence to have faster atomic operation why don't you use original C++0x(11 I hope) in your code? It would be uglier a little but you will have all that you want.BTW, Windows atomic operations also use XCHG under the hood(if Bing doesn't lie to me.)
-
[quote author="ixSci" date="1278363015"]Could you explain why you count each CPU tick and what the "9 times" would be in the time scale, please?
[/quote]
1 second on 1 billion calls std::call_once versus 9 seconds with Qt atomic implementation.[quote author="ixSci" date="1278363015"]
Also, I think you deepening in the premature optimization. But if you have such an insistence to have faster atomic operation why don't you use original C++0x(11 I hope) in your code? It would be uglier a little but you will have all that you want.
[/quote]
I don't want people to say, what Qt library slower than standard library or BOOST.