1*4440fb50SKudo Chien #pragma once
2*4440fb50SKudo Chien
3*4440fb50SKudo Chien #ifdef DEBUG
4*4440fb50SKudo Chien
5*4440fb50SKudo Chien #include <cxxabi.h>
6*4440fb50SKudo Chien
7*4440fb50SKudo Chien #include <iostream>
8*4440fb50SKudo Chien #include <string>
9*4440fb50SKudo Chien
10*4440fb50SKudo Chien #ifdef ANDROID
11*4440fb50SKudo Chien #include <android/log.h>
12*4440fb50SKudo Chien #endif
13*4440fb50SKudo Chien
14*4440fb50SKudo Chien namespace reanimated {
15*4440fb50SKudo Chien
16*4440fb50SKudo Chien // This is a class that counts how many instances of a different class there
17*4440fb50SKudo Chien // are. It is meant only to be used with classes that should only have one
18*4440fb50SKudo Chien // instance.
19*4440fb50SKudo Chien
20*4440fb50SKudo Chien template <class T>
21*4440fb50SKudo Chien class SingleInstanceChecker {
22*4440fb50SKudo Chien public:
23*4440fb50SKudo Chien SingleInstanceChecker();
24*4440fb50SKudo Chien ~SingleInstanceChecker();
25*4440fb50SKudo Chien
26*4440fb50SKudo Chien private:
assertWithMessage(bool condition,std::string message)27*4440fb50SKudo Chien void assertWithMessage(bool condition, std::string message) {
28*4440fb50SKudo Chien if (!condition) {
29*4440fb50SKudo Chien #ifdef ANDROID
30*4440fb50SKudo Chien __android_log_print(
31*4440fb50SKudo Chien ANDROID_LOG_WARN, "Reanimated", "%s", message.c_str());
32*4440fb50SKudo Chien #else
33*4440fb50SKudo Chien std::cerr << "[Reanimated] " << message << std::endl;
34*4440fb50SKudo Chien #endif
35*4440fb50SKudo Chien
36*4440fb50SKudo Chien #ifdef IS_REANIMATED_EXAMPLE_APP
37*4440fb50SKudo Chien assert(false);
38*4440fb50SKudo Chien #endif
39*4440fb50SKudo Chien }
40*4440fb50SKudo Chien }
41*4440fb50SKudo Chien
42*4440fb50SKudo Chien // A static field will exist separately for every class template.
43*4440fb50SKudo Chien // This has to be inline for automatic initialization.
44*4440fb50SKudo Chien inline static volatile int instanceCount_;
45*4440fb50SKudo Chien };
46*4440fb50SKudo Chien
47*4440fb50SKudo Chien template <class T>
SingleInstanceChecker()48*4440fb50SKudo Chien SingleInstanceChecker<T>::SingleInstanceChecker() {
49*4440fb50SKudo Chien int status = 0;
50*4440fb50SKudo Chien std::string className =
51*4440fb50SKudo Chien __cxxabiv1::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
52*4440fb50SKudo Chien
53*4440fb50SKudo Chien // Only one instance should exist, but it is possible for two instances
54*4440fb50SKudo Chien // to co-exist during a reload.
55*4440fb50SKudo Chien assertWithMessage(
56*4440fb50SKudo Chien instanceCount_ <= 1,
57*4440fb50SKudo Chien "More than one instance of " + className +
58*4440fb50SKudo Chien " present. This may indicate a memory leak due to a retain cycle.");
59*4440fb50SKudo Chien
60*4440fb50SKudo Chien instanceCount_++;
61*4440fb50SKudo Chien }
62*4440fb50SKudo Chien
63*4440fb50SKudo Chien template <class T>
~SingleInstanceChecker()64*4440fb50SKudo Chien SingleInstanceChecker<T>::~SingleInstanceChecker() {
65*4440fb50SKudo Chien instanceCount_--;
66*4440fb50SKudo Chien }
67*4440fb50SKudo Chien
68*4440fb50SKudo Chien } // namespace reanimated
69*4440fb50SKudo Chien
70*4440fb50SKudo Chien #endif // DEBUG
71