Skip to content

Commit

Permalink
fix(ios): avoid deadlock in native render manager (Tencent#4157)
Browse files Browse the repository at this point in the history
  • Loading branch information
wwwcg committed Dec 30, 2024
1 parent 94c1294 commit 79349c8
Showing 1 changed file with 150 additions and 91 deletions.
241 changes: 150 additions & 91 deletions renderer/native/ios/renderer/NativeRenderManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,14 @@
@autoreleasepool {
auto rootNode = root_node.lock();
if (rootNode) {
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
[uiManager createRenderNodes:std::move(nodes) onRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager createRenderNodes:std::move(nodes) onRootNode:root_node];
}
}
}
}
Expand All @@ -59,11 +64,15 @@
@autoreleasepool {
auto rootNode = root_node.lock();
if (rootNode) {
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
[uiManager updateRenderNodes:std::move(nodes) onRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager updateRenderNodes:std::move(nodes) onRootNode:root_node];
}
}

}
}

Expand All @@ -72,32 +81,43 @@
@autoreleasepool {
auto rootNode = root_node.lock();
if (rootNode) {
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
[uiManager deleteRenderNodesIds:std::move(nodes) onRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager deleteRenderNodesIds:std::move(nodes) onRootNode:root_node];
}
}
}
}


void NativeRenderManager::UpdateLayout(std::weak_ptr<hippy::RootNode> root_node,
const std::vector<std::shared_ptr<DomNode>>& nodes) {
@autoreleasepool {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
using DomNodeUpdateInfoTuple = std::tuple<int32_t, hippy::LayoutResult>;
std::vector<DomNodeUpdateInfoTuple> nodes_infos;
nodes_infos.reserve(nodes.size());
for (auto node : nodes) {
int32_t tag = node->GetId();
hippy::LayoutResult layoutResult = node->GetRenderLayoutResult();
DomNodeUpdateInfoTuple nodeUpdateInfo = std::make_tuple(tag, layoutResult);
nodes_infos.push_back(nodeUpdateInfo);
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
using DomNodeUpdateInfoTuple = std::tuple<int32_t, hippy::LayoutResult>;
std::vector<DomNodeUpdateInfoTuple> nodes_infos;
nodes_infos.reserve(nodes.size());
for (auto node : nodes) {
int32_t tag = node->GetId();
hippy::LayoutResult layoutResult = node->GetRenderLayoutResult();
DomNodeUpdateInfoTuple nodeUpdateInfo = std::make_tuple(tag, layoutResult);
nodes_infos.push_back(nodeUpdateInfo);
}
[uiManager updateNodesLayout:nodes_infos onRootNode:root_node];
}
[uiManager updateNodesLayout:nodes_infos onRootNode:root_node];
}
}

Expand All @@ -111,13 +131,18 @@
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
[uiManager renderMoveViews:std::move(moved_ids)
fromContainer:from_pid
toContainer:to_pid
index:index
onRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager renderMoveViews:std::move(moved_ids)
fromContainer:from_pid
toContainer:to_pid
index:index
onRootNode:root_node];
}
}
}

Expand All @@ -128,26 +153,31 @@
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
// Check whether all nodes have the same pid
uint32_t firstPid = nodes[0]->GetPid();
bool allSamePid = std::all_of(nodes.begin(), nodes.end(),
[firstPid](const std::shared_ptr<DomNode>& node) {
return node->GetPid() == firstPid;
});

if (allSamePid) {
// If all nodes have the same pid, call directly
[uiManager renderMoveNodes:std::move(nodes) onRootNode:root_node];
} else {
// If not, group them by pid and then call for each group
std::map<int, std::vector<std::shared_ptr<DomNode>>> pidNodeMap;
for (auto& node : nodes) {
pidNodeMap[node->GetPid()].push_back(node);
}
for (auto& pair : pidNodeMap) {
[uiManager renderMoveNodes:std::move(pair.second) onRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
// Check whether all nodes have the same pid
uint32_t firstPid = nodes[0]->GetPid();
bool allSamePid = std::all_of(nodes.begin(), nodes.end(),
[firstPid](const std::shared_ptr<DomNode>& node) {
return node->GetPid() == firstPid;
});

if (allSamePid) {
// If all nodes have the same pid, call directly
[uiManager renderMoveNodes:std::move(nodes) onRootNode:root_node];
} else {
// If not, group them by pid and then call for each group
std::map<int, std::vector<std::shared_ptr<DomNode>>> pidNodeMap;
for (auto& node : nodes) {
pidNodeMap[node->GetPid()].push_back(node);
}
for (auto& pair : pidNodeMap) {
[uiManager renderMoveNodes:std::move(pair.second) onRootNode:root_node];
}
}
}
}
Expand All @@ -160,18 +190,24 @@
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
[uiManager batchOnRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager batchOnRootNode:root_node];
}
TDF_PERF_LOG("NativeRenderManager::EndBatch End");

}
}

void NativeRenderManager::BeforeLayout(std::weak_ptr<hippy::RootNode> root_node) {
// Implementation if needed
}

void NativeRenderManager::AfterLayout(std::weak_ptr<hippy::RootNode> root_node) {
// Implementation if needed
}

void NativeRenderManager::AddEventListener(std::weak_ptr<hippy::RootNode> root_node,
Expand All @@ -182,15 +218,20 @@
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
auto node = dom_node.lock();
if (node) {
int32_t tag = node->GetId();
[uiManager addEventName:name forDomNodeId:tag onRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
auto node = dom_node.lock();
if (node) {
int32_t tag = node->GetId();
[uiManager addEventName:name forDomNodeId:tag onRootNode:root_node];
}
}
}
};
}

void NativeRenderManager::RemoveEventListener(std::weak_ptr<hippy::RootNode> root_node,
std::weak_ptr<DomNode> dom_node,
Expand All @@ -200,12 +241,17 @@
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
auto node = dom_node.lock();
if (node) {
int32_t node_id = node->GetId();
[uiManager removeEventName:name forDomNodeId:node_id onRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
auto node = dom_node.lock();
if (node) {
int32_t node_id = node->GetId();
[uiManager removeEventName:name forDomNodeId:node_id onRootNode:root_node];
}
}
}
}
Expand All @@ -216,9 +262,14 @@
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
[uiManager removeVSyncEventOnRootNode:root_node];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
[uiManager removeVSyncEventOnRootNode:root_node];
}
}
}

Expand All @@ -232,46 +283,54 @@
if (!rootNode) {
return;
}
std::shared_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootNode->GetId()];
std::shared_ptr<DomNode> node = dom_node.lock();
if (node) {
HippyValue hippy_value;
param.ToObject(hippy_value);
[uiManager dispatchFunction:name
viewName:node->GetViewName()
viewTag:node->GetId()
onRootNode:root_node
params:hippy_value
callback:node->GetCallback(name, cb)];
HippyUIManager *uiManager = nil;
{
std::shared_lock<std::shared_mutex> lock(_mutex);
uiManager = _uiManagerMap[rootNode->GetId()];
}
if (uiManager) {
std::shared_ptr<DomNode> node = dom_node.lock();
if (node) {
HippyValue hippy_value;
param.ToObject(hippy_value);
[uiManager dispatchFunction:name
viewName:node->GetViewName()
viewTag:node->GetId()
onRootNode:root_node
params:hippy_value
callback:node->GetCallback(name, cb)];
}
EndBatch(root_node);
}
EndBatch(root_node);
}
}

void NativeRenderManager::RegisterRootView(UIView *view,
std::weak_ptr<hippy::RootNode> root_node,
HippyUIManager *uiManager) {
@autoreleasepool {
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyAssertParam(uiManager);
auto rootNode = root_node.lock();
if (!rootNode) {
return;
}
HippyAssertParam(uiManager);
{
std::unique_lock<std::shared_mutex> lock(_mutex);
_uiManagerMap[rootNode->GetId()] = uiManager;
[uiManager registerRootView:view asRootNode:root_node];
}
[uiManager registerRootView:view asRootNode:root_node];
}

void NativeRenderManager::UnregisterRootView(uint32_t rootId) {
@autoreleasepool {
HippyUIManager *uiManager = nil;
{
std::unique_lock<std::shared_mutex> lock(_mutex);
HippyUIManager *uiManager = _uiManagerMap[rootId];
uiManager = _uiManagerMap[rootId];
HippyAssertParam(uiManager);
[uiManager unregisterRootViewFromTag:@(rootId)];
_uiManagerMap.erase(rootId);
}
if (uiManager) {
[uiManager unregisterRootViewFromTag:@(rootId)];
}
}

NativeRenderManager::~NativeRenderManager() {
Expand Down

0 comments on commit 79349c8

Please sign in to comment.