mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
89 lines
1.8 KiB
Go
89 lines
1.8 KiB
Go
package plugin_gb28181pro
|
|
|
|
import (
|
|
"math/bits"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// PortBitmap 使用原子位图实现端口分配/回收
|
|
type PortBitmap struct {
|
|
base uint16
|
|
size uint16
|
|
bitmap []uint64
|
|
cursor uint32
|
|
}
|
|
|
|
func (pb *PortBitmap) Init(base uint16, size uint16) {
|
|
pb.base = base
|
|
pb.size = size
|
|
words := int((uint32(size) + 63) / 64)
|
|
pb.bitmap = make([]uint64, words)
|
|
atomic.StoreUint32(&pb.cursor, 0)
|
|
}
|
|
|
|
func (pb *PortBitmap) Allocate() (uint16, bool) {
|
|
if pb.size == 0 || len(pb.bitmap) == 0 {
|
|
return 0, false
|
|
}
|
|
words := len(pb.bitmap)
|
|
start := int(atomic.LoadUint32(&pb.cursor) % uint32(words))
|
|
for i := 0; i < words; i++ {
|
|
widx := (start + i) % words
|
|
for {
|
|
old := atomic.LoadUint64(&pb.bitmap[widx])
|
|
free := ^old
|
|
if free == 0 {
|
|
break
|
|
}
|
|
pick := free & -free
|
|
newv := old | pick
|
|
if atomic.CompareAndSwapUint64(&pb.bitmap[widx], old, newv) {
|
|
bit := uint64(bits.TrailingZeros64(pick))
|
|
idx := uint64(widx)*64 + bit
|
|
if idx >= uint64(pb.size) {
|
|
// 回滚越界位
|
|
for {
|
|
cur := atomic.LoadUint64(&pb.bitmap[widx])
|
|
reverted := cur &^ pick
|
|
if atomic.CompareAndSwapUint64(&pb.bitmap[widx], cur, reverted) {
|
|
break
|
|
}
|
|
}
|
|
break
|
|
}
|
|
atomic.StoreUint32(&pb.cursor, uint32(widx))
|
|
return pb.base + uint16(idx), true
|
|
}
|
|
}
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
func (pb *PortBitmap) Release(port uint16) bool {
|
|
if pb.size == 0 || len(pb.bitmap) == 0 {
|
|
return false
|
|
}
|
|
if port < pb.base {
|
|
return false
|
|
}
|
|
idx := uint32(port - pb.base)
|
|
if idx >= uint32(pb.size) {
|
|
return false
|
|
}
|
|
widx := idx / 64
|
|
bit := idx % 64
|
|
mask := uint64(1) << bit
|
|
for {
|
|
old := atomic.LoadUint64(&pb.bitmap[widx])
|
|
if old&mask == 0 {
|
|
return false
|
|
}
|
|
newv := old &^ mask
|
|
if atomic.CompareAndSwapUint64(&pb.bitmap[widx], old, newv) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
|