MartinNowak / lock-free

Lock-Free data structures
40 stars 6 forks source link

implement simple list based stack #2

Open MartinNowak opened 9 years ago

MartinNowak commented 9 years ago

One example using cas SharedFreelist.

bitraft commented 6 years ago

Hi @MartinNowak

Can you review this Lock-Free Stack implement is Safe ?

import core.atomic;
import std.stdio;
import std.traits;
shared struct AtomicStack(pNode, size_t next_offset) if( isPointer!(pNode) ) {
        private {
                @disable this(this) ;
                alias Node              = Unqual!(PointerTarget!(pNode)) ;
                static assert( is(Node == struct)) ;
                enum  NullPtr   = cast(shared(Node)*)0xdeadbeafdeadbeaf ;
                static shared struct Link {
                        @disable this() ;
                        @disable this(this) ;
                        Node*   m_next = void ;
                }
                Node* m_head = NullPtr ;

                Link* getLink(shared(Node)* node) {
                        assert(node !is null) ;
                        return cast(Link*) (cast(void*)node + next_offset) ;
                }
        }

        @property bool empty() const {
                return m_head is NullPtr ;
        }

        @property shared(Node)* front(){
                if( m_head is NullPtr ) {
                        return null ;
                }
                return m_head ;
        }

        void pushFront(shared(Node)* newNode) {
                debug assert( getLink(newNode).m_next is null);
                do {
                        getLink(newNode).m_next = m_head ;
                } while (!cas( &m_head, getLink(newNode).m_next, newNode)) ;
        }

        shared(Node)* popFront() {
                shared(Node)* node = void ;
                do {
                        node    = m_head ;
                        if( node is NullPtr ) {
                                return null ;
                        }
                } while (!cas( &m_head, node, getLink(m_head).m_next)) ;
                debug getLink(node).m_next = null ;
                return node ;
        }
}
struct Node {
        int i = 10;
        Node* next;
        alias Stack = AtomicStack!(Node*, Node.init.next.offsetof);
        this(int i) {
                this.i  = i;
        }
}

static shared Node.Stack stack ;

void main(){
        auto p = cast(shared(Node)*) new Node(3);
        stack.pushFront(p);
        writefln("p.i=%d", p.i);
        p = cast(shared(Node)*) new Node(4);
        stack.pushFront(p);
        writefln("p.i=%d p.next.i=%d", p.i, p.next.i);
        p = stack.popFront;
        writefln("p.i=%d", p.i);
        p = stack.popFront;
        writefln("p.i=%d", p.i);
        p = stack.popFront;
        assert(p is null);
}