]> Cypherpunks repositories - gostls13.git/commitdiff
log: ensure writes are atomic.
authorRoger Peppe <rogpeppe@gmail.com>
Wed, 1 Dec 2010 18:15:42 +0000 (10:15 -0800)
committerRob Pike <r@golang.org>
Wed, 1 Dec 2010 18:15:42 +0000 (10:15 -0800)
This means that any Writer can be used safely
even when Output is called concurrently.
Fixes #1302.

R=r, nigeltao_gnome
CC=golang-dev
https://golang.org/cl/3300042

src/pkg/log/log.go

index ac24b4deaa7099cd67bf6ee2a68939060b0d2321..f7176e8e5ca88fa9cba2605502e98082ed8a82bf 100644 (file)
@@ -19,6 +19,7 @@ import (
        "runtime"
        "os"
        "time"
+       "sync"
 )
 
 // These flags define which text to prefix to each log entry generated by the Logger.
@@ -34,11 +35,15 @@ const (
        Lshortfile                // final file name element and line number: d.go:23. overrides Llongfile
 )
 
-// Logger represents an active logging object.
+// A Logger represents an active logging object that generates lines of
+// output to an io.Writer.  Each logging operation makes a single call to
+// the Writer's Write method.  A Logger can be used simultaneously from
+// multiple goroutines; it guarantees to serialize access to the Writer.
 type Logger struct {
-       out    io.Writer // destination for output
-       prefix string    // prefix to write at beginning of each line
-       flag   int       // properties
+       mu     sync.Mutex // ensures atomic writes
+       out    io.Writer  // destination for output
+       prefix string     // prefix to write at beginning of each line
+       flag   int        // properties
 }
 
 // New creates a new Logger.   The out variable sets the
@@ -46,7 +51,7 @@ type Logger struct {
 // The prefix appears at the beginning of each generated log line.
 // The flag argument defines the logging properties.
 func New(out io.Writer, prefix string, flag int) *Logger {
-       return &Logger{out, prefix, flag}
+       return &Logger{out: out, prefix: prefix, flag: flag}
 }
 
 var std = New(os.Stderr, "", Ldate|Ltime)
@@ -139,6 +144,8 @@ func (l *Logger) Output(calldepth int, s string) os.Error {
        if len(s) > 0 && s[len(s)-1] != '\n' {
                buf.WriteByte('\n')
        }
+       l.mu.Lock()
+       defer l.mu.Unlock()
        _, err := l.out.Write(buf.Bytes())
        return err
 }