fermentord/vendor/github.com/JuulLabs-OSS/ble/darwin/event.go

114 lines
2.3 KiB
Go
Raw Normal View History

package darwin
import (
"sync"
)
// eventSlot is a receiver for asynchronous events from CoreBluetooth. To
// prevent deadlock in the case of spurious events, eventSlot discards incoming
// signals if it is not explicitly listening for them.
type eventSlot struct {
ch chan interface{}
mtx sync.Mutex
}
func (e *eventSlot) closeNoLock() {
if e.ch == nil {
return
}
// Drain channel.
for len(e.ch) > 0 {
<-e.ch
}
close(e.ch)
e.ch = nil
}
func (e *eventSlot) Close() {
e.mtx.Lock()
defer e.mtx.Unlock()
e.closeNoLock()
}
// Listen listens for a single event on this slot. It returns the channel on
// which the event will be received.
func (e *eventSlot) Listen() chan interface{} {
e.mtx.Lock()
defer e.mtx.Unlock()
if e.ch != nil {
e.closeNoLock()
}
e.ch = make(chan interface{})
return e.ch
}
// RxSignal causes the event slot to process the given signal (i.e., it sends a
// signal to the slot). It blocks until the signal is consumed by a client or
// until the slot is closed.
func (e *eventSlot) RxSignal(sig interface{}) {
e.mtx.Lock()
defer e.mtx.Unlock()
if e.ch == nil {
// Not listening. Discard signal.
return
}
e.ch <- sig
// Stop listening.
e.closeNoLock()
}
type eventConnected struct {
conn *conn
err error
}
type eventRSSIRead struct {
rssi int
err error
}
// Each Client owns one of these (us-as-central).
type clientEventListener struct {
svcsDiscovered eventSlot // error
chrsDiscovered eventSlot // error
dscsDiscovered eventSlot // error
chrWritten eventSlot // error
dscRead eventSlot // error
dscWritten eventSlot // error
notifyChanged eventSlot // error
rssiRead eventSlot // *eventRSSIRead
}
func (cevl *clientEventListener) Close() {
cevl.svcsDiscovered.Close()
cevl.chrsDiscovered.Close()
cevl.dscsDiscovered.Close()
cevl.chrWritten.Close()
cevl.dscRead.Close()
cevl.dscWritten.Close()
cevl.notifyChanged.Close()
cevl.rssiRead.Close()
}
// Each Device owns one of these (us-as-peripheral).
type deviceEventListener struct {
stateChanged eventSlot // struct{}
connected eventSlot // *eventConnected
svcAdded eventSlot // error
advStarted eventSlot // error
}
func (devl *deviceEventListener) Close() {
devl.stateChanged.Close()
devl.svcAdded.Close()
devl.advStarted.Close()
}