Files
cthulhu/internal/app/speech_uninterruptible.go

57 lines
1.5 KiB
Go

// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package app
import (
"context"
"time"
)
// Bound protection even if the backend never reports completion. The deadline
// starts at admission, covering time spent in the bounded pending queue too.
const uninterruptibleSpeechTimeout = 30 * time.Second
func (worker *speechWorker) has_uninterruptible_locked() bool {
if worker.uninterruptibleContext != nil && worker.uninterruptibleContext.Err() == nil {
return true
}
for _, request := range worker.pending {
if request.Uninterruptible && request.context != nil && request.context.Err() == nil {
return true
}
}
return false
}
// Preserve unrelated queued speech, just as ordinary presentation revocation
// does. The existing cancellation barrier prevents CANCEL overtaking it.
func (worker *speechWorker) stop_uninterruptible() {
worker.mutex.Lock()
defer worker.mutex.Unlock()
retained := worker.pending[:0]
for _, request := range worker.pending {
if request.Uninterruptible {
completeSpeechRequest(request, context.Canceled)
} else {
retained = append(retained, request)
}
}
clear(worker.pending[len(retained):])
worker.pending = retained
if worker.uninterruptibleCancel == nil || !worker.running {
return
}
worker.uninterruptibleCancel()
worker.presentationDelivery = nil
if worker.beepCancel != nil {
worker.beepCancel()
}
worker.generation++
worker.interrupting = true
select {
case worker.interrupt <- struct{}{}:
default:
}
}