Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- with cache_lock.reader_lock:
- x = cache_fetch_under_rlock(params)
- if x is not None:
- return x
- # cache miss; must populate
- with cache_lock.writer_lock:
- x = cache_fetch_under_rlock(params)
- if x is not None:
- # oops, we didn't need to write, oh well
- return x
- x = do_the_expensive_thing(params)
- cache_write_under_wlock(params, x)
- return x
- # do_the_expensive_thing may repeat this pattern with a different lock,
- # if it has its own cache or pipelined single source of truth. This
- # is a nestable, generic pattern for maximizing cache throughput
- # while provably not duplicating the expensive thing. It has the
- # disadvantage of holding the cache lock for the entire Expensive Thing
- # but this is often appropriate; if it is worse to unnecessarily hold
- # the writer lock than it is to duplicate work, however...
- with cache_lock.reader_lock:
- x = cache_fetch_under_rlock(params)
- if x is not None:
- return x
- z = do_the_expensive_thing(params)
- with cache_lock.writer_lock:
- x = cache_fetch_under_rlock(params)
- if x is not None:
- # oops
- return x # it is more GC-memory-efficient to throw z away;
- # under garbage collection, prefer old objects
- cache_write_under_wlock(params, z)
- return z
Advertisement
Add Comment
Please, Sign In to add comment