Last active
June 15, 2022 03:04
-
-
Save cswiercz/4ccf72e5d5dd4bf93173193180c87506 to your computer and use it in GitHub Desktop.
Herb Sutter's favorite sub-10 line C++ snippet: Factory w/Cache
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Cached Factory | |
Sometimes you want to make objects with a lifetime managed | |
by their target owner but you also want to hold reference | |
to them in a custom cache. The target owner, naturally, will | |
be given a shared_ptr to the output object. However, we don't | |
want the lifetime of the output object to be tied to the | |
internal cache. I.e. if the owner dies then the object should | |
die even if referenced in the cache. | |
The solution is to have the cache contain weak_ptr's to the | |
created objects. These weak_ptrs are appropriately converted | |
to shared_ptrs, with correct ownership properties, when | |
obtained from the cache. | |
Furthermore, we want this cache to be thread-safe: multiple | |
threads should only be allowed to access a given element | |
of the cache one at a time. (However, multiple threads can | |
certainly access other cached objects.) | |
*/ | |
shared_ptr<Widget> make_widget(int id) { | |
static map<int, weak_ptr<width>> cache; // "static" is important here: one mutex and | |
static mutex mut_cache; // cache for all threads | |
lock_guard<mutex> hold(mut_cache); // RAII-style locking for the rest of the routine | |
auto sp = cache[id].lock(); // returns a shared_ptr with "appropriate" ownership props | |
if (!sp) // (see weak_ptr.lock() documentation) | |
cache[id] = sp = load_widget(id); // create the widget if it doesn't exist (as a | |
// shared_ptr to the heap-allocated resource) | |
return sp | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is a missing semicolon after
return
. Otherwise great job! One of my favourite C++ snippets aswell.