summaryrefslogtreecommitdiff
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
parent48c5055eb960d6db3d3b997bdc859670f473a277 (diff)
Removed Request completely, also updating the uitask files. Also renamed xperform to doissue for consistency.
-rw-r--r--redo/request.go69
-rw-r--r--redo/uitask.go93
-rw-r--r--redo/uitask_darwin.go9
-rw-r--r--redo/uitask_unix.go7
-rw-r--r--redo/uitask_windows.c2
-rw-r--r--redo/uitask_windows.go11
6 files changed, 38 insertions, 153 deletions
diff --git a/redo/request.go b/redo/request.go
deleted file mode 100644
index 4f1d98a..0000000
--- a/redo/request.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// 6 july 2014
-
-package ui
-
-// Doer is a channel that takes Requests returned by the various functions and methods of package ui.
-// There are two main Doers: ui.Do, which is for outside event handlers, and the Doer passed into an event handler function.
-// You should not create or use your own Doers; these are meaningless.
-type Doer chan *Request
-
-// Do is the main way to issue requests to package ui.
-// Requests returned by the various functions and methods of package ui should be sent across Do to have them performed.
-// When an event is dispatched to an event handler, that event handler will receive a new Doer which is active for the life of the event handler, and any requests made to Do will block until the event handler returns.
-var Do = make(Doer)
-
-// Request represents a request issued to the package.
-// These are returned by the various functions and methods of package ui and are sent to either Do or to the currently active event handler channel.
-// There are also several convenience functions that perfrom common operations with requests.
-type Request struct {
- op func()
- resp chan interface{}
-}
-
-// Response returns a channel which is pulsed exactly once, then immeidately closed, with the response from the function that issued the request.
-// If the function does not return a value, this value will be the zero value of struct{}.
-// Otherwise, the type of this value depends on the function that created the Request.
-func (r *Request) Response() <-chan interface{} {
- return r.resp
-}
-
-// Wait is a convenience function that performs a Request and waits for that request to be processed.
-// If the request returns a value, it is discarded.
-// You should generally use Wait on functions that do not return a value.
-// See the documentation of Bool for an example.
-func Wait(c Doer, r *Request) {
- c <- r
- <-r.resp
-}
-
-// Bool is a convenience function that performs a Request that returns a bool, waits for that request to be processed, and returns the result.
-// For example:
-// if ui.Bool(ui.Do, checkbox.Checked()) { /* do stuff */ }
-func Bool(c Doer, r *Request) bool {
- c <- r
- return (<-r.resp).(bool)
-}
-
-// Int is like Bool, but for int.
-func Int(c Doer, r *Request) int {
- c <- r
- return (<-r.resp).(int)
-}
-
-// String is like Bool, but for string.
-func String(c Doer, r *Request) string {
- c <- r
- return (<-r.resp).(string)
-}
-
-// IntSlice is like Bool, but for []int.
-func IntSlice(c Doer, r *Request) []int {
- c <- r
- return (<-r.resp).([]int)
-}
-
-// StringSlice is like Bool, but for []string.
-func StringSlice(c Doer, r *Request) []string {
- c <- r
- return (<-r.resp).([]string)
-}
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)()
}
diff --git a/redo/uitask_darwin.go b/redo/uitask_darwin.go
index 45fa8d1..eda0f29 100644
--- a/redo/uitask_darwin.go
+++ b/redo/uitask_darwin.go
@@ -25,12 +25,11 @@ func uistop() {
C.uistop()
}
-func issue(req *Request) {
- C.issue(unsafe.Pointer(req))
+func issue(f func()) {
+ C.issue(unsafe.Pointer(&f))
}
//export doissue
-func doissue(r unsafe.Pointer) {
- req := (*Request)(unsafe.Pointer(r))
- perform(req)
+func doissue(fp unsafe.Pointer) {
+ perform(fp)
}
diff --git a/redo/uitask_unix.go b/redo/uitask_unix.go
index 0b8fe4a..b1a556e 100644
--- a/redo/uitask_unix.go
+++ b/redo/uitask_unix.go
@@ -27,13 +27,12 @@ func uistop() {
C.gtk_main_quit()
}
-func issue(req *Request) {
- C.gdk_threads_add_idle(C.GSourceFunc(C.doissue), C.gpointer(unsafe.Pointer(req)))
+func issue(f func()) {
+ C.gdk_threads_add_idle(C.GSourceFunc(C.doissue), C.gpointer(unsafe.Pointer(&f)))
}
//export doissue
func doissue(data C.gpointer) C.gboolean {
- req := (*Request)(unsafe.Pointer(data))
- perform(req)
+ perform(unsafe.Pointer(data))
return C.FALSE // don't repeat
}
diff --git a/redo/uitask_windows.c b/redo/uitask_windows.c
index 291ef3b..e9f7e8a 100644
--- a/redo/uitask_windows.c
+++ b/redo/uitask_windows.c
@@ -38,7 +38,7 @@ static LRESULT CALLBACK msgwinproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
case WM_COMMAND:
return forwardCommand(hwnd, uMsg, wParam, lParam);
case msgRequest:
- xperform((void *) lParam);
+ doissue((void *) lParam);
return 0;
default:
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
diff --git a/redo/uitask_windows.go b/redo/uitask_windows.go
index 3cb5012..38f6bfe 100644
--- a/redo/uitask_windows.go
+++ b/redo/uitask_windows.go
@@ -41,8 +41,8 @@ func uistop() {
C.PostQuitMessage(0)
}
-func issue(req *Request) {
- C.issue(unsafe.Pointer(req))
+func issue(f func()) {
+ C.issue(unsafe.Pointer(&f))
}
func makemsgwin() error {
@@ -55,8 +55,7 @@ func makemsgwin() error {
return nil
}
-//export xperform
-func xperform(xreq unsafe.Pointer) {
- req := (*Request)(xreq)
- perform(req)
+//export doissue
+func doissue(fp unsafe.Pointer) {
+ perform(fp)
}