Skip to content

Instantly share code, notes, and snippets.

@liyiheng
Last active May 9, 2019 06:01
Show Gist options
  • Select an option

  • Save liyiheng/5c678020ac165dee319672fcd1e0a8cf to your computer and use it in GitHub Desktop.

Select an option

Save liyiheng/5c678020ac165dee319672fcd1e0a8cf to your computer and use it in GitHub Desktop.
Code with bugs
package main
import (
"fmt"
"sync"
"sync/atomic"
"time"
"unsafe"
)
func main() {
now := time.Now()
l := new(lockFreeList)
l.Add(&node{Value: 999999})
l.Add(&node{Value: 333333})
l.Add(&node{Value: 555555})
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(m int) {
for j := m; j < 10000; j += 10 {
l.Add(&node{Value: j})
//l.AddWithLock(&node{Value: j})
//l.LockFreeAdd(&node{Value: j})
}
fmt.Println("Worker", m, "finished")
wg.Done()
}(i)
}
wg.Wait()
fmt.Println(time.Now().Sub(now))
result := make(map[int]struct{})
hd := l.Head
for hd != nil {
n := ((*node)(hd))
if _, ok := result[n.Value]; ok {
fmt.Println(n.Value, "repeated")
time.Sleep(time.Millisecond * 300)
} else {
result[n.Value] = struct{}{}
}
hd = n.Next
}
fmt.Println("----", len(result))
for i := 0; i < 10; i++ {
if _, ok := result[i]; !ok {
fmt.Println(i, "missing")
}
}
}
type (
node struct {
Value int
Next unsafe.Pointer
}
lockFreeList struct {
Head unsafe.Pointer
Tail unsafe.Pointer
sync.RWMutex
}
)
func (l *lockFreeList) addHead(n *node) bool {
elem := unsafe.Pointer(n)
ok := atomic.CompareAndSwapPointer(&l.Head, nil, elem)
if !ok {
return false
}
return atomic.CompareAndSwapPointer(&l.Tail, nil, elem)
}
func (l *lockFreeList) Add(n *node) {
for {
if l.Head == nil {
ok := l.addHead(n)
if ok {
break
}
continue
}
//next := ((*node)(l.Tail)).Next
elem := unsafe.Pointer(n)
if !atomic.CompareAndSwapPointer(&((*node)(l.Tail)).Next, nil, elem) {
continue
}
tail := l.Tail
if !atomic.CompareAndSwapPointer(&l.Tail, tail, elem) {
continue
}
break
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment