Fix cyclic references in ResourceMap

What
--
Refactor `ResourceMap` struct to remove hard references to parent ResourceMap.

How
--
Assuming the child resource maps are always nested within a parent, then
we can always assume the parent will be there and use a weak reference to
refer back to it.

> A Weak pointer is useful for keeping a temporary reference to the allocation managed by Rc without preventing its inner value from being dropped. It is also used to prevent circular references between Rc pointers, since mutual owning references would never allow either Rc to be dropped. For example, a tree could have strong Rc pointers from parent nodes to children, and Weak pointers from children back to their parents.

[ref](https://doc.rust-lang.org/nightly/std/rc/struct.Weak.html)
This commit is contained in:
Matt Gathu 2020-09-25 16:10:24 +02:00
parent 37c76a39ab
commit f615e41b78
1 changed files with 6 additions and 6 deletions

View File

@ -1,5 +1,5 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::rc::{Rc, Weak};
use actix_router::ResourceDef;
use fxhash::FxHashMap;
@ -11,7 +11,7 @@ use crate::request::HttpRequest;
#[derive(Clone, Debug)]
pub struct ResourceMap {
root: ResourceDef,
parent: RefCell<Option<Rc<ResourceMap>>>,
parent: RefCell<Weak<ResourceMap>>,
named: FxHashMap<String, ResourceDef>,
patterns: Vec<(ResourceDef, Option<Rc<ResourceMap>>)>,
}
@ -20,7 +20,7 @@ impl ResourceMap {
pub fn new(root: ResourceDef) -> Self {
ResourceMap {
root,
parent: RefCell::new(None),
parent: RefCell::new(Weak::new()),
named: FxHashMap::default(),
patterns: Vec::new(),
}
@ -38,7 +38,7 @@ impl ResourceMap {
pub(crate) fn finish(&self, current: Rc<ResourceMap>) {
for (_, nested) in &self.patterns {
if let Some(ref nested) = nested {
*nested.parent.borrow_mut() = Some(current.clone());
*nested.parent.borrow_mut() = Rc::downgrade(&current);
nested.finish(nested.clone());
}
}
@ -210,7 +210,7 @@ impl ResourceMap {
U: Iterator<Item = I>,
I: AsRef<str>,
{
if let Some(ref parent) = *self.parent.borrow() {
if let Some(ref parent) = self.parent.borrow().upgrade() {
parent.fill_root(path, elements)?;
}
if self.root.resource_path(path, elements) {
@ -230,7 +230,7 @@ impl ResourceMap {
U: Iterator<Item = I>,
I: AsRef<str>,
{
if let Some(ref parent) = *self.parent.borrow() {
if let Some(ref parent) = self.parent.borrow().upgrade() {
if let Some(pattern) = parent.named.get(name) {
self.fill_root(path, elements)?;
if pattern.resource_path(path, elements) {