本文整理匯總了Golang中sync/atomic.LoadPointer函數的典型用法代碼示例。如果您正苦於以下問題:Golang LoadPointer函數的具體用法?Golang LoadPointer怎麽用?Golang LoadPointer使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了LoadPointer函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: GetOrInsert
func (m *Map) GetOrInsert(k uint64, v unsafe.Pointer) unsafe.Pointer {
if v == nil {
log.Fatal("GetOrInsert doesn't allow setting nil pointers.")
return nil
}
// Check immutable first.
cval := atomic.LoadPointer(&m.cs[IMMUTABLE])
if cval != nil {
c := (*container)(cval)
if pv := c.get(k); pv != nil {
return pv
}
}
// Okay, deal with mutable container now.
cval = atomic.LoadPointer(&m.cs[MUTABLE])
if cval == nil {
log.Fatal("This is disruptive in a bad way.")
}
c := (*container)(cval)
if pv := c.getOrInsert(k, v); pv != nil {
return pv
}
// We still couldn't insert the key. Time to grow.
// TODO: Handle this case.
return nil
}
示例2: 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
}
示例3: Preparex
func (db *DB) Preparex(query string) (stmt Stmt, err error) {
var m stmtCache
if p := (*stmtCache)(atomic.LoadPointer(&db.stmtCachePtr)); p != nil {
m = *p
if stmt = m[query]; stmt.Stmt != nil {
return
}
}
db.stmtCachePtrMutex.Lock()
defer db.stmtCachePtrMutex.Unlock()
if p := (*stmtCache)(atomic.LoadPointer(&db.stmtCachePtr)); p != nil {
m = *p
if stmt = m[query]; stmt.Stmt != nil {
return
}
}
stmtx, err := db.DB.Preparex(query)
if err != nil {
return
}
stmt = Stmt{Stmt: stmtx}
m2 := make(stmtCache, len(m)+1)
for k, v := range m {
m2[k] = v
}
m2[query] = stmt
atomic.StorePointer(&db.stmtCachePtr, unsafe.Pointer(&m2))
return
}
示例4: 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
}
示例5: mutate
func (p *partitionstore) mutate(cb func(keys, changes *gkvlite.Collection)) {
p.lock.Lock()
defer p.lock.Unlock()
cb((*gkvlite.Collection)(atomic.LoadPointer(&p.keys)),
(*gkvlite.Collection)(atomic.LoadPointer(&p.changes)))
}
示例6: visitItems
func (p *partitionstore) visitItems(start []byte, withValue bool,
visitor func(*item) bool) (err error) {
keys, changes := p.colls()
var vErr error
v := func(kItem *gkvlite.Item) bool {
i := (*item)(atomic.LoadPointer(&kItem.Transient))
if i != nil {
return visitor(i)
}
var cItem *gkvlite.Item
cItem, vErr = changes.GetItem(kItem.Val, true)
if vErr != nil {
return false
}
if cItem == nil {
return true // TODO: track this case; might have been compacted away.
}
i = (*item)(atomic.LoadPointer(&cItem.Transient))
if i != nil {
atomic.StorePointer(&kItem.Transient, unsafe.Pointer(i))
return visitor(i)
}
i = &item{key: kItem.Key}
if vErr = i.fromValueBytes(cItem.Val); vErr != nil {
return false
}
atomic.StorePointer(&cItem.Transient, unsafe.Pointer(i))
atomic.StorePointer(&kItem.Transient, unsafe.Pointer(i))
return visitor(i)
}
if err := p.visit(keys, start, true, v); err != nil {
return err
}
return vErr
}
示例7: cacheEvict
func (cache *DCache) cacheEvict(fpos int64) Node {
var node Node
idx := cache.indexFor(fpos)
for {
var retry bool
hash := (*[]unsafe.Pointer)(atomic.LoadPointer(&(cache.hash)))
addr := &((*hash)[idx])
hd := (*DCacheItem)(atomic.LoadPointer(addr))
for hd != nil {
nx := atomic.LoadPointer(&hd.next)
if hd.fpos == fpos {
if !atomic.CompareAndSwapPointer(addr, unsafe.Pointer(hd), nx) {
retry = true
} else {
node = hd.node
}
break
}
addr = &hd.next
hd = (*DCacheItem)(nx)
}
if retry {
continue
}
break
}
return node
}
示例8: next
func (self *element) next() *element {
next := atomic.LoadPointer(&self.Pointer)
for next != nil {
nextElement := (*element)(next)
/*
If our next element contains &deletedElement that means WE are deleted, and
we can just return the next-next element. It will make it impossible to add
stuff to us, since we will always lie about our next(), but then again, deleted
elements shouldn't get new children anyway.
*/
if sp, ok := nextElement.value.(*string); ok && sp == &deletedElement {
return nextElement.next()
}
/*
If our next element is itself deleted (by the same criteria) then we will just replace
it with its next() (which should be the first thing behind it that isn't itself deleted
(the power of recursion compels you) and then check again.
*/
if nextElement.isDeleted() {
atomic.CompareAndSwapPointer(&self.Pointer, next, unsafe.Pointer(nextElement.next()))
next = atomic.LoadPointer(&self.Pointer)
} else {
/*
If it isn't deleted then we just return it.
*/
return nextElement
}
}
/*
And if our next is nil, then we are at the end of the list and can just return nil for next()
*/
return nil
}
示例9: 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
}
示例10: advance
func (this *MapIterator) advance() {
if this.nextE != nil {
this.nextE = this.nextE.next
if this.nextE != nil {
return
}
}
for this.nextTableIndex >= 0 {
this.nextE = (*Entry)(atomic.LoadPointer(&this.currentTable[this.nextTableIndex]))
this.nextTableIndex--
if this.nextE != nil {
return
}
}
for this.nextSegmentIndex >= 0 {
seg := this.cm.segments[this.nextSegmentIndex]
this.nextSegmentIndex--
if atomic.LoadInt32(&seg.count) != 0 {
this.currentTable = seg.loadTable()
for j := len(this.currentTable) - 1; j >= 0; j-- {
this.nextE = (*Entry)(atomic.LoadPointer(&this.currentTable[j]))
if this.nextE != nil {
this.nextTableIndex = j - 1
return
}
}
}
}
}
示例11: checkPingPong
func (wstore *WStore) checkPingPong() {
ncping := (*map[int64]Node)(atomic.LoadPointer(&wstore.ncping))
ncpong := (*map[int64]Node)(atomic.LoadPointer(&wstore.ncpong))
if len(*ncping) != len(*ncpong) {
panic("Mismatch in nc ping-pong lengths")
}
for fpos := range *ncping {
if (*ncpong)[fpos] == nil {
panic("fpos not found in nc ping-pong")
}
}
//lcping := (*map[int64]Node)(atomic.LoadPointer(&wstore.lcping))
//lcpong := (*map[int64]Node)(atomic.LoadPointer(&wstore.lcpong))
//if len(*lcping) != len(*lcpong) {
// panic("Mismatch in lc ping-pong lengths")
//}
//for fpos := range *lcping {
// if (*lcpong)[fpos] == nil {
// panic("fpos not found in lc ping-pong")
// }
//}
kdping := (*map[int64][]byte)(atomic.LoadPointer(&wstore.kdping))
kdpong := (*map[int64][]byte)(atomic.LoadPointer(&wstore.kdpong))
if len(*kdping) != len(*kdpong) {
panic("Mismatch in kd ping-pong lengths")
}
for fpos := range *kdping {
if (*kdpong)[fpos] == nil {
panic("fpos not found in kd ping-pong")
}
}
}
示例12: Seek
// Seek seeks the handle.
func (t *BoundedTable) Seek(ctx context.Context, handle int64) (int64, bool, error) {
result := (*boundedItem)(nil)
if handle < invalidRecordID {
// this is the first seek call.
result = (*boundedItem)(atomic.LoadPointer(&t.records[0]))
} else {
for i := int64(0); i < t.capacity; i++ {
record := (*boundedItem)(atomic.LoadPointer(&t.records[i]))
if record == nil {
break
}
if handle == record.handle {
result = record
break
}
}
}
if result == nil {
// handle not found.
return invalidRecordID, false, nil
}
if result.handle != invalidRecordID {
// this record is valid.
return result.handle, true, nil
}
// this record is invalid.
return invalidRecordID, false, nil
}
示例13: gcasRead
// gcasRead performs a GCAS-linearizable read of the I-node's main node.
func gcasRead(in *iNode, ctrie *ctrie) *mainNode {
m := (*mainNode)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&in.main))))
prev := (*mainNode)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&m.prev))))
if prev == nil {
return m
}
return gcasComplete(in, m, ctrie)
}
示例14: 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
}
示例15: getBucket
func (r *Cache) getBucket(hash uint32) (*mNode, *mBucket) {
h := (*mNode)(atomic.LoadPointer(&r.mHead))
i := hash & h.mask
b := (*mBucket)(atomic.LoadPointer(&h.buckets[i]))
if b == nil {
b = h.initBucket(i)
}
return h, b
}