Skip to content

Instantly share code, notes, and snippets.

@alepez
Created June 5, 2018 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alepez/0cd9e8d9a17ee4ac26c30b0464813eb8 to your computer and use it in GitHub Desktop.
Save alepez/0cd9e8d9a17ee4ac26c30b0464813eb8 to your computer and use it in GitHub Desktop.
weak-ptr-global (global is bad practice, but at least this is automatically released)
#include <cassert>
#include <iostream>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
template <typename T>
std::shared_ptr<T> get_global(int id) {
using Map = std::unordered_map<int, std::weak_ptr<T>>;
static std::mutex mutex;
static Map instances;
std::lock_guard<std::mutex> lock(mutex);
/* Find if already created */
if (instances.count(id)) {
auto sptr = instances[id].lock();
/* Is it still valid? */
if (sptr) return sptr;
}
/* Never created or not valid, create a shared ptr */
auto sptr = std::make_shared<T>();
/* Keep only the weak ptr */
instances[id] = sptr;
/* Return the shared ptr, so lifetime is managed by caller */
return sptr;
}
void check(int id, const std::string& expected) {
auto r = get_global<std::string>(id);
assert(*r == expected);
}
void print(int id) {
auto inst = *get_global<std::string>(id);
std::cout << inst << std::endl;
}
int main() {
{
auto s = get_global<std::string>(0);
*s = "test";
check(0, "test");
print(0);
/* ss is bound to id 0 */
auto ss = get_global<std::string>(0);
*ss = "foo";
check(0, "foo");
print(0);
/* t has a different id, so it is a different resource */
auto t = get_global<std::string>(1);
*t = "ciao";
check(1, "ciao");
print(1);
check(0, "foo");
print(0);
}
/* s is out of scope, its resource is released */
{
/* q is bound to id 0, but it is a new resource, because previous has been
* released */
auto q = get_global<std::string>(0);
check(0, "");
print(0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment