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