Reduce memory allocation and remove channels

Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
This commit is contained in:
Sachin Joshi 2015-03-19 18:07:56 -07:00
parent 7fc3c0ba26
commit 9cc42dea7c

View file

@ -83,6 +83,7 @@ const (
ANSI_MAX_CMD_LENGTH = 256
MAX_INPUT_EVENTS = 128
MAX_INPUT_BUFFER = 1024
DEFAULT_WIDTH = 80
DEFAULT_HEIGHT = 24
@ -195,15 +196,18 @@ type (
type WindowsTerminal struct {
outMutex sync.Mutex
inMutex sync.Mutex
inputBuffer chan byte
inputBuffer []byte
inputSize int
inputEvents []INPUT_RECORD
screenBufferInfo *CONSOLE_SCREEN_BUFFER_INFO
inputEscapeSequence []byte
}
func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
handler := &WindowsTerminal{
inputBuffer: make(chan byte, MAX_INPUT_BUFFER),
inputBuffer: make([]byte, MAX_INPUT_BUFFER),
inputEscapeSequence: []byte(KEY_ESC_CSI),
inputEvents: make([]INPUT_RECORD, MAX_INPUT_EVENTS),
}
// Save current screen buffer info
@ -218,6 +222,8 @@ func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
// Set the window size
SetWindowSize(uintptr(handle), DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_HEIGHT)
buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y)
if IsTerminal(os.Stdout.Fd()) {
stdOut = &terminalWriter{
wrappedWriter: os.Stdout,
@ -427,6 +433,8 @@ func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
return 0
}
var buffer []CHAR_INFO
func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (bool, uint32, error) {
var writeRegion SMALL_RECT
writeRegion.Top = fromCoord.Y
@ -439,14 +447,13 @@ func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoor
height := toCoord.Y - fromCoord.Y + 1
size := width * height
if size > 0 {
buffer := make([]CHAR_INFO, size)
for i := 0; i < len(buffer); i++ {
for i := 0; i < int(size); i++ {
buffer[i].UnicodeChar = WCHAR(fillChar)
buffer[i].Attributes = attributes
}
// Write to buffer
r, err := writeConsoleOutput(fileDesc, buffer, windowSize, COORD{X: 0, Y: 0}, &writeRegion)
r, err := writeConsoleOutput(fileDesc, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
if !r {
if err != nil {
return false, 0, err
@ -914,6 +921,9 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n
// WriteChars writes the bytes to given writer.
func (term *WindowsTerminal) WriteChars(fd uintptr, w io.Writer, p []byte) (n int, err error) {
if len(p) == 0 {
return 0, nil
}
return w.Write(p)
}
@ -1049,24 +1059,19 @@ func mapKeystokeToTerminalString(keyEvent *KEY_EVENT_RECORD, escapeSequence []by
// getAvailableInputEvents polls the console for availble events
// The function does not return until at least one input record has been read.
func getAvailableInputEvents(fd uintptr) (inputEvents []INPUT_RECORD, err error) {
func getAvailableInputEvents(fd uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
handle := syscall.Handle(fd)
if nil != err {
return nil, err
return 0, err
}
for {
// Read number of console events available
tempBuffer := make([]INPUT_RECORD, MAX_INPUT_BUFFER)
nr, err := readConsoleInputKey(uintptr(handle), tempBuffer)
nr, err := readConsoleInputKey(uintptr(handle), inputEvents)
if nr == 0 {
return nil, err
return 0, err
}
if 0 < nr {
retValue := make([]INPUT_RECORD, nr)
for i := 0; i < nr; i++ {
retValue[i] = tempBuffer[i]
}
return retValue, nil
return nr, nil
}
}
}
@ -1086,32 +1091,19 @@ func getTranslatedKeyCodes(inputEvents []INPUT_RECORD, escapeSequence []byte) st
}
// ReadChars reads the characters from the given reader
func (term *WindowsTerminal) ReadChars(fd uintptr, w io.Reader, p []byte) (n int, err error) {
n = 0
for n < len(p) {
select {
case b := <-term.inputBuffer:
p[n] = b
n++
default:
// Read at least one byte read
if n > 0 {
return n, nil
}
inputEvents, _ := getAvailableInputEvents(fd)
if inputEvents != nil {
if len(inputEvents) == 0 && nil != err {
return n, err
}
if len(inputEvents) != 0 {
keyCodes := getTranslatedKeyCodes(inputEvents, term.inputEscapeSequence)
for _, b := range []byte(keyCodes) {
term.inputBuffer <- b
}
}
}
func (term *WindowsTerminal) ReadChars(fd uintptr, r io.Reader, p []byte) (n int, err error) {
for term.inputSize == 0 {
nr, err := getAvailableInputEvents(fd, term.inputEvents)
if nr == 0 && nil != err {
return n, err
}
if nr > 0 {
keyCodes := getTranslatedKeyCodes(term.inputEvents[:nr], term.inputEscapeSequence)
term.inputSize = copy(term.inputBuffer, keyCodes)
}
}
n = copy(p, term.inputBuffer[:term.inputSize])
term.inputSize -= n
return n, nil
}