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