Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix idle wakeup problem (second attempt) #157

Closed
wants to merge 3 commits into from

Conversation

zyedidia
Copy link
Contributor

@zyedidia zyedidia commented Jun 16, 2017

I found this package: https://github.com/npat-efault/poller which seems to use poll in some way to fix the issue on MacOS that we were having with the Close and Read.

For example, this code works as expected:

package main

import (
    "fmt"
    "os"
    "time"

    "github.com/npat-efault/poller"
)

func main() {
    f, e := poller.Open("/dev/tty", poller.O_RW)
    if e != nil {
        fmt.Println("Cannot open /dev/tty:", e)
        os.Exit(1)
    }

    go func() {
        time.Sleep(time.Second * 4)
        fmt.Println("Closing...")
        f.Close()
        fmt.Println("Close finished")
    }()

    data := make([]byte, 128)

    for {
        n, e := f.Read(data)
        if e != nil {
            fmt.Println("Error: ", e)
            return
        }
        fmt.Println("Got", n, "bytes")
    }
}

The original library used some cgo on all systems other than Linux, so I have made a fork and removed the need for cgo (fork at https://github.com/zyedidia/poller).

Since it appears that this problem only occurs on Mac, the implementations for Linux, bsd... do not use this library (perhaps bsd is buggy? I have only been able to test on MacOS and Linux -- edit: I tested on FreeBSD and it did not exhibit the bug that MacOS does). The poller is only used on Mac so now darwin should get its own tscreen file.

I have also set VTIME=0 and VMIN=1 so that tcell doesn't wake up unless there is data to read.

I removed the whole indoneq channel because it was just blocking (I think it was used for syncing the wakeup with the close?) and didn't seem to be of any use.

I also encountered a problem with the Alt keys after this change -- they were only responding on the next keypress. But if expire was always true then it worked well, so I effectively always made expire true by removing that if statement.

Let me know if you see any problems. I think this is a pretty good solution because it allows restarting the library during the program. Tcell in general is also a little snappier as a result (there is no 1/10th second delay when quitting or when use Alt keys).

Ref #129

This commit uses the poller package (github.com/zyedidia/poller which is
a slighty modified version of github.com/npat-efault/poller -- the cgo
code has been removed) so that the Read properly terminates when Close
is called.
@gdamore
Copy link
Owner

gdamore commented Jun 16, 2017 via email

Now that read blocks indefinitely, we need it to run in a separate
goroutine so that if a sigwinch event is received, we can process it.
@zyedidia
Copy link
Contributor Author

zyedidia commented Jun 20, 2017

I noticed there were some problems receiving the window resize events, so I put the input reading in a separate goroutine (since it blocks forever now) so that now there is a select between the quit channel, the sigwinch channel, and the input channel.

This PR also has the benefit that it turns t.in and t.out into io.Reader and io.Writer (#148). I'm not sure how much this solves that issue (it seems like the author of the issue was trying to do even more than this would allow), but this change would allow for an optimization in drawing (see zyedidia@8ae342e). When I tested after that optimization, screen.Show was considerably faster. Here was my benchmark from boxes.go:

Terminal size: 80x25

Before:

Finished 150 boxes in 51.293882ms
Average is 0.342 ms / box

After:

Finished 150 boxes in 23.773993ms
Average is 0.158 ms / box

Terminal size: 318x74

Before:

Finished 150 boxes in 332.561822ms
Average is 2.217 ms / box

After:

Finished 150 boxes in 116.176178ms
Average is 0.775 ms / box

But I'm getting ahead of myself because zyedidia@8ae342e is separate from this PR (although it requires the io.Reader and io.Writer business from this).

@gdamore
Copy link
Owner

gdamore commented Jul 4, 2017

I owe you a review, and either a merge or actionable feedback. Stay tuned.

@gdamore
Copy link
Owner

gdamore commented Jul 4, 2017

I'm a little less than optimal (2 glasses of wine, at the end of the evening) but I promise to review when fully sober at peak efficiency within 24 hours. Thanks.

@zyedidia
Copy link
Contributor Author

zyedidia commented Aug 6, 2017

FYI I don't think you should merge this yet. There are still some issues that I found but haven't fixed.

This commit also improves the performance of draw() by buffering the
output and sending it all to the terminal at the end of the draw().
@codecov
Copy link

codecov bot commented Sep 6, 2017

Codecov Report

❗ No coverage uploaded for pull request base (master@62d7350). Click here to learn what that means.
The diff coverage is 0%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #157   +/-   ##
=========================================
  Coverage          ?   75.97%           
=========================================
  Files             ?       19           
  Lines             ?     5358           
  Branches          ?        0           
=========================================
  Hits              ?     4071           
  Misses            ?     1257           
  Partials          ?       30
Impacted Files Coverage Δ
tscreen.go 0% <0%> (ø)
tscreen_linux.go 0% <0%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 62d7350...0082ef2. Read the comment docs.

@zyedidia
Copy link
Contributor Author

zyedidia commented Sep 6, 2017

Oops did I do something bad?

@gdamore
Copy link
Owner

gdamore commented Sep 24, 2017

I've taken a totally different approach, as part of fixing #164 Please have a look at the inputrefactor branch. Turns out this was simpler by just separating the read into its own loop, and adding another "mainloop" goroutine. Most likely I will close this in favor of that branch.

@zyedidia zyedidia closed this Sep 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants