node lock をする時点でもうlock free じゃないけど…
lock free linked list のtraverse の続き
node lock をどうするか?
node にlock をいれれば、traverse で捨て子問題とかは回避できる。でも list_encabezado package では 行かの用に埋め込むのが前提だ
type User struct {
ID int
Name string
list_encabezado.ListHead
}
ListHead の中身は prev と next のpointer だけだ
type ListHead struct {
prev *ListHead
next *ListHead
}
ここにsync.RWMutext とかいれちゃえばかんたんだが、使いたくない人もいるかもしれないし、 毎node sync.RWMutext のnode が使いたくない人も取るのはいやだ。てことで
それぞれの利用者側で mutext を追加して
type User struct {
ID int
Name string
sync.RWMutex
list_encabezado.ListHead
}
ListHeadからUserのRWMutext を取得する関数を用意する
func UserMutex(head *ListHead) *sync.RWMutex {
user := list_encabezado.ElementOf(&User{}, head)
return &user.RWMutex
}
list_encabezado.ElementOf は以下のようなものだ
func ElementOf(l List, head *ListHead) unsafe.Pointer {
if head == nil || l == nil {
return nil
}
return unsafe.Pointer(uintptr(unsafe.Pointer(head)) - l.Offset())
}
で以下のようにつかっていく
user.Next(list_encabezado.LockFn(UserMutex))
user.Prev(list_encabezado.LockFn(UserMutex))
user.Delete(list_encabezado.LockFn(UserMutex))
いちよnode ごとにlock しながらすすめるようにした。(ちなみにPrev, Next のときはRLock している)
たぶん終わり。