本文整理匯總了Golang中sync/atomic.CompareAndSwapPointer函數的典型用法代碼示例。如果您正苦於以下問題:Golang CompareAndSwapPointer函數的具體用法?Golang CompareAndSwapPointer怎麽用?Golang CompareAndSwapPointer使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了CompareAndSwapPointer函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: QueueRequest
func (s *memdQueue) QueueRequest(req *memdQRequest) bool {
s.lock.RLock()
if s.isDrained {
s.lock.RUnlock()
return false
}
if !atomic.CompareAndSwapPointer(&req.queuedWith, nil, unsafe.Pointer(s)) {
panic("Request was dispatched while already queued somewhere.")
}
logSchedf("Writing request to queue!")
// Try to write the request to the queue, if the queue is full,
// we immediately fail the request with a queueOverflow error.
select {
case s.reqsCh <- req:
s.lock.RUnlock()
return true
default:
s.lock.RUnlock()
// As long as we have not lost ownership, dispatch a queue overflow error.
if atomic.CompareAndSwapPointer(&req.queuedWith, unsafe.Pointer(s), nil) {
req.Callback(nil, ErrOverload)
}
return true
}
}
示例2: dequeue
func (q *queue) dequeue() (interface{}, bool) {
var temp interface{}
var oldDummy, oldHead *node
removed := false
for !removed {
oldDummy = q.dummy
oldHead = oldDummy.next
oldTail := q.tail
if q.dummy != oldDummy {
continue
}
if oldHead == nil {
return nil, false
}
if oldTail == oldDummy {
atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)), unsafe.Pointer(oldTail), unsafe.Pointer(oldHead))
continue
}
temp = oldHead.value
removed = atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&q.dummy)), unsafe.Pointer(oldDummy), unsafe.Pointer(oldHead))
}
return temp, true
}
示例3: enqueue
func (q *queue) enqueue(v interface{}) {
var oldTail, oldTailNext *node
newNode := new(node)
newNode.value = v
newNodeAdded := false
for !newNodeAdded {
oldTail = q.tail
oldTailNext = oldTail.next
if q.tail != oldTail {
continue
}
if oldTailNext != nil {
atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)), unsafe.Pointer(oldTail), unsafe.Pointer(oldTailNext))
continue
}
newNodeAdded = atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&oldTail.next)), unsafe.Pointer(oldTailNext), unsafe.Pointer(newNode))
}
atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)), unsafe.Pointer(oldTail), unsafe.Pointer(newNode))
}
示例4: getOrInsert
func (c *container) getOrInsert(k uint64, v unsafe.Pointer) unsafe.Pointer {
bi := k & (c.sz - 1)
b := c.list[bi]
for i := range b.elems {
e := &b.elems[i]
// Once allocated a valid key, it would never change. So, first check if
// it's allocated. If not, then allocate it. If can't, or not allocated,
// then check if it's k. If it is, then replace value. Otherwise continue.
// This sequence could be problematic, if this happens:
// Main thread runs Step 1. Check
if atomic.CompareAndSwapUint64(&e.k, 0, k) { // Step 1.
atomic.AddUint32(&c.numElems, 1)
if atomic.CompareAndSwapPointer(&e.v, nil, v) {
return v
}
return atomic.LoadPointer(&e.v)
}
if atomic.LoadUint64(&e.k) == k {
// Swap if previous pointer is nil.
if atomic.CompareAndSwapPointer(&e.v, nil, v) {
return v
}
return atomic.LoadPointer(&e.v)
}
}
return nil
}
示例5: Add
// Add adds a new element to the list, returning true if, and only if the
// element wasn't already there. This method is lock-free.
func (l *List) Add(key string) bool {
for {
pred, pred_m, curr, _ := l.find(key)
if curr != nil && curr.key == key {
return false
}
node := &node{key, &markAndRef{false, curr}}
// Insert the new node after the pred node or modify the head of the
// list if there is no predecessor.
if pred == nil {
if atomic.CompareAndSwapPointer(
(*unsafe.Pointer)(unsafe.Pointer(&l.head)),
unsafe.Pointer(curr),
unsafe.Pointer(node)) {
return true
}
} else {
m := &markAndRef{false, node}
if atomic.CompareAndSwapPointer(
(*unsafe.Pointer)(unsafe.Pointer(&pred.m)),
unsafe.Pointer(pred_m),
unsafe.Pointer(m)) {
return true
}
}
// Another thread has modified the pred node, by either marking it as
// deleted or by inserting another node directly after it. The other
// thread progressed, but we need to retry our insert.
}
panic("not reachable")
}
示例6: next
func (self *element) next() *element {
next := atomic.LoadPointer(&self.Pointer)
for next != nil {
/*
If the pointer of the next element is marked as deleted, that means the next element is supposed to be GONE
*/
if nextPointer := atomic.LoadPointer(&(*element)(normal(next)).Pointer); isDeleted(nextPointer) {
/*
If OUR pointer is marked as deleted, that means WE are supposed to be gone
*/
if isDeleted(next) {
/*
.. which means that we can steal the pointer of the next element right away,
it points to the right place AND it is marked as deleted.
*/
atomic.CompareAndSwapPointer(&self.Pointer, next, nextPointer)
} else {
/*
.. if not, we have to remove the marking on the pointer before we steal it.
*/
atomic.CompareAndSwapPointer(&self.Pointer, next, normal(nextPointer))
}
next = atomic.LoadPointer(&self.Pointer)
} else {
/*
If the next element is NOT deleted, then we simply return a pointer to it, and make
damn sure that the pointer is a working one even if we are deleted (and, therefore,
our pointer is marked as deleted).
*/
return (*element)(normal(next))
}
}
return nil
}
示例7: Dequeue
// Dequeue returns the value at the head of the queue and true, or if the queue is empty, it returns a nil value and false
func (q *ZFifo) Dequeue() (value interface{}, ok bool) {
for {
head := atomic.LoadPointer(&q.head) // Read head pointer
tail := atomic.LoadPointer(&q.tail) // Read tail pointer
next := atomic.LoadPointer(&(*lfNode)(head).next) // Read head.next
if head != q.head { // Check head, tail, and next consistency
continue // Not consistent. Try again
}
if head == tail { // Is queue empty or tail failing behind
if next == unsafe.Pointer(q) { // Is queue empty?
return
}
// Try to swing tail to the next node as the tail was not pointing to the last node
atomic.CompareAndSwapPointer(&q.tail, tail, next)
} else {
// Read value before CAS
// Otherwise, another dequeue might free the next node
value = (*lfNode)(next).value
// Try to swing Head to the next node
if atomic.CompareAndSwapPointer(&q.head, head, next) {
ok = true
return
}
value = nil
}
}
return // Dummy return
}
示例8: Insert
// Insert inserts v into the list in order. An error is returned if v is already present.
func (l *partitionList) Insert(v partition.Partition) error {
n := &partitionListNode{
val: v,
next: nil,
}
HEAD:
headPtr := atomic.LoadPointer(&l.head)
if headPtr == nil {
if !atomic.CompareAndSwapPointer(&l.head, headPtr, unsafe.Pointer(n)) {
goto HEAD
}
atomic.AddInt32(&l.size, 1)
return nil
}
headNode := (*partitionListNode)(headPtr)
if comparePartitions(headNode.val, n.val) > 0 {
n.next = headPtr
if !atomic.CompareAndSwapPointer(&l.head, headPtr, unsafe.Pointer(n)) {
goto HEAD
}
atomic.AddInt32(&l.size, 1)
return nil
}
NEXT:
nextPtr := atomic.LoadPointer(&headNode.next)
if nextPtr == nil {
if !atomic.CompareAndSwapPointer(&headNode.next, nextPtr, unsafe.Pointer(n)) {
goto NEXT
}
atomic.AddInt32(&l.size, 1)
return nil
}
nextNode := (*partitionListNode)(nextPtr)
if comparePartitions(nextNode.val, n.val) > 0 {
n.next = nextPtr
if !atomic.CompareAndSwapPointer(&headNode.next, nextPtr, unsafe.Pointer(n)) {
goto NEXT
}
atomic.AddInt32(&l.size, 1)
return nil
}
if comparePartitions(nextNode.val, n.val) == 0 {
return errors.New("catena/partition_list: partition exists")
}
headNode = nextNode
goto NEXT
}
示例9: find
// find returns the nodes of either side of a specific key. It will physically
// delete all nodes marked for deletion while traversing the list.
func (l *List) find(key string) (pred *node, pred_m *markAndRef, curr *node, curr_m *markAndRef) {
retry:
for {
curr = (*node)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&l.head))))
for curr != nil {
curr_m = (*markAndRef)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&curr.m))))
if curr_m.marked {
// curr is marked as deleted. Try to remove it physically by
// unlinking the node from the list.
if pred == nil {
if !atomic.CompareAndSwapPointer(
(*unsafe.Pointer)(unsafe.Pointer(&l.head)),
unsafe.Pointer(curr),
unsafe.Pointer(curr_m.next)) {
// Another thread has modified the head pointer of our
// list. The other thread progressed, but we need to
// restart the list traversal.
continue retry
}
} else {
m := &markAndRef{false, curr_m.next}
if !atomic.CompareAndSwapPointer(
(*unsafe.Pointer)(unsafe.Pointer(&pred.m)),
unsafe.Pointer(pred_m),
unsafe.Pointer(m)) {
// Another thread has progressed by modifying the next
// pointer of our predecessor. We need to traverse the
// list again.
continue retry
}
pred_m = m
}
curr = curr_m.next
continue
}
if curr.key >= key {
return
}
pred = curr
pred_m = curr_m
curr = curr_m.next
}
return
}
panic("not reachable")
}
示例10: enqueue1
func (q *Queue) enqueue1(x string) {
newValue := unsafe.Pointer(&Node{body: x, next: nil})
var tail, next unsafe.Pointer
for {
tail = q.tail
next = ((*Node)(tail)).next
if next != nil {
atomic.CompareAndSwapPointer(&(q.tail), tail, next)
} else if atomic.CompareAndSwapPointer(&((*Node)(tail).next), nil, newValue) {
break
}
runtime.Gosched()
}
}
示例11: Log
// Log implements the Log method required by Backend.
func (b *MemoryBackend) Log(level Level, calldepth int, rec *Record) error {
var size int32
n := &node{Record: rec}
np := unsafe.Pointer(n)
// Add the record to the tail. If there's no records available, tail and
// head will both be nil. When we successfully set the tail and the previous
// value was nil, it's safe to set the head to the current value too.
for {
tailp := b.tail
swapped := atomic.CompareAndSwapPointer(
&b.tail,
tailp,
np,
)
if swapped == true {
if tailp == nil {
b.head = np
} else {
(*node)(tailp).next = n
}
size = atomic.AddInt32(&b.size, 1)
break
}
}
// Since one record was added, we might have overflowed the list. Remove
// a record if that is the case. The size will fluctate a bit, but
// eventual consistent.
if b.maxSize > 0 && size > b.maxSize {
for {
headp := b.head
head := (*node)(b.head)
if head.next == nil {
break
}
swapped := atomic.CompareAndSwapPointer(
&b.head,
headp,
unsafe.Pointer(head.next),
)
if swapped == true {
atomic.AddInt32(&b.size, -1)
break
}
}
}
return nil
}
示例12: enq
func (q *Q) enq(val interface{}) {
var t, n unsafe.Pointer
n = unsafe.Pointer(&node{val: val, nxt: nil})
for {
t = q.tail
nxt := ((*node)(t)).nxt
if nxt != nil {
atomic.CompareAndSwapPointer(&q.tail, t, nxt)
} else if atomic.CompareAndSwapPointer(&((*node)(t)).nxt, nil, n) {
break
}
}
atomic.CompareAndSwapPointer(&q.tail, t, n)
}
示例13: enqueue2
func (q *Queue) enqueue2(x string) {
node := unsafe.Pointer(&Node{body: x, next: nil})
p := atomic.LoadPointer(&q.tail)
oldp := p
for {
for ((*Node)(p)).next != nil {
p = ((*Node)(p).next)
}
if atomic.CompareAndSwapPointer(&(((*Node)(p)).next), nil, node) {
break
}
}
atomic.CompareAndSwapPointer(&(q.tail), oldp, node)
}
示例14: Swap
func (l *partitionList) Swap(old, new partition.Partition) error {
n := &partitionListNode{
val: new,
next: nil,
}
HEAD:
headPtr := atomic.LoadPointer(&l.head)
if headPtr == nil {
return errors.New("catena/partition_list: partition not found")
}
headNode := (*partitionListNode)(headPtr)
if comparePartitions(headNode.val, n.val) == 0 {
n.next = headNode.next
if !atomic.CompareAndSwapPointer(&l.head, headPtr, unsafe.Pointer(n)) {
goto HEAD
}
return nil
}
NEXT:
nextPtr := atomic.LoadPointer(&headNode.next)
if nextPtr == nil {
return errors.New("catena/partition_list: partition not found")
}
nextNode := (*partitionListNode)(nextPtr)
if comparePartitions(nextNode.val, n.val) == 0 {
n.next = nextNode.next
if !atomic.CompareAndSwapPointer(&headNode.next, nextPtr, unsafe.Pointer(n)) {
goto NEXT
}
return nil
}
if comparePartitions(nextNode.val, n.val) > 0 {
return errors.New("catena/partition_list: partition not found")
}
headNode = nextNode
goto NEXT
}
示例15: disperse2
// helper function for subdivide()
//
// places all points in the tree in the appropriate quadrant,
// and clears the points of this tree.
func (q *LockfreeQuadtree) disperse2() {
for {
oldPoints := (*PointList)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&q.Points))))
if oldPoints == nil || oldPoints.Length == 0 {
break
}
newPoints := *oldPoints
p := *newPoints.First.Point
newPoints.First = newPoints.First.Next
newPoints.Length--
ok := atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&q.Points)), unsafe.Pointer(oldPoints), unsafe.Pointer(&newPoints))
if !ok {
continue
}
ok = q.Nw.Insert(&p) || q.Ne.Insert(&p) || q.Sw.Insert(&p) || q.Se.Insert(&p)
// debug
if !ok {
panic("quadtree contained a point outside boundary")
}
}
// we don't need to compare. We know it needs set at nil now; if someone else set it first, setting again doesn't hurt.
// this does need to be atomic, however. Else, Query() might read a pointer which was half-set to nil
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&q.Points)), nil)
}