LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ssh | 5 package ssh |
6 | 6 |
7 import ( | 7 import ( |
8 "io" | 8 "io" |
9 "sync" | 9 "sync" |
10 ) | 10 ) |
(...skipping 25 matching lines...) Expand all Loading... |
36 head: e, | 36 head: e, |
37 tail: e, | 37 tail: e, |
38 } | 38 } |
39 return b | 39 return b |
40 } | 40 } |
41 | 41 |
42 // write makes buf available for Read to receive. | 42 // write makes buf available for Read to receive. |
43 // buf must not be modified after the call to write. | 43 // buf must not be modified after the call to write. |
44 func (b *buffer) write(buf []byte) { | 44 func (b *buffer) write(buf []byte) { |
45 b.Cond.L.Lock() | 45 b.Cond.L.Lock() |
46 defer b.Cond.L.Unlock() | |
47 e := &element{buf: buf} | 46 e := &element{buf: buf} |
48 b.tail.next = e | 47 b.tail.next = e |
49 b.tail = e | 48 b.tail = e |
50 b.Cond.Signal() | 49 b.Cond.Signal() |
| 50 b.Cond.L.Unlock() |
51 } | 51 } |
52 | 52 |
53 // eof closes the buffer. Reads from the buffer once all | 53 // eof closes the buffer. Reads from the buffer once all |
54 // the data has been consumed will receive os.EOF. | 54 // the data has been consumed will receive os.EOF. |
55 func (b *buffer) eof() error { | 55 func (b *buffer) eof() error { |
56 b.Cond.L.Lock() | 56 b.Cond.L.Lock() |
57 defer b.Cond.L.Unlock() | |
58 b.closed = true | 57 b.closed = true |
59 b.Cond.Signal() | 58 b.Cond.Signal() |
| 59 b.Cond.L.Unlock() |
60 return nil | 60 return nil |
61 } | 61 } |
62 | 62 |
63 // Read reads data from the internal buffer in buf. | 63 // Read reads data from the internal buffer in buf. Reads will block |
64 // Reads will block if no data is available, or until | 64 // if no data is available, or until the buffer is closed. |
65 // the buffer is closed. | |
66 func (b *buffer) Read(buf []byte) (n int, err error) { | 65 func (b *buffer) Read(buf []byte) (n int, err error) { |
67 b.Cond.L.Lock() | 66 b.Cond.L.Lock() |
68 defer b.Cond.L.Unlock() | 67 defer b.Cond.L.Unlock() |
| 68 |
69 for len(buf) > 0 { | 69 for len(buf) > 0 { |
70 // if there is data in b.head, copy it | 70 // if there is data in b.head, copy it |
71 if len(b.head.buf) > 0 { | 71 if len(b.head.buf) > 0 { |
72 r := copy(buf, b.head.buf) | 72 r := copy(buf, b.head.buf) |
73 buf, b.head.buf = buf[r:], b.head.buf[r:] | 73 buf, b.head.buf = buf[r:], b.head.buf[r:] |
74 n += r | 74 n += r |
75 continue | 75 continue |
76 } | 76 } |
77 // if there is a next buffer, make it the head | 77 // if there is a next buffer, make it the head |
78 if len(b.head.buf) == 0 && b.head != b.tail { | 78 if len(b.head.buf) == 0 && b.head != b.tail { |
79 b.head = b.head.next | 79 b.head = b.head.next |
80 continue | 80 continue |
81 } | 81 } |
| 82 |
82 // if at least one byte has been copied, return | 83 // if at least one byte has been copied, return |
83 if n > 0 { | 84 if n > 0 { |
84 break | 85 break |
85 } | 86 } |
| 87 |
86 // if nothing was read, and there is nothing outstanding | 88 // if nothing was read, and there is nothing outstanding |
87 // check to see if the buffer is closed. | 89 // check to see if the buffer is closed. |
88 if b.closed { | 90 if b.closed { |
89 err = io.EOF | 91 err = io.EOF |
90 break | 92 break |
91 } | 93 } |
92 // out of buffers, wait for producer | 94 // out of buffers, wait for producer |
93 b.Cond.Wait() | 95 b.Cond.Wait() |
94 } | 96 } |
95 return | 97 return |
96 } | 98 } |
LEFT | RIGHT |