- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Plus you would like compatability with the standard integer operator functions.
( <<=, >>=, *=, /= will require using compare and swap)
Look in the TBB package for the header containing the atomic class. In there you will find
value_type
operator+=( D addend ) {
return fetch_and_add(addend)+addend;
}
This will be some amount of work on your part to add
fetch_and_or
fetch_and_and
fetch_and_xor
And the associated operator functions
operator|=()
operator&=()
operator^=()
This will also require extending the appropriate file referenced by tbb_machine.h (e.g. windows_intel64.h)
The windows_intel64.h has
__TBB_machine_OR
__TBB_machine_AND
but not__TBB_machine_XOR
The above are defined as returning void, but they should be returning the original value.
Frankly I am surprised these operators are not in the TBB headers already.
The reason you do not want to use compare and swap (which will work) is these functions do not require it.
Note, you could use compare and swap to perform an ADD, but it is not necessary to do so.
For:
ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG
you can use the instructions containing a LOCK prefix. And as a result, the code will always succeed on the first attempt.Jim Dempsey
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
tbb::atomic
to see if it has
|= or
^= xor
&= and
If it does not, then add these functions.
Bit set uses OR= with bit in position
Bit clear uses AND= with ~(with bit in position)
Bit add uses XOR= with bit in position
Bit test uses non-modifying AND with bit in position
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Plus you would like compatability with the standard integer operator functions.
( <<=, >>=, *=, /= will require using compare and swap)
Look in the TBB package for the header containing the atomic class. In there you will find
value_type
operator+=( D addend ) {
return fetch_and_add(addend)+addend;
}
This will be some amount of work on your part to add
fetch_and_or
fetch_and_and
fetch_and_xor
And the associated operator functions
operator|=()
operator&=()
operator^=()
This will also require extending the appropriate file referenced by tbb_machine.h (e.g. windows_intel64.h)
The windows_intel64.h has
__TBB_machine_OR
__TBB_machine_AND
but not__TBB_machine_XOR
The above are defined as returning void, but they should be returning the original value.
Frankly I am surprised these operators are not in the TBB headers already.
The reason you do not want to use compare and swap (which will work) is these functions do not require it.
Note, you could use compare and swap to perform an ADD, but it is not necessary to do so.
For:
ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG
you can use the instructions containing a LOCK prefix. And as a result, the code will always succeed on the first attempt.Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is nothing in the tutorials that go to this dept of discussion. I suggest you read the header files and start with the AND or OR function (because the ...\machine\*.h files already contain the necessary underlaying functions. When those are working, then implement the XOR. Note, MSVC has _InterlockedXor and _InterlockedXor64 for 32-bit and 64-bit operands. A full implementation would handle BYTE and SHORT too.
>>If you can provide me with the code, that would be even great. :)
Ah grasshopper..., but then you would not have this excellentlearning experience....
Note, a fist attempt hack could add the operator??() functions and use the atomic compare and swap (less code to write). While this would work, it would also exemplify your coding style. A proper implementation would be something you can be proud of. Or usefule in your next job interview.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I wonder how much difference a CAS loop makes compared to a locked operation on x86. They're both very heavy compared to normal processing, and avoiding unnecessary use might amortise both implementations equally. Perhaps the difference only shows up in high levels of contention, where a CAS loop might need a relatively smart backoff strategy to guarantee progress for everybody. But that's for a toolkit writer to worry about, or for somebody who has to assure continuous proper operation in the field, probably not for a casual user who can always go in later to fix any problem when it arises.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The CAS has more overhead to setup and will retry when there is a concurrancy issue
***> pseudo code <***
// returns old value
longGetSet(long* p,longbit)
{
long old;
long mask = (1 << bit);
do {
old = *p;
long new = old | mask;
} while(_InterlockedCompareExchange((volatile long*)p,new, old) != old);
return old&mask; // 0=was not set, x=was set
}
verses
voidSet(long* p,longbit)
{
long mask = (1 << bit);
__asm {
mov eax, p
mov edxmask
LOCK
or dword ptr [eax], edx
}
}
Using the LOCK (_Interlocked...) you eliminate reading the old value and a potential retry on failure of CAS.
The consideration here is if you need the old value (e.g. were you the first thread to set the bit?)
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This depends on your coding requirements...
When your requirements are to only
set
clear (reset)
read
Then use of byte field in multi-threaded shared flags is best because a single write or single read can be done without LOCK prefex.
However, when your requirements are to
oldValue = set(NewValue)
Then you can use
LOCK XCHG al, byte ptr [ecx] ; ecx pointing to location (rcx if x64)
or
LOCK BTS dword ptr [ecx], eax ; ecx has location, eax has bit position 0:31
SBB eax, eax ; BTS set CF with old value of bit, produces eax-eax-CF (0/-1)
(use BTC for ^ (xor) and BTR for set to 0)
Your compiler may or may not have locking intrinsics for these operations.
If not, now is the time to learn how to write these yourself...
Or fall back onusing interlocked compare and exchange.
The XCHG implicitly has a LOCK so the prefix is not required.
Both XCHG and BTx with LOCK are thread safe and will not require a compare and its potential for having to retry.
assuming you have an intrinsic
char interlockedXCHG(char* p, char v);
char resourceInUse = 0; // 1 = in use
...
while(interlockedXCHG(&resourceInUse, 1))
_mm_pause();
... use the resource
resourceInUse = 0; // free the resource
or
int interlockedBTS(__int32* p, __int32 b);
int interlockedBTR(__int32* p, __int32 b);
__int32 resourcesInUse = 0;
const __int32 resourceX = 0;
const __int32 resourceY = 1;
...
while(interlockedBTS(&resourcesInUse, resourceX))
_mm_pause();
...
interlockedBTR(&resourcesInUse, resourceX);
Note, using CHAR requires 1 LOCKed instruction, using BTx requires 2 LOCKed instructions.
Size verses overhead.
Jim Dempsey
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page