mirror of https://github.com/fafhrd91/actix-web
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:
parent
37c76a39ab
commit
f615e41b78
12
src/rmap.rs
12
src/rmap.rs
|
@ -1,5 +1,5 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
use actix_router::ResourceDef;
|
use actix_router::ResourceDef;
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
|
@ -11,7 +11,7 @@ use crate::request::HttpRequest;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ResourceMap {
|
pub struct ResourceMap {
|
||||||
root: ResourceDef,
|
root: ResourceDef,
|
||||||
parent: RefCell<Option<Rc<ResourceMap>>>,
|
parent: RefCell<Weak<ResourceMap>>,
|
||||||
named: FxHashMap<String, ResourceDef>,
|
named: FxHashMap<String, ResourceDef>,
|
||||||
patterns: Vec<(ResourceDef, Option<Rc<ResourceMap>>)>,
|
patterns: Vec<(ResourceDef, Option<Rc<ResourceMap>>)>,
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ impl ResourceMap {
|
||||||
pub fn new(root: ResourceDef) -> Self {
|
pub fn new(root: ResourceDef) -> Self {
|
||||||
ResourceMap {
|
ResourceMap {
|
||||||
root,
|
root,
|
||||||
parent: RefCell::new(None),
|
parent: RefCell::new(Weak::new()),
|
||||||
named: FxHashMap::default(),
|
named: FxHashMap::default(),
|
||||||
patterns: Vec::new(),
|
patterns: Vec::new(),
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ impl ResourceMap {
|
||||||
pub(crate) fn finish(&self, current: Rc<ResourceMap>) {
|
pub(crate) fn finish(&self, current: Rc<ResourceMap>) {
|
||||||
for (_, nested) in &self.patterns {
|
for (_, nested) in &self.patterns {
|
||||||
if let Some(ref nested) = nested {
|
if let Some(ref nested) = nested {
|
||||||
*nested.parent.borrow_mut() = Some(current.clone());
|
*nested.parent.borrow_mut() = Rc::downgrade(¤t);
|
||||||
nested.finish(nested.clone());
|
nested.finish(nested.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ impl ResourceMap {
|
||||||
U: Iterator<Item = I>,
|
U: Iterator<Item = I>,
|
||||||
I: AsRef<str>,
|
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)?;
|
parent.fill_root(path, elements)?;
|
||||||
}
|
}
|
||||||
if self.root.resource_path(path, elements) {
|
if self.root.resource_path(path, elements) {
|
||||||
|
@ -230,7 +230,7 @@ impl ResourceMap {
|
||||||
U: Iterator<Item = I>,
|
U: Iterator<Item = I>,
|
||||||
I: AsRef<str>,
|
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) {
|
if let Some(pattern) = parent.named.get(name) {
|
||||||
self.fill_root(path, elements)?;
|
self.fill_root(path, elements)?;
|
||||||
if pattern.resource_path(path, elements) {
|
if pattern.resource_path(path, elements) {
|
||||||
|
|
Loading…
Reference in New Issue