diff --git a/oviewer/control_test.go b/oviewer/control_test.go index 04edade..1d87d92 100644 --- a/oviewer/control_test.go +++ b/oviewer/control_test.go @@ -161,9 +161,7 @@ func TestDocument_requestLoad(t *testing.T) { if err := m.ControlFile(f); err != nil { t.Fatalf("Document.ControlFile() fatal = %v, wantErr %v", err, tt.wantErr) } - for !m.BufEOF() { - } - + m.WaitEOF() m.requestLoad(tt.fields.chunkNum) sc := controlSpecifier{ @@ -235,8 +233,7 @@ func TestDocument_requestSearch(t *testing.T) { if err := m.ControlFile(f); (err != nil) != tt.wantErr { t.Errorf("Document.ControlFile() error = %v, wantErr %v", err, tt.wantErr) } - for !m.BufEOF() { - } + m.WaitEOF() if got := m.requestSearch(tt.fields.chunkNum, searcher); got != tt.want { t.Errorf("Document.requestSearch() = %v, want %v", got, tt.want) } @@ -304,10 +301,7 @@ func TestDocument_requestFollow(t *testing.T) { if err := m.ControlFile(f); err != nil { t.Fatalf("Document.ControlFile() fatal = %v, wantErr %v", err, tt.wantErr) } - - for !m.BufEOF() { - } - + m.WaitEOF() af, err := os.OpenFile(fname, os.O_APPEND|os.O_RDWR, 0o600) if err != nil { t.Fatal("open error", tt.fields.FileName) @@ -371,8 +365,7 @@ func TestDocument_requestClose(t *testing.T) { if err := m.ControlFile(f); (err != nil) != tt.wantErr { t.Errorf("Document.ControlFile() error = %v, wantErr %v", err, tt.wantErr) } - for !m.BufEOF() { - } + m.WaitEOF() if got := m.requestClose(); got != tt.want { t.Errorf("Document.requestSearch() = %v, want %v", got, tt.want) } diff --git a/oviewer/document.go b/oviewer/document.go index e13640c..be29f6c 100644 --- a/oviewer/document.go +++ b/oviewer/document.go @@ -59,6 +59,8 @@ type Document struct { // alignConv is an interface that converts alignment. alignConv *align + cond *sync.Cond + // fileName is the file name to display. FileName string // Caption is an additional caption to display after the file name. @@ -232,6 +234,8 @@ func NewDocument() (*Document, error) { } m.alignConv = newAlignConverter(m.ColumnWidth) m.conv = m.converterType(m.general.Converter) + + m.cond = sync.NewCond(&sync.Mutex{}) return m, nil } @@ -428,6 +432,16 @@ func (m *Document) storeEndNum() int { return int(atomic.LoadInt32(&m.store.endNum)) } +// WaitEOF waits for EOF. +func (m *Document) WaitEOF() { + m.cond.L.Lock() + defer m.cond.L.Unlock() + if m.BufEOF() { + return + } + m.cond.Wait() +} + // BufEOF return true if EOF is reached. func (m *Document) BufEOF() bool { return atomic.LoadInt32(&m.store.eof) == 1 diff --git a/oviewer/document_test.go b/oviewer/document_test.go index a606c59..5cef3fb 100644 --- a/oviewer/document_test.go +++ b/oviewer/document_test.go @@ -17,8 +17,7 @@ func docHelper(t *testing.T, str string) *Document { if err := m.ControlReader(bytes.NewBufferString(str), nil); err != nil { t.Fatal(err) } - for !m.BufEOF() { - } + m.WaitEOF() return m } @@ -28,9 +27,7 @@ func docFileReadHelper(t *testing.T, fileName string) *Document { if err != nil { t.Fatal(err) } - for !m.BufEOF() { - } - + m.WaitEOF() return m } @@ -162,8 +159,6 @@ func TestDocument_Export(t *testing.T) { t.Parallel() m := docHelper(t, tt.str) w := &bytes.Buffer{} - for !m.BufEOF() { - } m.bottomLN = m.BufEndNum() if err := m.Export(w, tt.args.start, tt.args.end); err != nil { t.Fatal(err) diff --git a/oviewer/filter_test.go b/oviewer/filter_test.go index b73f868..8f724c1 100644 --- a/oviewer/filter_test.go +++ b/oviewer/filter_test.go @@ -174,8 +174,9 @@ func TestRoot_filterDocument(t *testing.T) { root.Doc.Header = tt.fields.header root.filterDocument(context.Background(), tt.args.searcher) filterDoc := root.DocList[len(root.DocList)-1] - for !filterDoc.BufEOF() { - } + filterDoc.cond.L.Lock() + filterDoc.cond.Wait() + filterDoc.cond.L.Unlock() line := filterDoc.getLineC(0) if line.str != tt.want { t.Errorf("filterDocument() = %v, want %v", line.str, tt.want) @@ -242,8 +243,7 @@ func TestRoot_filterLink(t *testing.T) { ctx := context.Background() root.filterDocument(ctx, tt.args.searcher) filterDoc := root.DocList[len(root.DocList)-1] - for !filterDoc.BufEOF() { - } + filterDoc.WaitEOF() filterDoc.LineNumMode = true root.prepareStartX() filterDoc.topLN = 2 @@ -299,8 +299,7 @@ func TestRoot_closeAllFilter(t *testing.T) { root := rootFileReadHelper(t, tt.fields.fileNames...) root.filterDocument(context.Background(), tt.args.searcher) filterDoc := root.DocList[len(root.DocList)-1] - for !filterDoc.BufEOF() { - } + filterDoc.WaitEOF() ctx := context.Background() root.closeAllFilter(ctx) if len(root.DocList) != tt.want { diff --git a/oviewer/oviewer_test.go b/oviewer/oviewer_test.go index b447f22..f25df3c 100644 --- a/oviewer/oviewer_test.go +++ b/oviewer/oviewer_test.go @@ -43,8 +43,7 @@ func rootFileReadHelper(t *testing.T, fileNames ...string) *Root { } root.mu.RLock() for _, doc := range root.DocList { - for !doc.BufEOF() { - } + doc.WaitEOF() } root.mu.RUnlock() return root diff --git a/oviewer/reader.go b/oviewer/reader.go index ace4646..3c54866 100644 --- a/oviewer/reader.go +++ b/oviewer/reader.go @@ -268,6 +268,9 @@ func (m *Document) afterEOF(reader *bufio.Reader) *bufio.Reader { atomic.StoreInt32(&m.tmpLN, atomic.LoadInt32(&m.followStore.endNum)) m.cache.Purge() } + m.cond.L.Lock() + m.cond.Broadcast() + m.cond.L.Unlock() if !m.seekable { // for NamedPipe. return bufio.NewReader(m.file) }