Added foreign events. Untested for now.
This commit is contained in:
parent
570f08a49c
commit
7c13661f4a
redo
|
@ -6,6 +6,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Go initializes and runs package ui.
|
// Go initializes and runs package ui.
|
||||||
|
@ -115,3 +116,53 @@ func perform(fp unsafe.Pointer) {
|
||||||
f := (*func())(fp)
|
f := (*func())(fp)
|
||||||
(*f)()
|
(*f)()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForeignEvent wraps a channel in such a way that it can be used safely with package ui.
|
||||||
|
type ForeignEvent struct {
|
||||||
|
c reflect.Value
|
||||||
|
e *event
|
||||||
|
d interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForeignEvent creates a new ForeignEvent with the specified channel.
|
||||||
|
// It panics if the argument is not a receivable channel.
|
||||||
|
// The returned ForeignEvent assumes ownership of the channel.
|
||||||
|
// Each time a value is received on the channel, the returned function is invoked on the main thread.
|
||||||
|
func NewForeignEvent(channel interface{}, handler func(data interface{})) *ForeignEvent {
|
||||||
|
c := reflect.ValueOf(channel)
|
||||||
|
t := c.Type()
|
||||||
|
if t.Kind() != reflect.Chan || (t.ChanDir() & reflect.RecvDir) == 0 {
|
||||||
|
panic("non-channel or non-receivable channel passed to NewForeignEvent()")
|
||||||
|
}
|
||||||
|
fe := &ForeignEvent{
|
||||||
|
c: c,
|
||||||
|
e: newEvent(),
|
||||||
|
}
|
||||||
|
fe.e.set(func() {
|
||||||
|
handler(fe.d)
|
||||||
|
})
|
||||||
|
go fe.do()
|
||||||
|
return fe
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fe *ForeignEvent) do() {
|
||||||
|
wait := make(chan struct{})
|
||||||
|
defer close(wait)
|
||||||
|
for {
|
||||||
|
v, ok := fe.c.Recv()
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fe.d = v.Interface()
|
||||||
|
Do(func() {
|
||||||
|
fe.e.fire()
|
||||||
|
wait <- struct{}{}
|
||||||
|
})
|
||||||
|
<-wait
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop ceases all future invocations of the handler passed to NewForeignEvent() on fe; the values read from the channel are merely discarded.
|
||||||
|
func (fe *ForeignEvent) Stop() {
|
||||||
|
fe.e.set(nil)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue