func (m *trylocker) channel() chan struct{} {
	m.lock.Lock()
	ch := m.ch
	m.lock.Unlock()
	return ch
}
get broadcast channel
package trylock
import (
	"context"
	"sync"
	"sync/atomic"
	"time"
)
type TryLocker interface {
	TryLock(context.Context) bool
	TryLockTimeout(time.Duration) bool
	Lock()
	Unlock()
	RTryLock(context.Context) bool
	RTryLockTimeout(time.Duration) bool
	RLock()
	RUnlock()
}
type trylocker struct {
	state *int32
	ch chan struct{}
	lock sync.Mutex
}
var _ sync.Locker = &trylocker{}
func New() TryLocker {
	return &trylocker{
		state: new(int32),
		ch:    make(chan struct{}, 1),
	}
}
func (m *trylocker) TryLock(ctx context.Context) bool {
	for {
		if atomic.CompareAndSwapInt32(m.state, 0, -1) {
			return true
		}
		if ctx == nil {
			return false
		}
		ch := m.channel()
		select {
		case <-ch:
		case <-ctx.Done():
			return false
		}
	}
}
func (m *trylocker) TryLockTimeout(d time.Duration) bool {
	ctx, cancel := context.WithTimeout(context.Background(), d)
	defer cancel()
	return m.TryLock(ctx)
}
func (m *trylocker) RTryLock(ctx context.Context) bool {
	for {
		n := atomic.LoadInt32(m.state)
		if n >= 0 {
			if atomic.CompareAndSwapInt32(m.state, n, n+1) {
				return true
			}
		}
		if ctx == nil {
			return false
		}
		ch := m.channel()
		select {
		case <-ch:
		case <-ctx.Done():
			return false
		}
	}
}
func (m *trylocker) RTryLockTimeout(d time.Duration) bool {
	ctx, cancel := context.WithTimeout(context.Background(), d)
	defer cancel()
	return m.RTryLock(ctx)
}
func (m *trylocker) Lock() {
	m.TryLock(context.Background())
}
func (m *trylocker) RLock() {
	m.RTryLock(context.Background())
}
func (m *trylocker) Unlock() {
	if ok := atomic.CompareAndSwapInt32(m.state, -1, 0); !ok {
		panic("Unlock() failed")
	}
	m.broadcast()
}
func (m *trylocker) RUnlock() {
	n := atomic.AddInt32(m.state, -1)
	if n < 0 {
		panic("RUnlock() failed")
	}
	if n == 0 {
		m.broadcast()
	}
}