Skip to content

Commit 64d0332

Browse files
committed
Enhance Process module with memory usage and exit functionality; update CI workflow to specify main branch and add V8 download step
1 parent b0242f3 commit 64d0332

6 files changed

Lines changed: 389 additions & 53 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: CI
22
on:
33
push:
4-
branches: '*'
4+
branches: [main]
55
pull_request:
66

77
jobs:
@@ -20,6 +20,9 @@ jobs:
2020
- name: Install Dependencies
2121
run: npm install
2222

23+
- name: Download V8
24+
run: ./download-v8.sh
25+
2326
- name: Install libffi build tools
2427
run: brew install autoconf automake libtool texinfo
2528

NativeScript/ffi/Block.mm

Lines changed: 90 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cstdint>
44
#include <cstring>
55
#include <mutex>
6+
#include <thread>
67
#include <unordered_map>
78
#include "Interop.h"
89
#include "ObjCBridge.h"
@@ -37,9 +38,59 @@
3738
constexpr int kBlockHasCopyDispose = (1 << 25);
3839
constexpr int kBlockRefCountOne = (1 << 1);
3940
constexpr int kBlockHasSignature = (1 << 30);
40-
std::unordered_map<void*, napi_ref> g_blockToJsFunction;
41+
42+
struct BlockJsFunctionEntry {
43+
napi_ref ref = nullptr;
44+
napi_env env = nullptr;
45+
std::thread::id jsThreadId;
46+
CFRunLoopRef jsRunLoop = nullptr;
47+
};
48+
49+
std::unordered_map<void*, BlockJsFunctionEntry> g_blockToJsFunction;
4150
std::mutex g_blockToJsFunctionMutex;
4251

52+
inline bool removeCachedBlockJsFunctionEntry(void* blockPtr, BlockJsFunctionEntry* entry) {
53+
std::lock_guard<std::mutex> lock(g_blockToJsFunctionMutex);
54+
auto it = g_blockToJsFunction.find(blockPtr);
55+
if (it == g_blockToJsFunction.end()) {
56+
return false;
57+
}
58+
if (entry != nullptr) {
59+
*entry = it->second;
60+
}
61+
g_blockToJsFunction.erase(it);
62+
return true;
63+
}
64+
65+
inline void deleteBlockReferenceOnOwningLoop(const BlockJsFunctionEntry& entry) {
66+
if (entry.ref == nullptr || entry.env == nullptr) {
67+
return;
68+
}
69+
70+
if (entry.jsThreadId == std::this_thread::get_id()) {
71+
napi_delete_reference(entry.env, entry.ref);
72+
return;
73+
}
74+
75+
CFRunLoopRef runLoop = entry.jsRunLoop;
76+
if (runLoop == nullptr) {
77+
runLoop = CFRunLoopGetMain();
78+
}
79+
80+
if (runLoop == nullptr) {
81+
return;
82+
}
83+
84+
CFRetain(runLoop);
85+
napi_env env = entry.env;
86+
napi_ref ref = entry.ref;
87+
CFRunLoopPerformBlock(runLoop, kCFRunLoopCommonModes, ^{
88+
napi_delete_reference(env, ref);
89+
CFRelease(runLoop);
90+
});
91+
CFRunLoopWakeUp(runLoop);
92+
}
93+
4394
void block_copy(void* dest, void* src) {
4495
auto dst = static_cast<Block_literal_1*>(dest);
4596
auto source = static_cast<Block_literal_1*>(src);
@@ -55,15 +106,9 @@ void block_release(void* src) {
55106
return;
56107
}
57108

58-
if (block->closure != nullptr && block->closure->env != nullptr) {
59-
std::lock_guard<std::mutex> lock(g_blockToJsFunctionMutex);
60-
auto it = g_blockToJsFunction.find(block);
61-
if (it != g_blockToJsFunction.end()) {
62-
if (std::this_thread::get_id() == block->closure->jsThreadId) {
63-
napi_delete_reference(block->closure->env, it->second);
64-
}
65-
g_blockToJsFunction.erase(it);
66-
}
109+
BlockJsFunctionEntry entry;
110+
if (removeCachedBlockJsFunctionEntry(block, &entry)) {
111+
deleteBlockReferenceOnOwningLoop(entry);
67112
}
68113

69114
if (block->closure != nullptr) {
@@ -81,20 +126,34 @@ void block_release(void* src) {
81126
};
82127

83128
inline napi_value getCachedBlockJsFunction(napi_env env, void* blockPtr) {
84-
std::lock_guard<std::mutex> lock(g_blockToJsFunctionMutex);
85-
auto it = g_blockToJsFunction.find(blockPtr);
86-
if (it == g_blockToJsFunction.end()) {
87-
return nullptr;
129+
BlockJsFunctionEntry removedEntry;
130+
bool shouldDelete = false;
131+
napi_value value = nullptr;
132+
133+
{
134+
std::lock_guard<std::mutex> lock(g_blockToJsFunctionMutex);
135+
auto it = g_blockToJsFunction.find(blockPtr);
136+
if (it == g_blockToJsFunction.end()) {
137+
return nullptr;
138+
}
139+
140+
value = nativescript::get_ref_value(env, it->second.ref);
141+
if (value == nullptr) {
142+
removedEntry = it->second;
143+
g_blockToJsFunction.erase(it);
144+
shouldDelete = true;
145+
}
88146
}
89-
napi_value value = nativescript::get_ref_value(env, it->second);
90-
if (value == nullptr) {
91-
napi_delete_reference(env, it->second);
92-
g_blockToJsFunction.erase(it);
147+
148+
if (shouldDelete) {
149+
deleteBlockReferenceOnOwningLoop(removedEntry);
93150
}
151+
94152
return value;
95153
}
96154

97-
inline void cacheBlockJsFunction(napi_env env, void* blockPtr, napi_value jsFunction) {
155+
inline void cacheBlockJsFunction(napi_env env, void* blockPtr, napi_value jsFunction,
156+
nativescript::Closure* closure) {
98157
if (blockPtr == nullptr || jsFunction == nullptr) {
99158
return;
100159
}
@@ -103,24 +162,27 @@ inline void cacheBlockJsFunction(napi_env env, void* blockPtr, napi_value jsFunc
103162
return;
104163
}
105164
// Keep this weak so callback identity can round-trip without preventing GC.
106-
g_blockToJsFunction[blockPtr] = nativescript::make_ref(env, jsFunction, 0);
165+
BlockJsFunctionEntry entry;
166+
entry.ref = nativescript::make_ref(env, jsFunction, 0);
167+
entry.env = env;
168+
entry.jsThreadId = closure != nullptr ? closure->jsThreadId : std::this_thread::get_id();
169+
entry.jsRunLoop = closure != nullptr ? closure->jsRunLoop : CFRunLoopGetCurrent();
170+
g_blockToJsFunction[blockPtr] = entry;
107171
}
108172

109173
} // namespace
110174

111175
void block_finalize(napi_env env, void* data, void* hint) {
176+
(void)env;
177+
(void)hint;
112178
auto block = static_cast<Block_literal_1*>(data);
113179
if (block == nullptr) {
114180
return;
115181
}
116182

117-
{
118-
std::lock_guard<std::mutex> lock(g_blockToJsFunctionMutex);
119-
auto it = g_blockToJsFunction.find(block);
120-
if (it != g_blockToJsFunction.end()) {
121-
napi_delete_reference(env, it->second);
122-
g_blockToJsFunction.erase(it);
123-
}
183+
BlockJsFunctionEntry entry;
184+
if (removeCachedBlockJsFunctionEntry(block, &entry)) {
185+
deleteBlockReferenceOnOwningLoop(entry);
124186
}
125187

126188
if (block->closure != nullptr) {
@@ -175,7 +237,7 @@ id registerBlock(napi_env env, Closure* closure, napi_value callback) {
175237
}
176238
#endif // ENABLE_JS_RUNTIME
177239

178-
cacheBlockJsFunction(env, block, callback);
240+
cacheBlockJsFunction(env, block, callback, closure);
179241

180242
return (id)block;
181243
}

0 commit comments

Comments
 (0)