From fc13e78cf0f3873ba5b7628a480f37caada76736 Mon Sep 17 00:00:00 2001 From: guonaihong Date: Mon, 20 May 2024 21:27:31 +0800 Subject: [PATCH] add myonce --- frame/frame_v1.go | 3 --- myonce/myonce.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 myonce/myonce.go diff --git a/frame/frame_v1.go b/frame/frame_v1.go index f1956b3..98f2008 100644 --- a/frame/frame_v1.go +++ b/frame/frame_v1.go @@ -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 diff --git a/myonce/myonce.go b/myonce/myonce.go new file mode 100644 index 0000000..dc10519 --- /dev/null +++ b/myonce/myonce.go @@ -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() + } +}