// Copyright 2012 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// Lock-free stack.package runtimeimport ()// lfstack is the head of a lock-free stack.//// The zero value of lfstack is an empty list.//// This stack is intrusive. Nodes must embed lfnode as the first field.//// The stack does not keep GC-visible pointers to nodes, so the caller// is responsible for ensuring the nodes are not garbage collected// (typically by allocating them from manually-managed memory).typelfstackuint64func ( *lfstack) ( *lfnode) { .pushcnt++ := lfstackPack(, .pushcnt)if := lfstackUnpack(); != {print("runtime: lfstack.push invalid packing: node=", , " cnt=", hex(.pushcnt), " packed=", hex(), " -> node=", , "\n")throw("lfstack.push") }for { := atomic.Load64((*uint64)()) .next = ifatomic.Cas64((*uint64)(), , ) {break } }}func ( *lfstack) () unsafe.Pointer {for { := atomic.Load64((*uint64)())if == 0 {returnnil } := lfstackUnpack() := atomic.Load64(&.next)ifatomic.Cas64((*uint64)(), , ) {returnunsafe.Pointer() } }}func ( *lfstack) () bool {returnatomic.Load64((*uint64)()) == 0}// lfnodeValidate panics if node is not a valid address for use with// lfstack.push. This only needs to be called when node is allocated.func ( *lfnode) {iflfstackUnpack(lfstackPack(, ^uintptr(0))) != {printlock()println("runtime: bad lfnode address", hex(uintptr(unsafe.Pointer())))throw("bad lfnode address") }}