-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathRNFPointerHolder.h
More file actions
105 lines (88 loc) · 3.11 KB
/
RNFPointerHolder.h
File metadata and controls
105 lines (88 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//
// Created by Marc Rousavy on 16.04.24.
//
#pragma once
#include "RNFHybridObject.h"
#include "RNFLogger.h"
#include <memory>
#include <mutex>
#include <utility>
#include <string>
namespace margelo {
namespace jsi = facebook::jsi;
template <typename T> class PointerHolder : public HybridObject {
public:
size_t getMemoryPressure() override {
std::unique_lock lock(_mutex);
if (_pointer == nullptr) {
return 0;
}
// Default to a small-but-nonzero floor so holders contribute to pressure.
return 64 * 1024; // 64KB
}
protected:
// no default constructor
PointerHolder() = delete;
/**
* Create a new instance of a pointer holder which holds the given shared_ptr.
* @param name The name of the implementing class, for example "ViewWrapper".
* @param pointer The pointer this class will hold. It might be released from JS at any point via `release()`.
*/
PointerHolder(const char* name, std::shared_ptr<T> pointer) : HybridObject(name), _name(name), _pointer(pointer) {
// eagerly initialize the release() method instead of putting it in `loadHybridMethods`
registerHybridMethod("release", &PointerHolder<T>::release, this);
registerHybridGetter("isValid", &PointerHolder<T>::getIsValid, this);
}
/**
* Create a new instance of a pointer holder which holds a shared_ptr of the given value.
* The shared_ptr will be move-constructed.
* @param name The name of the implementing class, for example "ViewWrapper".
* @param value The value this class will hold as a shared_ptr. It might be destroyed from JS at any point via `release()`.
*/
PointerHolder(const char* name, T&& value) : PointerHolder(name, std::make_shared<T>(std::move(value))) {}
/**
* Called when the PointerHolder gets automatically destroyed (e.g. via GC) and the shared_ptr will be destroyed.
*/
~PointerHolder() {
if (_pointer != nullptr) {
Logger::log(TAG, "Automatically releasing %s... (~PointerHolder())", _name.c_str());
}
}
protected:
/**
* Manually release this reference to the pointer.
* If there are any other references to this pointer, no memory will be force-deleted.
*/
virtual void release() {
std::unique_lock lock(_mutex);
if (_pointer == nullptr) {
throw std::runtime_error("Pointer " + _name + " has already been manually released!");
}
Logger::log(TAG, "Manually releasing %s... (PointerHolder::release())", _name.c_str());
_pointer = nullptr;
}
/**
* Get the shared_ptr this class is holding.
* If it has already been manually released from JS, this method will throw a runtime_error.
*/
std::shared_ptr<T> pointee() {
std::unique_lock lock(_mutex);
if (_pointer == nullptr) {
throw std::runtime_error("Pointer " + _name + " has already been manually released!");
}
return _pointer;
}
/**
* Get if the pointer is still valid and strong.
*/
bool getIsValid() {
std::unique_lock lock(_mutex);
return _pointer != nullptr;
}
private:
std::string _name;
std::shared_ptr<T> _pointer;
std::mutex _mutex;
static constexpr auto TAG = "PointerHolder";
};
} // namespace margelo