mirror of
https://github.com/RGBCube/cstree
synced 2025-07-27 17:17:45 +00:00
Make SyntaxNode
Send
and Sync
(#12)
This commit is contained in:
parent
4116ed0138
commit
fb463aef18
4 changed files with 175 additions and 0 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -15,6 +15,12 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.2"
|
version = "1.4.2"
|
||||||
|
@ -27,10 +33,22 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cstree"
|
name = "cstree"
|
||||||
version = "0.0.2"
|
version = "0.0.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
"fxhash",
|
"fxhash",
|
||||||
"lasso",
|
"lasso",
|
||||||
"m_lexer",
|
"m_lexer",
|
||||||
|
|
|
@ -25,6 +25,7 @@ features = ["derive"]
|
||||||
m_lexer = "0.0.4"
|
m_lexer = "0.0.4"
|
||||||
serde_json = "1.0.61"
|
serde_json = "1.0.61"
|
||||||
serde_test = "1.0.119"
|
serde_test = "1.0.119"
|
||||||
|
crossbeam-utils = "0.8"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
|
@ -38,6 +38,9 @@ pub struct SyntaxNode<L: Language, D: 'static = (), R: 'static = ()> {
|
||||||
data: *mut NodeData<L, D, R>,
|
data: *mut NodeData<L, D, R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<L: Language, D: 'static, R: 'static> Send for SyntaxNode<L, D, R> {}
|
||||||
|
unsafe impl<L: Language, D: 'static, R: 'static> Sync for SyntaxNode<L, D, R> {}
|
||||||
|
|
||||||
impl<L: Language, D, R> SyntaxNode<L, D, R> {
|
impl<L: Language, D, R> SyntaxNode<L, D, R> {
|
||||||
pub fn debug(&self, resolver: &impl Resolver, recursive: bool) -> String {
|
pub fn debug(&self, resolver: &impl Resolver, recursive: bool) -> String {
|
||||||
// NOTE: `fmt::Write` methods on `String` never fail
|
// NOTE: `fmt::Write` methods on `String` never fail
|
||||||
|
|
153
tests/sendsync.rs
Normal file
153
tests/sendsync.rs
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
#![allow(clippy::redundant_clone)]
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
mod common;
|
||||||
|
|
||||||
|
use crossbeam_utils::thread::scope;
|
||||||
|
use std::{thread, time::Duration};
|
||||||
|
|
||||||
|
use common::{build_recursive, Element, SyntaxNode};
|
||||||
|
use cstree::GreenNodeBuilder;
|
||||||
|
use lasso::Resolver;
|
||||||
|
|
||||||
|
fn build_tree<D>(root: &Element<'_>) -> SyntaxNode<D, impl Resolver> {
|
||||||
|
let mut builder = GreenNodeBuilder::new();
|
||||||
|
build_recursive(root, &mut builder, 0);
|
||||||
|
let (node, interner) = builder.finish();
|
||||||
|
SyntaxNode::new_root_with_resolver(node, interner.unwrap().into_resolver())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn two_level_tree() -> Element<'static> {
|
||||||
|
use Element::*;
|
||||||
|
Node(vec![
|
||||||
|
Node(vec![Token("0.0"), Token("0.1")]),
|
||||||
|
Node(vec![Token("1.0")]),
|
||||||
|
Node(vec![Token("2.0"), Token("2.1"), Token("2.2")]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore)]
|
||||||
|
fn send() {
|
||||||
|
let tree = two_level_tree();
|
||||||
|
let tree = build_tree::<()>(&tree);
|
||||||
|
let thread_tree = tree.clone();
|
||||||
|
let thread = thread::spawn(move || {
|
||||||
|
let leaf1_0 = thread_tree
|
||||||
|
.children()
|
||||||
|
.nth(1)
|
||||||
|
.unwrap()
|
||||||
|
.children_with_tokens()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
let leaf1_0 = leaf1_0.into_token().unwrap();
|
||||||
|
leaf1_0.resolve_text(thread_tree.resolver().as_ref()).to_string()
|
||||||
|
});
|
||||||
|
assert_eq!(thread.join().unwrap(), "1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore)]
|
||||||
|
fn send_data() {
|
||||||
|
let tree = two_level_tree();
|
||||||
|
let tree = build_tree::<String>(&tree);
|
||||||
|
let thread_tree = tree.clone();
|
||||||
|
{
|
||||||
|
let node2 = tree.children().nth(2).unwrap();
|
||||||
|
assert_eq!(*node2.try_set_data("data".into()).unwrap(), "data");
|
||||||
|
let data = node2.get_data().unwrap();
|
||||||
|
assert_eq!(data.as_str(), "data");
|
||||||
|
node2.set_data("payload".into());
|
||||||
|
let data = node2.get_data().unwrap();
|
||||||
|
assert_eq!(data.as_str(), "payload");
|
||||||
|
}
|
||||||
|
let t = thread::spawn(move || {
|
||||||
|
let node2 = thread_tree.children().nth(2).unwrap();
|
||||||
|
assert!(node2.try_set_data("already present".into()).is_err());
|
||||||
|
let data = node2.get_data().unwrap();
|
||||||
|
assert_eq!(data.as_str(), "payload");
|
||||||
|
node2.set_data("new data".into());
|
||||||
|
});
|
||||||
|
// wait for t to finish
|
||||||
|
t.join().unwrap();
|
||||||
|
{
|
||||||
|
let node2 = tree.children().nth(2).unwrap();
|
||||||
|
let data = node2.get_data().unwrap();
|
||||||
|
assert_eq!(data.as_str(), "new data");
|
||||||
|
node2.clear_data();
|
||||||
|
// re-use `data` after node data was cleared
|
||||||
|
assert_eq!(data.as_str(), "new data");
|
||||||
|
}
|
||||||
|
let thread_tree = tree.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let node2 = thread_tree.children().nth(2).unwrap();
|
||||||
|
assert_eq!(node2.get_data(), None);
|
||||||
|
})
|
||||||
|
.join()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore)]
|
||||||
|
fn sync() {
|
||||||
|
let tree = two_level_tree();
|
||||||
|
let tree = build_tree::<()>(&tree);
|
||||||
|
let thread_tree = &tree;
|
||||||
|
let result = scope(move |s| {
|
||||||
|
s.spawn(move |_| {
|
||||||
|
let leaf1_0 = thread_tree
|
||||||
|
.children()
|
||||||
|
.nth(1)
|
||||||
|
.unwrap()
|
||||||
|
.children_with_tokens()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
let leaf1_0 = leaf1_0.into_token().unwrap();
|
||||||
|
leaf1_0.resolve_text(thread_tree.resolver().as_ref()).to_string()
|
||||||
|
})
|
||||||
|
.join()
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
assert_eq!(result.unwrap(), "1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore)]
|
||||||
|
fn drop_send() {
|
||||||
|
let tree = two_level_tree();
|
||||||
|
let tree = build_tree::<()>(&tree);
|
||||||
|
let thread_tree = tree.clone();
|
||||||
|
let thread = thread::spawn(move || {
|
||||||
|
drop(thread_tree);
|
||||||
|
});
|
||||||
|
thread.join().unwrap();
|
||||||
|
thread::sleep(Duration::from_millis(500));
|
||||||
|
drop(tree);
|
||||||
|
|
||||||
|
let tree = two_level_tree();
|
||||||
|
let tree = build_tree::<()>(&tree);
|
||||||
|
let thread_tree = tree.clone();
|
||||||
|
drop(tree);
|
||||||
|
let thread = thread::spawn(move || {
|
||||||
|
thread::sleep(Duration::from_millis(500));
|
||||||
|
drop(thread_tree);
|
||||||
|
});
|
||||||
|
thread.join().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore)]
|
||||||
|
#[allow(clippy::drop_ref)]
|
||||||
|
fn drop_sync() {
|
||||||
|
let tree = two_level_tree();
|
||||||
|
let tree = build_tree::<()>(&tree);
|
||||||
|
let thread_tree = &tree;
|
||||||
|
scope(move |s| {
|
||||||
|
s.spawn(move |_| {
|
||||||
|
drop(thread_tree);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
thread::sleep(Duration::from_millis(500));
|
||||||
|
drop(tree);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue