Operacje atomowe dla listy podwójnie połączonej bez blokady

Piszę podwójnie połączoną listę bez blokady na podstawie tych dokumentów:

„Wydajna i niezawodna rekultywacja pamięci bez blokowania oparta na zliczaniu referencji” Anders Gidenstam, Członek, IEEE, Marina Papatriantafilou, H˚ akan Sundell i Philippas Tsigas

„Deques bez blokady i listy podwójnie połączone” Håkan Sundell, Philippas Tsigas

Na to pytanie możemy odłożyć pierwszy dokument.

W tym dokumencie używają inteligentnego sposobu przechowywania flagi usuwania i wskaźnika w słowie. (Więcej informacjitutaj)

Pseudo kod dla tej sekcji w dokumencie:

union Link
    : word
    (p,d): {pointer to Node, boolean} 

structure Node
    value: pointer to word
    prev: union Link
    next: union Link

I mój kod dla powyższego pseudo kodu:

template< typename NodeT >
struct LockFreeLink
{
public:
    typedef NodeT NodeType;

private:

protected:
    std::atomic< NodeT* > mPointer;

public:
    bcLockFreeLink()
    {
        std::atomic_init(&mPointer, nullptr);
    }
    ~bcLockFreeLink() {}

    inline NodeType* getNode() const throw()
    {
        return std::atomic_load(&mPointer, std::memory_order_relaxed);
    }
    inline std::atomic< NodeT* >* getAtomicNode() const throw()
    {
        return &mPointer;
    }
};

struct Node : public LockFreeNode
{
    struct Link : protected LockFreeLink< Node >
    {
        static const int dMask = 1;
        static const int ptrMask = ~dMask;

        Link() { } throw()
        Link(const Node* pPointer, bcBOOL pDel = bcFALSE) throw()
        { 
            std::atomic_init(&mPointer, (reinterpret_cast<int>(pPointer) | (int)pDel)); 
        }

        Node* pointer() const throw() 
        { 
            return reinterpret_cast<Node*>(
                std::atomic_load(&data, std::memory_order_relaxed) & ptrMask); 
        }
        bool del() const throw() 
        { 
            return std::atomic_load(&data, std::memory_order_relaxed) & dMask; 
        }
        bool compareAndSwap(const Link& pExpected, const Link& pNew) throw() 
        { 
            Node* lExpected = std::atomic_load(&pExpected.mPointer, std::memory_order_relaxed);
            Node* lNew = std::atomic_load(&pNew.mPointer, std::memory_order_relaxed);

            return std::atomic_compare_exchange_strong_explicit(
                &mPointer,
                &lExpected,
                lNew,
                std::memory_order_relaxed,
                std::memory_order_relaxed); 
        }

        bool operator==(const Link& pOther) throw() 
        { 
            return std::atomic_load(data, std::memory_order_relaxed) == 
                std::atomic_load(pOther.data, std::memory_order_relaxed); 
        }
        bool operator!=(const Link& pOther) throw() 
        { 
            return !operator==(pOther); 
        }
    };

    Link mPrev;
    Link mNext;
    Type mData;

    Node() {};
    Node(const Type& pValue) : mData(pValue) {};
};

W tym dokumencie znajduje się funkcja ustawiania znaku usunięcia linku na true:

procedure SetMark(link: pointer to pointer to Node)
    while true do
       node = *link;
       if node.d = true or CAS(link, node, (node.p, true)) then break;

I mój kod dla tej funkcji:

void _setMark(Link* pLink)
{
    while (bcTRUE)
    {
        Link lOld = *pLink;
        if(pLink->del() || pLink->compareAndSwap(lOld, Link(pLink->pointer(), bcTRUE)))
            break;
    }
}

Ale mój problem jestcompareAndSwap funkcja gdzie i musi porównać i zamienić trzy zmienne atomowe. Informacja o problemie jesttutaj

(Tak właściwienew zmienna w funkcji porównania i wymiany nie jest ważna, ponieważ jest lokalna w wątku)

Teraz moje pytanie: jak mogę napisać funkcję compareAndSwap, aby porównać i zamienić trzy warianty atomowe lub gdzie popełniam błąd?

(Przepraszam za długie pytanie)

Edytować:

Podobny problem dotyczy papieru menedżera pamięci:

function CompareAndSwapRef(link:pointer to pointer toNode,
old:pointer toNode, new:pointer toNode):boolean
    if CAS(link,old,new) then
        if new=NULL then
            FAA(&new.mmref,1);
            new.mmtrace:=false;
    if old=NULLthen FAA(&old.mmref,-1);
    return true;
return false; 

tutaj znowu muszę porównać i zamienić trzy zmienne atomowe. (Zauważ, że moje argumenty są typuLink i muszę porównać i zamienićmPointer zLink)

questionAnswers(3)

yourAnswerToTheQuestion