mirror of
https://github.com/jetkvm/kvm.git
synced 2025-09-16 08:38:14 +00:00
This change replaces all instances of GetConfig() function calls with direct access to the Config variable throughout the audio package. The modification improves performance by eliminating function call overhead and simplifies the codebase by removing unnecessary indirection. The commit also includes minor optimizations in validation logic and connection handling, while maintaining all existing functionality. Error handling remains robust with appropriate fallbacks when config values are not available. Additional improvements include: - Enhanced connection health monitoring in UnifiedAudioClient - Optimized validation functions using cached config values - Reduced memory allocations in hot paths - Improved error recovery during quality changes
128 lines
3.3 KiB
Go
128 lines
3.3 KiB
Go
package audio
|
|
|
|
import (
|
|
"sync/atomic"
|
|
"time"
|
|
"unsafe"
|
|
)
|
|
|
|
// MicrophoneContentionManager manages microphone access with cooldown periods
|
|
type MicrophoneContentionManager struct {
|
|
// Atomic fields MUST be first for ARM32 alignment (int64 fields need 8-byte alignment)
|
|
lastOpNano int64
|
|
cooldownNanos int64
|
|
operationID int64
|
|
|
|
lockPtr unsafe.Pointer
|
|
}
|
|
|
|
func NewMicrophoneContentionManager(cooldown time.Duration) *MicrophoneContentionManager {
|
|
return &MicrophoneContentionManager{
|
|
cooldownNanos: int64(cooldown),
|
|
}
|
|
}
|
|
|
|
type OperationResult struct {
|
|
Allowed bool
|
|
RemainingCooldown time.Duration
|
|
OperationID int64
|
|
}
|
|
|
|
func (mcm *MicrophoneContentionManager) TryOperation() OperationResult {
|
|
now := time.Now().UnixNano()
|
|
cooldown := atomic.LoadInt64(&mcm.cooldownNanos)
|
|
lastOp := atomic.LoadInt64(&mcm.lastOpNano)
|
|
elapsed := now - lastOp
|
|
|
|
if elapsed >= cooldown {
|
|
if atomic.CompareAndSwapInt64(&mcm.lastOpNano, lastOp, now) {
|
|
opID := atomic.AddInt64(&mcm.operationID, 1)
|
|
return OperationResult{
|
|
Allowed: true,
|
|
RemainingCooldown: 0,
|
|
OperationID: opID,
|
|
}
|
|
}
|
|
// Retry once if CAS failed
|
|
lastOp = atomic.LoadInt64(&mcm.lastOpNano)
|
|
elapsed = now - lastOp
|
|
if elapsed >= cooldown && atomic.CompareAndSwapInt64(&mcm.lastOpNano, lastOp, now) {
|
|
opID := atomic.AddInt64(&mcm.operationID, 1)
|
|
return OperationResult{
|
|
Allowed: true,
|
|
RemainingCooldown: 0,
|
|
OperationID: opID,
|
|
}
|
|
}
|
|
}
|
|
|
|
remaining := time.Duration(cooldown - elapsed)
|
|
if remaining < 0 {
|
|
remaining = 0
|
|
}
|
|
|
|
return OperationResult{
|
|
Allowed: false,
|
|
RemainingCooldown: remaining,
|
|
OperationID: atomic.LoadInt64(&mcm.operationID),
|
|
}
|
|
}
|
|
|
|
func (mcm *MicrophoneContentionManager) SetCooldown(cooldown time.Duration) {
|
|
atomic.StoreInt64(&mcm.cooldownNanos, int64(cooldown))
|
|
}
|
|
|
|
func (mcm *MicrophoneContentionManager) GetCooldown() time.Duration {
|
|
return time.Duration(atomic.LoadInt64(&mcm.cooldownNanos))
|
|
}
|
|
|
|
func (mcm *MicrophoneContentionManager) GetLastOperationTime() time.Time {
|
|
nanos := atomic.LoadInt64(&mcm.lastOpNano)
|
|
if nanos == 0 {
|
|
return time.Time{}
|
|
}
|
|
return time.Unix(0, nanos)
|
|
}
|
|
|
|
func (mcm *MicrophoneContentionManager) GetOperationCount() int64 {
|
|
return atomic.LoadInt64(&mcm.operationID)
|
|
}
|
|
|
|
func (mcm *MicrophoneContentionManager) Reset() {
|
|
atomic.StoreInt64(&mcm.lastOpNano, 0)
|
|
atomic.StoreInt64(&mcm.operationID, 0)
|
|
}
|
|
|
|
var (
|
|
globalMicContentionManager unsafe.Pointer
|
|
micContentionInitialized int32
|
|
)
|
|
|
|
func GetMicrophoneContentionManager() *MicrophoneContentionManager {
|
|
ptr := atomic.LoadPointer(&globalMicContentionManager)
|
|
if ptr != nil {
|
|
return (*MicrophoneContentionManager)(ptr)
|
|
}
|
|
|
|
if atomic.CompareAndSwapInt32(&micContentionInitialized, 0, 1) {
|
|
manager := NewMicrophoneContentionManager(Config.MicContentionTimeout)
|
|
atomic.StorePointer(&globalMicContentionManager, unsafe.Pointer(manager))
|
|
return manager
|
|
}
|
|
|
|
ptr = atomic.LoadPointer(&globalMicContentionManager)
|
|
if ptr != nil {
|
|
return (*MicrophoneContentionManager)(ptr)
|
|
}
|
|
|
|
return NewMicrophoneContentionManager(Config.MicContentionTimeout)
|
|
}
|
|
|
|
func TryMicrophoneOperation() OperationResult {
|
|
return GetMicrophoneContentionManager().TryOperation()
|
|
}
|
|
|
|
func SetMicrophoneCooldown(cooldown time.Duration) {
|
|
GetMicrophoneContentionManager().SetCooldown(cooldown)
|
|
}
|