1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2
3 #pragma once
4
5 #include <fbjni/fbjni.h>
6
7 #include <memory>
8 #include <unordered_map>
9
10 namespace jni = facebook::jni;
11
12 namespace expo {
13
14 template <typename T>
hash_combine(std::size_t & seed,const T & v)15 inline void hash_combine(std::size_t& seed, const T& v)
16 {
17 std::hash<T> hasher;
18 // Reference from: https://github.com/boostorg/container_hash/blob/boost-1.76.0/include/boost/container_hash/hash.hpp
19 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
20 }
21
22 struct pairhash {
23 template <typename A, typename B>
operatorpairhash24 std::size_t operator()(const std::pair<A, B>& v) const {
25 std::size_t seed = 0;
26 hash_combine(seed, v.first);
27 hash_combine(seed, v.second);
28 return seed;
29 }
30 };
31
32 using MethodHashMap = std::unordered_map<std::pair<std::string, std::string>, jmethodID, pairhash>;
33
34 /**
35 * Singleton registry used to store references to often used Java classes.
36 */
37 class JavaReferencesCache {
38 public:
39 /**
40 * An entry in the Java class registry.
41 */
42 class CachedJClass {
43 public:
44 CachedJClass(jclass clazz, MethodHashMap methods);
45
46 /**
47 * A bare reference to the class object.
48 */
49 jclass clazz;
50
51 /**
52 * Returns a cached method id for provided method name and signature.
53 */
54 jmethodID getMethod(const std::string &name, const std::string &signature);
55
56 private:
57 MethodHashMap methods;
58 };
59
60 JavaReferencesCache(JavaReferencesCache const &) = delete;
61
62 JavaReferencesCache &operator=(JavaReferencesCache const &) = delete;
63
64 /**
65 * Gets a singleton instance
66 */
67 static std::shared_ptr<JavaReferencesCache> instance();
68
69 /**
70 * Gets a cached Java class entry.
71 */
72 CachedJClass &getJClass(const std::string &className);
73
74 /**
75 * Gets a cached Java class entry or loads it to the registry.
76 */
77 CachedJClass &getOrLoadJClass(JNIEnv *env, const std::string &className);
78
79 /**
80 * Loads predefined set of Java classes and stores them
81 */
82 void loadJClasses(JNIEnv *env);
83
84 private:
85 JavaReferencesCache() = default;
86
87 std::unordered_map<std::string, CachedJClass> jClassRegistry;
88
89 void loadJClass(
90 JNIEnv *env,
91 const std::string &name,
92 const std::vector<std::pair<std::string, std::string>> &methods
93 );
94 };
95 } // namespace expo
96