]> Cypherpunks repositories - gostls13.git/commitdiff
Cache *os.Error values across all users.
authorRob Pike <r@golang.org>
Thu, 8 Jan 2009 00:37:43 +0000 (16:37 -0800)
committerRob Pike <r@golang.org>
Thu, 8 Jan 2009 00:37:43 +0000 (16:37 -0800)
R=rsc
DELTA=27  (23 added, 0 deleted, 4 changed)
OCL=22245
CL=22245

src/lib/os/os_error.go

index 4c03454d94a51dc11dde2ed530a10c10cc3fc0b5..c8d52dc4eee271c6272f16031f035937ef0d23dd 100644 (file)
@@ -12,24 +12,47 @@ export type Error struct {
        s string
 }
 
+// Indexed by errno.
+// If we worry about syscall speed (only relevant on failure), we could
+// make it an array, but it's probably not important.
 var ErrorTab = make(map[int64] *Error);
 
+// Table of all known errors in system.  Use the same error string twice,
+// get the same *os.Error.
+var ErrorStringTab = make(map[string] *Error);
+
+// These functions contain a race if two goroutines add identical
+// errors simultaneously but the consequences are unimportant.
+
+// Allocate an Error objecct, but if it's been seen before, share that one.
 export func NewError(s string) *Error {
-       return &Error{s}
+       if s == "" {
+               return nil
+       }
+       err, ok := ErrorStringTab[s];
+       if ok {
+               return err
+       }
+       err = &Error{s};
+       ErrorStringTab[s] = err;
+       return err;
 }
 
+// Allocate an Error objecct, but if it's been seen before, share that one.
 export func ErrnoToError(errno int64) *Error {
        if errno == 0 {
                return nil
        }
+       // Quick lookup by errno.
        err, ok := ErrorTab[errno];
        if ok {
                return err
        }
-       e := NewError(syscall.errstr(errno));
-       ErrorTab[errno] = e;
-       return e;
+       err = NewError(syscall.errstr(errno));
+       ErrorTab[errno] = err;
+       return err;
 }
+
 export var (
        ENONE = ErrnoToError(syscall.ENONE);
        EPERM = ErrnoToError(syscall.EPERM);