| [04b5cef] | 1 | //
 | 
|---|
| [9c438546] | 2 | // Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
 | 
|---|
 | 3 | // The contents of this file are covered under the licence agreement in the
 | 
|---|
 | 4 | // file "LICENCE" distributed with Cforall.
 | 
|---|
 | 5 | //
 | 
|---|
| [04b5cef] | 6 | // stackLockFree.hfa --
 | 
|---|
 | 7 | //
 | 
|---|
| [9c438546] | 8 | // Author           : Peter A. Buhr
 | 
|---|
 | 9 | // Created On       : Wed May 13 20:58:58 2020
 | 
|---|
 | 10 | // Last Modified By : Peter A. Buhr
 | 
|---|
| [9019b14] | 11 | // Last Modified On : Sun Jun 14 13:25:09 2020
 | 
|---|
 | 12 | // Update Count     : 64
 | 
|---|
| [04b5cef] | 13 | //
 | 
|---|
| [9c438546] | 14 | 
 | 
|---|
 | 15 | #pragma once
 | 
|---|
 | 16 | 
 | 
|---|
 | 17 | #include <stdint.h>
 | 
|---|
 | 18 | 
 | 
|---|
 | 19 | forall( dtype T )
 | 
|---|
 | 20 | union Link {
 | 
|---|
| [280ec46] | 21 |         struct {                                                                                        // 32/64-bit x 2
 | 
|---|
| [04b5cef] | 22 |                 T * volatile top;                                                               // pointer to stack top
 | 
|---|
| [280ec46] | 23 |                 uintptr_t count;                                                                // count each push
 | 
|---|
| [9c438546] | 24 |         };
 | 
|---|
| [314dab6] | 25 |         #if __SIZEOF_INT128__ == 16
 | 
|---|
| [280ec46] | 26 |         __int128                                                                                        // gcc, 128-bit integer
 | 
|---|
| [9c438546] | 27 |         #else
 | 
|---|
| [280ec46] | 28 |         uint64_t                                                                                        // 64-bit integer
 | 
|---|
| [314dab6] | 29 |         #endif // __SIZEOF_INT128__ == 16
 | 
|---|
| [9c438546] | 30 |         atom;
 | 
|---|
 | 31 | }; // Link
 | 
|---|
 | 32 | 
 | 
|---|
| [8b58bae] | 33 | forall( otype T | sized(T) | { Link(T) * ?`next( T * ); } ) {
 | 
|---|
| [64a7146] | 34 |         struct StackLF {
 | 
|---|
| [9c438546] | 35 |                 Link(T) stack;
 | 
|---|
 | 36 |         }; // StackLF
 | 
|---|
 | 37 | 
 | 
|---|
 | 38 |         static inline {
 | 
|---|
 | 39 |                 void ?{}( StackLF(T) & this ) with(this) { stack.atom = 0; }
 | 
|---|
 | 40 | 
 | 
|---|
 | 41 |                 T * top( StackLF(T) & this ) with(this) { return stack.top; }
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 |                 void push( StackLF(T) & this, T & n ) with(this) {
 | 
|---|
| [8b58bae] | 44 |                         *( &n )`next = stack;                                   // atomic assignment unnecessary, or use CAA
 | 
|---|
| [9c438546] | 45 |                         for () {                                                                        // busy wait
 | 
|---|
| [0f89d4f] | 46 |                           if ( __atomic_compare_exchange_n( &stack.atom, &( &n )`next->atom, (Link(T))@{ {&n, ( &n )`next->count + 1} }.atom, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) break; // attempt to update top node
 | 
|---|
| [9c438546] | 47 |                         } // for
 | 
|---|
 | 48 |                 } // push
 | 
|---|
 | 49 | 
 | 
|---|
 | 50 |                 T * pop( StackLF(T) & this ) with(this) {
 | 
|---|
| [9019b14] | 51 |                         Link(T) t @= stack;                                                     // atomic assignment unnecessary, or use CAA
 | 
|---|
| [9c438546] | 52 |                         for () {                                                                        // busy wait
 | 
|---|
 | 53 |                           if ( t.top == 0p ) return 0p;                         // empty stack ?
 | 
|---|
| [0f89d4f] | 54 |                           if ( __atomic_compare_exchange_n( &stack.atom, &t.atom, (Link(T))@{ {( t.top )`next->top, t.count} }.atom, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) return t.top; // attempt to update top node
 | 
|---|
| [9c438546] | 55 |                         } // for
 | 
|---|
 | 56 |                 } // pop
 | 
|---|
| [64a7146] | 57 | 
 | 
|---|
 | 58 |                 bool unsafe_remove( StackLF(T) & this, T * node ) with(this) {
 | 
|---|
 | 59 |                         Link(T) * link = &stack;
 | 
|---|
 | 60 |                         for() {
 | 
|---|
 | 61 |                                 T * next = link->top;
 | 
|---|
 | 62 |                                 if( next == node ) {
 | 
|---|
| [0f89d4f] | 63 |                                         link->top = ( node )`next->top;
 | 
|---|
| [64a7146] | 64 |                                         return true;
 | 
|---|
 | 65 |                                 }
 | 
|---|
 | 66 |                                 if( next == 0p ) return false;
 | 
|---|
| [0f89d4f] | 67 |                                 link = (next)`next;
 | 
|---|
| [64a7146] | 68 |                         }
 | 
|---|
 | 69 |                 }
 | 
|---|
| [9c438546] | 70 |         } // distribution
 | 
|---|
 | 71 | } // distribution
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 | 
 | 
|---|
 | 74 | // Local Variables: //
 | 
|---|
 | 75 | // tab-width: 4 //
 | 
|---|
 | 76 | // End: //
 | 
|---|