2019-11-21 16:19:22 +00:00
|
|
|
// +build nimbus
|
|
|
|
|
|
|
|
package nimbusbridge
|
|
|
|
|
|
|
|
import (
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
|
|
|
// RoutineQueue provides a mechanism for marshalling function calls
|
|
|
|
// so that they are run in a specific thread (the thread where
|
|
|
|
// RoutineQueue is initialized).
|
|
|
|
type RoutineQueue struct {
|
|
|
|
tid int
|
|
|
|
events chan event
|
|
|
|
}
|
|
|
|
|
2019-12-18 13:18:31 +00:00
|
|
|
type callReturn struct {
|
|
|
|
value interface{}
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
2019-11-21 16:19:22 +00:00
|
|
|
// NewRoutineQueue returns a new RoutineQueue object.
|
|
|
|
func NewRoutineQueue() *RoutineQueue {
|
|
|
|
q := &RoutineQueue{
|
|
|
|
tid: syscall.Gettid(),
|
|
|
|
events: make(chan event, 20),
|
|
|
|
}
|
|
|
|
|
|
|
|
return q
|
|
|
|
}
|
|
|
|
|
|
|
|
// event represents an event triggered by the user.
|
|
|
|
type event struct {
|
2019-12-18 13:18:31 +00:00
|
|
|
f func(chan<- callReturn)
|
|
|
|
done chan callReturn
|
2019-11-21 16:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (q *RoutineQueue) HandleEvent() {
|
2019-12-18 13:02:43 +00:00
|
|
|
if syscall.Gettid() != q.tid {
|
|
|
|
panic("HandleEvent called from wrong thread")
|
|
|
|
}
|
|
|
|
|
2019-11-21 16:19:22 +00:00
|
|
|
select {
|
|
|
|
case ev := <-q.events:
|
|
|
|
ev.f(ev.done)
|
|
|
|
default:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send executes the passed function. This method can be called safely from a
|
|
|
|
// goroutine in order to execute a Nimbus function. It is important to note that the
|
|
|
|
// passed function won't be executed immediately, instead it will be added to
|
|
|
|
// the user events queue.
|
2019-12-18 13:18:31 +00:00
|
|
|
func (q *RoutineQueue) Send(f func(chan<- callReturn)) callReturn {
|
|
|
|
ev := event{f: f, done: make(chan callReturn, 1)}
|
2019-11-21 16:19:22 +00:00
|
|
|
defer close(ev.done)
|
|
|
|
if syscall.Gettid() == q.tid {
|
|
|
|
f(ev.done)
|
|
|
|
return <-ev.done
|
|
|
|
}
|
|
|
|
q.events <- ev
|
|
|
|
return <-ev.done
|
|
|
|
}
|