summaryrefslogtreecommitdiff
path: root/redo/uitask.go
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-07-19 09:57:01 -0400
committerPietro Gagliardi <[email protected]>2014-07-19 09:57:01 -0400
commit104337188f1d7bcdb0774748f41cb91a06216122 (patch)
tree21da8ff026a6a82547294b005d6e2b59869575c1 /redo/uitask.go
parent48c5055eb960d6db3d3b997bdc859670f473a277 (diff)
Removed Request completely, also updating the uitask files. Also renamed xperform to doissue for consistency.
Diffstat (limited to 'redo/uitask.go')
-rw-r--r--redo/uitask.go93
1 files changed, 25 insertions, 68 deletions
diff --git a/redo/uitask.go b/redo/uitask.go
index 42006fe..8b5e523 100644
--- a/redo/uitask.go
+++ b/redo/uitask.go
@@ -14,53 +14,32 @@ func Go() error {
if err := uiinit(); err != nil {
return err
}
- go uitask(Do)
uimsgloop()
return nil
}
-// Stop issues a Request for package ui to stop and returns immediately.
-// Some time after this request is received, Go() will return without performing any final cleanup.
-// Stop is internally issued to Do, so it will not be registered until any event handlers and dialog boxes return.
-func Stop() {
- go func() {
- c := make(chan interface{})
- Do <- &Request{
- op: func() {
- uistop()
- c <- struct{}{}
- },
- resp: c,
- }
- <-c
- }()
+// Do performs f on the main loop, as if it were an event handler.
+// It waits for f to execute before returning.
+// Do cannot be called within event handlers or within Do itself.
+func Do(f func()) {
+ done := make(chan struct{})
+ defer close(done)
+ issue(func() {
+ f()
+ done <- struct{}{}
+ })
+ <-done
}
-// This is the ui main loop.
-// It is spawned by Go as a goroutine.
-// It can also be called recursively using the recur/unrecur chain.
-func uitask(doer Doer) {
- for {
- select {
- case req := <-doer:
- // TODO foreign event
- issue(req)
- case rec := <-recur: // want to perform event
- c := make(Doer)
- rec <- c
- uitask(c)
- case <-unrecur: // finished with event
- close(doer)
- return
- }
- }
+// Stop informs package ui that it should stop.
+// Stop then returns immediately.
+// Some time after this request is received, Go() will return without performing any final cleanup.
+// Stop will not have an effect until any event handlers or dialog boxes presently active return.
+// (TODO make sure this is the case for dialog boxes)
+func Stop() {
+ issue(uistop)
}
-// Send a channel over recur to have uitask() above enter a recursive loop in which the Doer sent back becomes the active request handler.
-// Pulse unrecur when finished.
-var recur = make(chan chan Doer)
-var unrecur = make(chan struct{})
-
type event struct {
// All events internally return bool; those that don't will be wrapped around to return a dummy value.
do func(c Doer) bool
@@ -105,38 +84,16 @@ func (e *event) setbool(f func(Doer) bool) {
// This is the common code for running an event.
// It runs on the main thread without a message pump; it provides its own.
func (e *event) fire() bool {
- cc := make(chan Doer)
- recur <- cc
- c := <-cc
- close(cc)
- result := false
- finished := make(chan struct{})
- go func() {
- e.lock.Lock()
- defer e.lock.Unlock()
+ e.lock.Lock()
+ defer e.lock.Unlock()
- result = e.do(c)
- finished <- struct{}{}
- }()
- <-finished
- close(finished)
- // leave the event handler; leave it only after returning from the OS-side event handler so we must issue it like a normal Request
- issue(&Request{
- op: func() {
- unrecur <- struct{}{}
- },
- // unfortunately, closing a nil channel causes a panic
- // therefore, we have to make a dummy channel
- // TODO add conditional checks to the request handler instead?
- resp: make(chan interface{}),
- })
- return result
+ return e.do(c)
}
-// Common code for performing a Request.
+// Common code for performing a requested action (ui.Do() or ui.Stop()).
// This should run on the main thread.
// Implementations of issue() should call this.
-func perform(req *Request) {
- req.op()
- close(req.resp)
+func perform(fp unsafe.Pointer) {
+ f := (*func())(fp)
+ (*f)()
}