2014-12-15 16 views
5

Git'e float32 değerlerini atomik olarak eklemek için bir işleve ihtiyacım var.Go atomic.AddFloat32()

package atomic 

import (
    "sync/atomic" 
    "unsafe" 
    "math" 
) 

func AddFloat32(addr *float32, delta float32) (new float32) { 
    unsafeAddr := (*uint32)(unsafe.Pointer(addr)) 

    for { 
     oldValue := math.Float32bits(*addr) 
     new  = *addr + delta 
     newValue := math.Float32bits(new) 

     if atomic.CompareAndSwapUint32(unsafeAddr, oldValue, newValue) { 
      return 
     } 
    } 
} 

o (yani gerçekten atom olun) çalışması yapılmalıdır: Bu Bulduğum bazı C koduna göre geldi nedir? Go'da daha iyi/hızlı bir yolu var mı?

cevap

3

Uyum sağlamak için Go standart kitaplığından bazı kodlar arayın. Örneğin, olur float32 için

func addUint64(val *uint64, delta uint64) (new uint64) { 
    for { 
     old := *val 
     new = old + delta 
     if CompareAndSwapUint64(val, old, new) { 
      break 
     } 
    } 
    return 
} 

, go/src/sync/atomic/64bit_arm.go den

package main 

import (
    "fmt" 
    "math" 
    "sync/atomic" 
    "unsafe" 
) 

func AddFloat32(val *float32, delta float32) (new float32) { 
    for { 
     old := *val 
     new = old + delta 
     if atomic.CompareAndSwapUint32(
      (*uint32)(unsafe.Pointer(val)), 
      math.Float32bits(old), 
      math.Float32bits(new), 
     ) { 
      break 
     } 
    } 
    return 
} 

func main() { 
    val, delta := float32(math.Pi), float32(math.E) 
    fmt.Println(val, delta, val+delta) 
    new := AddFloat32(&val, delta) 
    fmt.Println(val, new) 
} 

Çıktı:

 
3.1415927 2.7182817 5.8598747 
5.8598747 5.8598747 
+0

@JimB: Eğer, bu başarısız olabilir demek bunu bağlıdır anlamına yaptığınızda hedef mimarlık? Alıntı kod sadece/kol/src/sync/atomic/64bit_arm.go'dan sadece kolda güvenilir mi? –

+0

@ B_old: Üzgünüm, konuyu burada yeterince karıştırmış gibi görünüyor. @ PeterSO'nun örneğinin doğru olduğunu ve float32 değerini doğru şekilde güncelleyeceğini kabul ediyorum. Yaptığım yorum, sadece yarış dedektörü ve şu anda değil de * korumalı okumayı * * addr'den * nasıl * işaretleyebiliyordu. Kodun '-race 'altından geçmesini sağlamak genellikle çok önemlidir ve eğer gelecekte bunu gösterirse, etrafta çalışmak zor değildir. (eski yorumları kaldırdılar ve gerçekten kullanışlı değillerdi) – JimB