Last active
January 11, 2016 19:53
-
-
Save Porges/f4442bc7911f29dcdd89 to your computer and use it in GitHub Desktop.
This file contains 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
#include "stdafx.h" | |
#include <atomic> | |
#include <iostream> | |
#include <mutex> | |
#include <typeindex> | |
#include <typeinfo> | |
#include <unordered_map> | |
// here is the global mapping of type -> counts: | |
std::mutex counts_mutex; // protects 'counts': | |
std::unordered_map<std::type_index, std::atomic<std::uint64_t>*> counts; | |
// threadsafe way to get the mapping: | |
std::unordered_map<std::type_index, std::atomic<std::uint64_t>*> get_counts() | |
{ | |
std::lock_guard<std::mutex> lock{ counts_mutex }; | |
return counts; | |
} | |
template<class T> | |
class counted | |
{ | |
// per-class count: | |
static std::atomic<std::uint64_t> count_; | |
const static std::uint64_t warn_threshold = 10000; | |
// adds the per-class count to the global mapping: | |
struct count_initializer | |
{ | |
count_initializer() | |
{ | |
std::lock_guard<std::mutex> lock{ counts_mutex }; | |
counts[typeid(T)] = &count_; | |
} | |
}; | |
protected: | |
counted() noexcept | |
{ | |
// initialization happens threadsafely here: | |
static count_initializer init; | |
if (++count_ > warn_threshold) | |
{ | |
std::cout << "BEEP BEEP BEEP" << std::endl; | |
} | |
} | |
~counted() | |
{ | |
--count_; | |
} | |
}; | |
// example: | |
class Base : counted<Base> | |
{ | |
}; | |
std::atomic<std::uint64_t> counted<Base>::count_{ 0 }; | |
class Foo : counted<Foo>, Base | |
{ | |
}; | |
std::atomic<std::uint64_t> counted<Foo>::count_{ 0 }; | |
class Bar : counted<Bar>, Base | |
{ | |
}; | |
std::atomic<std::uint64_t> counted<Bar>::count_{ 0 }; | |
void print_counts() | |
{ | |
std::cout << "Counts" << std::endl << "------" << std::endl; | |
auto counts = get_counts(); | |
for (const auto& count : counts) | |
{ | |
std::cout << count.first.name() << ": " << count.second->load() << std::endl; | |
} | |
std::cout << std::endl; | |
} | |
int main() | |
{ | |
print_counts(); | |
Foo foo; | |
Bar bar; | |
{ | |
Bar bar2; | |
print_counts(); | |
} | |
print_counts(); | |
// Output is: | |
////Counts | |
////------ | |
////Counts | |
////------ | |
////class Foo : 1 | |
////class Bar : 2 | |
////Counts | |
////------ | |
////class Foo : 1 | |
////class Bar : 1 | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment