| 1 | //
 | 
|---|
| 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 | //
 | 
|---|
| 6 | // stackLockFree.hfa --
 | 
|---|
| 7 | //
 | 
|---|
| 8 | // Author           : Peter A. Buhr
 | 
|---|
| 9 | // Created On       : Wed May 13 20:58:58 2020
 | 
|---|
| 10 | // Last Modified By : Peter A. Buhr
 | 
|---|
| 11 | // Last Modified On : Sun Jun 14 13:25:09 2020
 | 
|---|
| 12 | // Update Count     : 64
 | 
|---|
| 13 | //
 | 
|---|
| 14 | 
 | 
|---|
| 15 | #pragma once
 | 
|---|
| 16 | 
 | 
|---|
| 17 | #include <stdint.h>
 | 
|---|
| 18 | 
 | 
|---|
| 19 | forall( dtype T )
 | 
|---|
| 20 | union Link {
 | 
|---|
| 21 |         struct {                                                                                        // 32/64-bit x 2
 | 
|---|
| 22 |                 T * volatile top;                                                               // pointer to stack top
 | 
|---|
| 23 |                 uintptr_t count;                                                                // count each push
 | 
|---|
| 24 |         };
 | 
|---|
| 25 |         #if __SIZEOF_INT128__ == 16
 | 
|---|
| 26 |         __int128                                                                                        // gcc, 128-bit integer
 | 
|---|
| 27 |         #else
 | 
|---|
| 28 |         uint64_t                                                                                        // 64-bit integer
 | 
|---|
| 29 |         #endif // __SIZEOF_INT128__ == 16
 | 
|---|
| 30 |         atom;
 | 
|---|
| 31 | }; // Link
 | 
|---|
| 32 | 
 | 
|---|
| 33 | forall( otype T | sized(T) | { Link(T) * ?`next( T * ); } ) {
 | 
|---|
| 34 |         struct StackLF {
 | 
|---|
| 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) {
 | 
|---|
| 44 |                         *( &n )`next = stack;                                   // atomic assignment unnecessary, or use CAA
 | 
|---|
| 45 |                         for () {                                                                        // busy wait
 | 
|---|
| 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
 | 
|---|
| 47 |                         } // for
 | 
|---|
| 48 |                 } // push
 | 
|---|
| 49 | 
 | 
|---|
| 50 |                 T * pop( StackLF(T) & this ) with(this) {
 | 
|---|
| 51 |                         Link(T) t @= stack;                                                     // atomic assignment unnecessary, or use CAA
 | 
|---|
| 52 |                         for () {                                                                        // busy wait
 | 
|---|
| 53 |                           if ( t.top == 0p ) return 0p;                         // empty stack ?
 | 
|---|
| 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
 | 
|---|
| 55 |                         } // for
 | 
|---|
| 56 |                 } // pop
 | 
|---|
| 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 ) {
 | 
|---|
| 63 |                                         link->top = ( node )`next->top;
 | 
|---|
| 64 |                                         return true;
 | 
|---|
| 65 |                                 }
 | 
|---|
| 66 |                                 if( next == 0p ) return false;
 | 
|---|
| 67 |                                 link = (next)`next;
 | 
|---|
| 68 |                         }
 | 
|---|
| 69 |                 }
 | 
|---|
| 70 |         } // distribution
 | 
|---|
| 71 | } // distribution
 | 
|---|
| 72 | 
 | 
|---|
| 73 | 
 | 
|---|
| 74 | // Local Variables: //
 | 
|---|
| 75 | // tab-width: 4 //
 | 
|---|
| 76 | // End: //
 | 
|---|