当前位置: 首页>>代码示例>>Golang>>正文


Golang atomic.CompareAndSwapPointer函数代码示例

本文整理汇总了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
	}
}
开发者ID:Vellocet,项目名称:gocb,代码行数:29,代码来源:memdqueue.go

示例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
}
开发者ID:smothiki,项目名称:lfreequeue,代码行数:30,代码来源:lfreequeue.go

示例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))
}
开发者ID:smothiki,项目名称:lfreequeue,代码行数:26,代码来源:lfreequeue.go

示例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
}
开发者ID:dgraph-io,项目名称:experiments,代码行数:28,代码来源:map.go

示例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")
}
开发者ID:tux21b,项目名称:goco,代码行数:36,代码来源:list.go

示例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
}
开发者ID:sedzinreri,项目名称:gotomic,代码行数:34,代码来源:list.go

示例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
}
开发者ID:egonelbre,项目名称:goqueuestest,代码行数:30,代码来源:zfifo.go

示例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
}
开发者ID:jmptrader,项目名称:catena,代码行数:59,代码来源:partition_list.go

示例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")
}
开发者ID:tux21b,项目名称:goco,代码行数:54,代码来源:list.go

示例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()
	}
}
开发者ID:rdallman,项目名称:qfree,代码行数:14,代码来源:q.go

示例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
}
开发者ID:andradeandrey,项目名称:go-ipfs,代码行数:51,代码来源:memory.go

示例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)
}
开发者ID:fmstephe,项目名称:lfqueue,代码行数:14,代码来源:lfqueue.go

示例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)
}
开发者ID:rdallman,项目名称:qfree,代码行数:14,代码来源:q.go

示例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
}
开发者ID:jmptrader,项目名称:catena,代码行数:48,代码来源:partition_list.go

示例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)
}
开发者ID:robert-butts,项目名称:quadtree,代码行数:29,代码来源:free_quadtree.go


注:本文中的sync/atomic.CompareAndSwapPointer函数示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。