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