For example, map access like this:
func (pool *fPool) fetch(url string) *ResultPromise {
pool.cacheLock.RLock()
if rp, pres := pool.cache[url]; pres {
pool.cacheLock.RUnlock()
return rp
}
pool.cacheLock.RUnlock()
pool.cacheLock.Lock()
if rp, pres := pool.cache[url]; pres {
pool.cacheLock.Unlock()
// Skip adding url if someone snuck it in between RUnlock an Lock
return rp
}
rp := newPromise()
pool.cache[url] = rp
pool.cacheLock.Unlock()
pool.c <- fetchWork{rp, url}
return rp
}
Here, the contents of the second if
condition are not covered. However, by placing breakpoints it's trivial to end up in that block.
The example isn't contrived, because:
- If we skip the
RLock
, the map will be unnecessarily locked when the workload is mostly reads. - If we skip the second
if
,the most expensive work (handled bypool.c <- fetchWork{rp, url}
in this case) can happen more than once for the same key, which is unacceptable.
Aucun commentaire:
Enregistrer un commentaire