I am trying to use tagged pointers for handling the lock free operations on a list, in order to block the compare-and-swap (CAS) from going through if some other thread operated on the list during this transaction. My node struct and CAS look like this:
struct node {
unsigned long key;
unsigned long val;
struct node * next;
};
static inline bool CAS(std::atomic<node*> node, struct node* oldNode, struct node* newNode)
{
node.compare_exchange_strong(oldNode, newNode, std::memory_order_seq_cst);
}
I found some methods for setting and checking these pointers but it is unclear to me how they work, these are the methods for setting the mask and verifying it.
__inline struct node* setTagMask(struct node* p, int MASK_BIT)
{
return (struct node*) ((uintptr_t)p | MASK_BIT);
}
__inline bool isMaskFlagSet(struct node* p)
{
return ((uintptr_t)p & MASK_BIT) != 0;
}
So what is unclear to me is for example in the setTagMask, if I use it on my list than it will delete all its references to its value and next element as well.
Can anyone explain to me how can I properly set these bits so the other elements of the list remain the same?
The setTagMask
function returns a modified version of the pointer p
. If you store this modified pointer in your linked-list, then the list gets broken because the modified pointer does not point to a node
anymore.
The pointer is modified as follows. The pointer p
is converted to an unsigned integer which is capable to store a pointer: uintptr_t
.
Then one or more bits are set according to MASK_BIT
. Finally, the result is converted back to a pointer and returned.
The function isMaskFlagSet
checks whether the mask bits are still set.
The only use case, I can image is: you have to call isMaskFlagSet
every time, before you use the pointer. If the mask bits are set, then it is prohibited to actually use the pointer.
来源:https://stackoverflow.com/questions/35534481/tagged-pointers-for-lockfree-list-in-c