Skip to content

Commit

Permalink
add myonce
Browse files Browse the repository at this point in the history
  • Loading branch information
guonaihong committed May 20, 2024
1 parent c3ac38c commit fc13e78
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
3 changes: 0 additions & 3 deletions frame/frame_v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,6 @@ func ReadHeader(r io.Reader, headArray *[enum.MaxFrameHeaderSize]byte) (h FrameH
switch {
// 长度
case h.PayloadLen >= 0 && h.PayloadLen <= 125:
if h.PayloadLen == 0 && !h.Mask {
return
}
case h.PayloadLen == 126:
// 2字节长度
have += 2
Expand Down
33 changes: 33 additions & 0 deletions myonce/myonce.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package myonce

import (
"sync"
"sync/atomic"
)

type MyOnce struct {
done uint32
}

func (o *MyOnce) Do(mu *sync.Mutex, f func()) {

if atomic.LoadUint32(&o.done) == 0 {

o.doSlow(mu, f)
}
}

// 这里与标准库的做法不一样,标准库是保证了f执行之后才会设置done为1
// 这里是先设置done为1,然后再执行f
// 标准库是站在资源必须初始化成功的角度设计,而这里主要是为了解决资源释放自己调用自己的死锁问题
// 试想下这个场景;
// 出错会调用用户的OnClose函数,这个函数会被包在sync.Once里面,而OnClose函数中又会调用Close函数,这个函数里面也会有调用OnClose的逻辑,这样就会死锁
// 如果前置设置done为1,那么就不会有这个问题
func (o *MyOnce) doSlow(mu *sync.Mutex, f func()) {
mu.Lock()
defer mu.Unlock()
if o.done == 0 {
atomic.StoreUint32(&o.done, 1)
f()
}
}

0 comments on commit fc13e78

Please sign in to comment.