1 #include "RuntimeLifecycleMonitor.h"
2 
3 #include <unordered_map>
4 #include <unordered_set>
5 #include <utility>
6 
7 namespace RNJsi {
8 
9 static std::unordered_map<jsi::Runtime *,
10                           std::unordered_set<RuntimeLifecycleListener *>>
11     listeners;
12 
13 struct RuntimeLifecycleMonitorObject : public jsi::HostObject {
14   jsi::Runtime *_rt;
RuntimeLifecycleMonitorObjectRNJsi::RuntimeLifecycleMonitorObject15   explicit RuntimeLifecycleMonitorObject(jsi::Runtime *rt) : _rt(rt) {}
~RuntimeLifecycleMonitorObjectRNJsi::RuntimeLifecycleMonitorObject16   ~RuntimeLifecycleMonitorObject() {
17     auto listenersSet = listeners.find(_rt);
18     if (listenersSet != listeners.end()) {
19       for (auto listener : listenersSet->second) {
20         listener->onRuntimeDestroyed(_rt);
21       }
22       listeners.erase(listenersSet);
23     }
24   }
25 };
26 
addListener(jsi::Runtime & rt,RuntimeLifecycleListener * listener)27 void RuntimeLifecycleMonitor::addListener(jsi::Runtime &rt,
28                                           RuntimeLifecycleListener *listener) {
29   auto listenersSet = listeners.find(&rt);
30   if (listenersSet == listeners.end()) {
31     // We install a global host object in the provided runtime, this way we can
32     // use that host object destructor to get notified when the runtime is being
33     // terminated. We use a unique name for the object as it gets saved with the
34     // runtime's global object.
35     rt.global().setProperty(
36         rt, "__rnskia_rt_lifecycle_monitor",
37         jsi::Object::createFromHostObject(
38             rt, std::make_shared<RuntimeLifecycleMonitorObject>(&rt)));
39     std::unordered_set<RuntimeLifecycleListener *> newSet;
40     newSet.insert(listener);
41     listeners.emplace(&rt, std::move(newSet));
42   } else {
43     listenersSet->second.insert(listener);
44   }
45 }
46 
removeListener(jsi::Runtime & rt,RuntimeLifecycleListener * listener)47 void RuntimeLifecycleMonitor::removeListener(
48     jsi::Runtime &rt, RuntimeLifecycleListener *listener) {
49   auto listenersSet = listeners.find(&rt);
50   if (listenersSet == listeners.end()) {
51     // nothing to do here
52   } else {
53     listenersSet->second.erase(listener);
54   }
55 }
56 
57 } // namespace RNJsi
58