mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-23 05:24:51 +00:00
refactor: use Weak in container
This commit is contained in:
parent
9748779f08
commit
065e646a7e
13 changed files with 74 additions and 49 deletions
|
@ -1,5 +1,5 @@
|
|||
// TODO: refactor, extract common code with text
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Mutex, Weak};
|
||||
|
||||
use rle::{
|
||||
rle_tree::{tree_trait::CumulateTreeTrait, HeapMode},
|
||||
|
@ -88,9 +88,9 @@ impl ListContainer {
|
|||
let (event, container_id) = self.insert_obj(ctx, pos, value.into_container().unwrap());
|
||||
let m = ctx.log_store();
|
||||
let store = m.read().unwrap();
|
||||
let container = Arc::clone(store.get_container(&container_id).unwrap());
|
||||
let container = store.get_container(&container_id).unwrap();
|
||||
drop(store);
|
||||
prelim.integrate(ctx, &container);
|
||||
prelim.integrate(ctx, container);
|
||||
(event, Some(container_id))
|
||||
} else {
|
||||
let value = value.into_value().unwrap();
|
||||
|
@ -554,21 +554,21 @@ impl Container for ListContainer {
|
|||
}
|
||||
|
||||
pub struct List {
|
||||
instance: Arc<Mutex<ContainerInstance>>,
|
||||
instance: Weak<Mutex<ContainerInstance>>,
|
||||
client_id: ClientID,
|
||||
}
|
||||
|
||||
impl Clone for List {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
instance: Arc::clone(&self.instance),
|
||||
instance: Weak::clone(&self.instance),
|
||||
client_id: self.client_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl List {
|
||||
pub fn from_instance(instance: Arc<Mutex<ContainerInstance>>, client_id: ClientID) -> Self {
|
||||
pub fn from_instance(instance: Weak<Mutex<ContainerInstance>>, client_id: ClientID) -> Self {
|
||||
Self {
|
||||
instance,
|
||||
client_id,
|
||||
|
@ -618,7 +618,8 @@ impl ContainerWrapper for List {
|
|||
where
|
||||
F: FnOnce(&mut Self::Container) -> R,
|
||||
{
|
||||
let mut container_instance = self.instance.try_lock().unwrap();
|
||||
let w = self.instance.upgrade().unwrap();
|
||||
let mut container_instance = w.try_lock().unwrap();
|
||||
let list = container_instance.as_list_mut().unwrap();
|
||||
let ans = f(list);
|
||||
drop(container_instance);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Mutex, Weak};
|
||||
|
||||
use super::{super::pool::Pool, InnerMapSet};
|
||||
use crate::{
|
||||
|
@ -73,9 +73,9 @@ impl MapContainer {
|
|||
let (event, container_id) = self.insert_obj(ctx, key, value.into_container().unwrap());
|
||||
let m = ctx.log_store();
|
||||
let store = m.read().unwrap();
|
||||
let container = Arc::clone(store.get_container(&container_id).unwrap());
|
||||
let container = store.get_container(&container_id).unwrap();
|
||||
drop(store);
|
||||
prelim.integrate(ctx, &container);
|
||||
prelim.integrate(ctx, container);
|
||||
(event, Some(container_id))
|
||||
} else {
|
||||
let value = value.into_value().unwrap();
|
||||
|
@ -481,21 +481,21 @@ impl Container for MapContainer {
|
|||
}
|
||||
|
||||
pub struct Map {
|
||||
instance: Arc<Mutex<ContainerInstance>>,
|
||||
instance: Weak<Mutex<ContainerInstance>>,
|
||||
client_id: ClientID,
|
||||
}
|
||||
|
||||
impl Clone for Map {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
instance: Arc::clone(&self.instance),
|
||||
instance: Weak::clone(&self.instance),
|
||||
client_id: self.client_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Map {
|
||||
pub fn from_instance(instance: Arc<Mutex<ContainerInstance>>, client_id: ClientID) -> Self {
|
||||
pub fn from_instance(instance: Weak<Mutex<ContainerInstance>>, client_id: ClientID) -> Self {
|
||||
Self {
|
||||
instance,
|
||||
client_id,
|
||||
|
@ -521,6 +521,8 @@ impl Map {
|
|||
|
||||
pub fn id(&self) -> ContainerID {
|
||||
self.instance
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.as_map()
|
||||
|
@ -531,6 +533,8 @@ impl Map {
|
|||
|
||||
pub fn get_value(&self) -> LoroValue {
|
||||
self.instance
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.as_map()
|
||||
|
@ -556,7 +560,8 @@ impl ContainerWrapper for Map {
|
|||
where
|
||||
F: FnOnce(&mut Self::Container) -> R,
|
||||
{
|
||||
let mut container_instance = self.instance.try_lock().unwrap();
|
||||
let w = self.instance.upgrade().unwrap();
|
||||
let mut container_instance = w.try_lock().unwrap();
|
||||
let map = container_instance.as_map_mut().unwrap();
|
||||
let ans = f(map);
|
||||
drop(container_instance);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
sync::{Arc, Mutex, RwLockWriteGuard},
|
||||
sync::{Arc, Mutex, RwLockWriteGuard, Weak},
|
||||
};
|
||||
|
||||
use enum_as_inner::EnumAsInner;
|
||||
|
@ -248,10 +248,10 @@ impl ContainerRegistry {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get(&self, id: &ContainerID) -> Option<&Arc<Mutex<ContainerInstance>>> {
|
||||
pub fn get(&self, id: &ContainerID) -> Option<Weak<Mutex<ContainerInstance>>> {
|
||||
self.container_to_idx
|
||||
.get(id)
|
||||
.map(|x| &self.containers[x.0 as usize].container)
|
||||
.map(|x| Arc::downgrade(&self.containers[x.0 as usize].container))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -290,7 +290,7 @@ impl ContainerRegistry {
|
|||
self.insert(id.clone(), container)
|
||||
}
|
||||
|
||||
pub(crate) fn get_or_create(&mut self, id: &ContainerID) -> &Arc<Mutex<ContainerInstance>> {
|
||||
pub(crate) fn get_or_create(&mut self, id: &ContainerID) -> Weak<Mutex<ContainerInstance>> {
|
||||
if !self.container_to_idx.contains_key(id) {
|
||||
let container = self.create(id.clone());
|
||||
self.insert(id.clone(), container);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Mutex, Weak};
|
||||
|
||||
use append_only_bytes::AppendOnlyBytes;
|
||||
use rle::HasLength;
|
||||
|
@ -476,21 +476,21 @@ impl Container for TextContainer {
|
|||
}
|
||||
|
||||
pub struct Text {
|
||||
instance: Arc<Mutex<ContainerInstance>>,
|
||||
instance: Weak<Mutex<ContainerInstance>>,
|
||||
client_id: ClientID,
|
||||
}
|
||||
|
||||
impl Clone for Text {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
instance: Arc::clone(&self.instance),
|
||||
instance: Weak::clone(&self.instance),
|
||||
client_id: self.client_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Text {
|
||||
pub fn from_instance(instance: Arc<Mutex<ContainerInstance>>, client_id: ClientID) -> Self {
|
||||
pub fn from_instance(instance: Weak<Mutex<ContainerInstance>>, client_id: ClientID) -> Self {
|
||||
Self {
|
||||
instance,
|
||||
client_id,
|
||||
|
@ -499,6 +499,8 @@ impl Text {
|
|||
|
||||
pub fn id(&self) -> ContainerID {
|
||||
self.instance
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.as_text()
|
||||
|
@ -527,6 +529,8 @@ impl Text {
|
|||
|
||||
pub fn get_value(&self) -> LoroValue {
|
||||
self.instance
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.as_text()
|
||||
|
@ -551,7 +555,8 @@ impl ContainerWrapper for Text {
|
|||
where
|
||||
F: FnOnce(&mut Self::Container) -> R,
|
||||
{
|
||||
let mut container_instance = self.instance.try_lock().unwrap();
|
||||
let w = self.instance.upgrade().unwrap();
|
||||
let mut container_instance = w.try_lock().unwrap();
|
||||
let text = container_instance.as_text_mut().unwrap();
|
||||
let ans = f(text);
|
||||
drop(container_instance);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::sync::{Arc, Mutex, RwLock, Weak};
|
||||
|
||||
use crate::{
|
||||
container::{registry::ContainerInstance, ContainerID},
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||
|
||||
pub trait Context {
|
||||
fn log_store(&self) -> Arc<RwLock<LogStore>>;
|
||||
fn get_container(&self, id: &ContainerID) -> Option<Arc<Mutex<ContainerInstance>>>;
|
||||
fn get_container(&self, id: &ContainerID) -> Option<Weak<Mutex<ContainerInstance>>>;
|
||||
}
|
||||
|
||||
impl Context for LoroCore {
|
||||
|
@ -15,11 +15,7 @@ impl Context for LoroCore {
|
|||
self.log_store.clone()
|
||||
}
|
||||
|
||||
fn get_container(&self, id: &ContainerID) -> Option<Arc<Mutex<ContainerInstance>>> {
|
||||
self.log_store
|
||||
.try_read()
|
||||
.unwrap()
|
||||
.get_container(id)
|
||||
.cloned()
|
||||
fn get_container(&self, id: &ContainerID) -> Option<Weak<Mutex<ContainerInstance>>> {
|
||||
self.log_store.try_read().unwrap().get_container(id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,6 +160,8 @@ impl Hierarchy {
|
|||
if let Some(parent) = parent {
|
||||
let parent_node = reg.get(parent).unwrap();
|
||||
let index = parent_node
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.index_of_child(node_id)
|
||||
|
|
|
@ -10,7 +10,7 @@ pub use encoding::{EncodeConfig, EncodeMode, LoroEncoder};
|
|||
pub(crate) use import::ImportContext;
|
||||
use std::{
|
||||
marker::PhantomPinned,
|
||||
sync::{Arc, Mutex, MutexGuard, RwLock},
|
||||
sync::{Arc, Mutex, MutexGuard, RwLock, Weak},
|
||||
};
|
||||
|
||||
use fxhash::FxHashMap;
|
||||
|
@ -341,12 +341,12 @@ impl LogStore {
|
|||
pub fn get_or_create_container(
|
||||
&mut self,
|
||||
container: &ContainerID,
|
||||
) -> &Arc<Mutex<ContainerInstance>> {
|
||||
) -> Weak<Mutex<ContainerInstance>> {
|
||||
self.reg.get_or_create(container)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_container(&self, container: &ContainerID) -> Option<&Arc<Mutex<ContainerInstance>>> {
|
||||
pub fn get_container(&self, container: &ContainerID) -> Option<Weak<Mutex<ContainerInstance>>> {
|
||||
self.reg.get(container)
|
||||
}
|
||||
|
||||
|
|
|
@ -198,7 +198,12 @@ pub(super) fn encode_snapshot(store: &LogStore, gc: bool) -> Result<Vec<u8>, Lor
|
|||
let (_, containers) = store.reg.export();
|
||||
for container_id in containers.iter() {
|
||||
let container = store.reg.get(container_id).unwrap();
|
||||
container.try_lock().unwrap().initialize_pool_mapping();
|
||||
container
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.initialize_pool_mapping();
|
||||
}
|
||||
|
||||
let mut changes = Vec::with_capacity(change_num);
|
||||
|
@ -220,6 +225,8 @@ pub(super) fn encode_snapshot(store: &LogStore, gc: bool) -> Result<Vec<u8>, Lor
|
|||
let container_id = store.reg.get_id(container_idx).unwrap();
|
||||
let container = store.reg.get(container_id).unwrap();
|
||||
let new_ops = container
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.to_export_snapshot(&op.content, gc);
|
||||
|
@ -251,6 +258,8 @@ pub(super) fn encode_snapshot(store: &LogStore, gc: bool) -> Result<Vec<u8>, Lor
|
|||
.map(|container_id| {
|
||||
let container = store.reg.get(container_id).unwrap();
|
||||
container
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.try_lock()
|
||||
.unwrap()
|
||||
.encode_and_release_pool_mapping()
|
||||
|
|
|
@ -338,7 +338,8 @@ impl LogStore {
|
|||
for change in changes.iter() {
|
||||
for op in change.ops.iter() {
|
||||
if !container_map.contains_key(&op.container) {
|
||||
let guard = self.reg.get_or_create(&op.container).try_lock().unwrap();
|
||||
let guard = self.reg.get_or_create(&op.container).upgrade().unwrap();
|
||||
let guard = guard.try_lock().unwrap();
|
||||
container_map
|
||||
// SAFETY: ignore lifetime issues here, because it's safe for us to store the mutex guard here
|
||||
.insert(op.container.clone(), unsafe { std::mem::transmute(guard) });
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Mutex, Weak};
|
||||
|
||||
use enum_as_inner::EnumAsInner;
|
||||
|
||||
|
@ -14,7 +14,7 @@ pub trait Prelim: Sized {
|
|||
fn convert_value(self) -> (PrelimValue, Option<Self>);
|
||||
|
||||
/// How to integrate the value into the Loro.
|
||||
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>);
|
||||
fn integrate<C: Context>(self, ctx: &C, container: Weak<Mutex<ContainerInstance>>);
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumAsInner)]
|
||||
|
@ -33,7 +33,7 @@ where
|
|||
(PrelimValue::Value(value), None)
|
||||
}
|
||||
|
||||
fn integrate<C: Context>(self, _ctx: &C, _container: &Arc<Mutex<ContainerInstance>>) {}
|
||||
fn integrate<C: Context>(self, _ctx: &C, _container: Weak<Mutex<ContainerInstance>>) {}
|
||||
}
|
||||
|
||||
impl Prelim for ContainerType {
|
||||
|
@ -41,7 +41,7 @@ impl Prelim for ContainerType {
|
|||
(PrelimValue::Container(self), Some(self))
|
||||
}
|
||||
|
||||
fn integrate<C: Context>(self, _ctx: &C, _container: &Arc<Mutex<ContainerInstance>>) {}
|
||||
fn integrate<C: Context>(self, _ctx: &C, _container: Weak<Mutex<ContainerInstance>>) {}
|
||||
}
|
||||
|
||||
impl From<LoroValue> for PrelimValue {
|
||||
|
|
|
@ -52,7 +52,8 @@ impl LoroValue {
|
|||
self = reg
|
||||
.get(id)
|
||||
.map(|container| {
|
||||
let mut value = container.try_lock().unwrap().get_value();
|
||||
let mut value =
|
||||
container.upgrade().unwrap().try_lock().unwrap().get_value();
|
||||
|
||||
match &mut value {
|
||||
LoroValue::List(list) => {
|
||||
|
|
|
@ -263,12 +263,14 @@ fn encode_hierarchy() {
|
|||
let (_, text_id) = {
|
||||
let list_id = map.insert(&c1, "a", ContainerType::List).unwrap();
|
||||
let list = c1.get_container(&list_id.unwrap()).unwrap();
|
||||
let list = list.upgrade().unwrap();
|
||||
let mut list = list.try_lock().unwrap();
|
||||
let list = list.as_list_mut().unwrap();
|
||||
list.insert(&c1, 0, ContainerType::Text)
|
||||
};
|
||||
{
|
||||
let text = c1.get_container(&text_id.unwrap()).unwrap();
|
||||
let text = text.upgrade().unwrap();
|
||||
let mut text = text.try_lock().unwrap();
|
||||
let text = text.as_text_mut().unwrap();
|
||||
text.insert(&c1, 0, "text_text");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, Mutex, Weak},
|
||||
};
|
||||
|
||||
use loro_core::{
|
||||
|
@ -35,7 +35,7 @@ impl Prelim for PrelimType {
|
|||
}
|
||||
}
|
||||
|
||||
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>) {
|
||||
fn integrate<C: Context>(self, ctx: &C, container: Weak<Mutex<ContainerInstance>>) {
|
||||
match self {
|
||||
PrelimType::Text(t) => t.integrate(ctx, container),
|
||||
PrelimType::Map(m) => m.integrate(ctx, container),
|
||||
|
@ -148,8 +148,9 @@ impl Prelim for PrelimText {
|
|||
(PrelimValue::Container(ContainerType::Text), Some(self))
|
||||
}
|
||||
|
||||
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>) {
|
||||
let mut text = container.try_lock().unwrap();
|
||||
fn integrate<C: Context>(self, ctx: &C, container: Weak<Mutex<ContainerInstance>>) {
|
||||
let text = container.upgrade().unwrap();
|
||||
let mut text = text.try_lock().unwrap();
|
||||
let text = text.as_text_mut().unwrap();
|
||||
text.insert(ctx, 0, &self.0);
|
||||
}
|
||||
|
@ -160,8 +161,9 @@ impl Prelim for PrelimList {
|
|||
(PrelimValue::Container(ContainerType::List), Some(self))
|
||||
}
|
||||
|
||||
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>) {
|
||||
let mut list = container.try_lock().unwrap();
|
||||
fn integrate<C: Context>(self, ctx: &C, container: Weak<Mutex<ContainerInstance>>) {
|
||||
let list = container.upgrade().unwrap();
|
||||
let mut list = list.try_lock().unwrap();
|
||||
let list = list.as_list_mut().unwrap();
|
||||
let values: Vec<LoroValue> = self.0.into_iter().map(|v| v.into()).collect();
|
||||
list.insert_batch(ctx, 0, values);
|
||||
|
@ -173,8 +175,9 @@ impl Prelim for PrelimMap {
|
|||
(PrelimValue::Container(ContainerType::Map), Some(self))
|
||||
}
|
||||
|
||||
fn integrate<C: Context>(self, ctx: &C, container: &Arc<Mutex<ContainerInstance>>) {
|
||||
let mut map = container.try_lock().unwrap();
|
||||
fn integrate<C: Context>(self, ctx: &C, container: Weak<Mutex<ContainerInstance>>) {
|
||||
let map = container.upgrade().unwrap();
|
||||
let mut map = map.try_lock().unwrap();
|
||||
let map = map.as_map_mut().unwrap();
|
||||
for (key, value) in self.0.into_iter() {
|
||||
let value: LoroValue = value.into();
|
||||
|
|
Loading…
Reference in a new issue