-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstat.go
78 lines (67 loc) · 1.95 KB
/
stat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// dcc - dependency-driven C/C++ compiler front end
//
// Copyright © A.Newman 2015.
//
// This source code is released under version 2 of the GNU Public License.
// See the file LICENSE for details.
//
package main
import (
"os"
"sync"
)
var (
// statCache is a cache of os.Stat results.
//
statCache = make(map[string]os.FileInfo)
// statCacheMutex protects statCache
//
statCacheMutex sync.Mutex
)
// Stat wraps os.Stat and caches the results.
//
func Stat(path string) (os.FileInfo, error) {
statCacheMutex.Lock()
info, found := statCache[path]
statCacheMutex.Unlock()
if found {
return info, nil
}
// We don't hold the mutex while calling os.Stat and this
// introduces a race - multiple routines Stat'ing the same
// path can overlap and do the same work - call os.Stat and
// add the resultant info to the cache. Other than doing
// things more than once this doesn't really matter.
//
// Given the nature of the paths being Stat'd the FileInfo
// will be identical. The real effect of the race will be to
// call os.Stat more than once for a given path, updating the
// cache with identical data if it succeeds with the
// associated locking overhead.
//
// The likelihood of this race occurring depends the ordering
// and timing of Stat calls which at first would appear to be
// essentiallly random but it should be noted that generated
// dependencies will often list paths in the same order and
// that the initial compilation jobs will all start at about
// the same time.
//
info, err := os.Stat(path)
if err != nil {
return nil, err
}
statCacheMutex.Lock()
if _, found = statCache[path]; !found {
statCache[path] = info
}
statCacheMutex.Unlock()
return info, nil
}
// ClearCachedStat removes an entry from the cache. This is required after compilation
// to ensure we re-stat the file and get its new modtime.
//
func ClearCachedStat(path string) {
statCacheMutex.Lock()
delete(statCache, path)
statCacheMutex.Unlock()
}