From 55ff13b84a2fc8f5c8c1c2baae7c4286ce7fb09d Mon Sep 17 00:00:00 2001 From: chrism Date: Sun, 12 Jan 2025 13:53:21 -0500 Subject: [PATCH 1/4] Add multithreaded example --- examples/multithread.rs | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 examples/multithread.rs diff --git a/examples/multithread.rs b/examples/multithread.rs new file mode 100644 index 00000000..d618ab86 --- /dev/null +++ b/examples/multithread.rs @@ -0,0 +1,52 @@ +use redb::TableHandle; +use redb::{Database, Error, TableDefinition}; +use std::{sync::Arc, thread, time::Duration}; + +fn main() -> Result<(), Error> { + let db = Database::create("my_db.redb")?; + let definition: TableDefinition<&str, u32> = TableDefinition::new("my_data"); + + let db = Arc::new(db); + + let threads = 10; + let mut handles = Vec::with_capacity(threads); + for i in 0..threads { + let db = db.clone(); + let a = std::thread::spawn(move || -> Result<(), Error> { + // Sleep a little bit to add some non-determinism to execution order + thread::sleep(Duration::from_millis(100)); + let write_txn = db.begin_write()?; + { + let mut table = write_txn.open_table(definition)?; + table.insert(&i.to_string().as_str(), i as u32)?; + // The resulting table should have a different "a" value each time this example is run + table.insert("a".to_string().as_str(), i as u32)?; + } + write_txn.commit()?; + Ok(()) + }); + handles.push(a); + } + // See if there any errors were returned from the threads + for handle in handles { + if let Err(e) = handle.join() { + println!("{:?}", e) + } + } + + // Check that the `Database` has the table (and only the table) that we created + let read_txn = db.begin_read()?; + let tables = read_txn.list_tables()?; + for table in tables { + println!("Table: {}", table.name()); + let _d = TableDefinition::<&str, u32>::new(table.name()); + } + + // Print every (key, value) pair in the table + let table = read_txn.open_table(definition)?; + for (k, v) in table.range("0"..)?.flatten() { + println!("{:?}, {:?}", k.value(), v.value()); + } + + Ok(()) +} From fe469bb127c44d7ae4b0ea43db5f68ffe7db4018 Mon Sep 17 00:00:00 2001 From: chrism Date: Sat, 1 Feb 2025 22:40:50 -0500 Subject: [PATCH 2/4] Update to multiple readers and writers --- examples/multithread.rs | 59 +++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/examples/multithread.rs b/examples/multithread.rs index d618ab86..8098c792 100644 --- a/examples/multithread.rs +++ b/examples/multithread.rs @@ -1,5 +1,6 @@ use redb::TableHandle; use redb::{Database, Error, TableDefinition}; +use std::time::Instant; use std::{sync::Arc, thread, time::Duration}; fn main() -> Result<(), Error> { @@ -7,26 +8,56 @@ fn main() -> Result<(), Error> { let definition: TableDefinition<&str, u32> = TableDefinition::new("my_data"); let db = Arc::new(db); + // Seed the database with some information + let write_txn = db.begin_write()?; + { + let mut table = write_txn.open_table(definition)?; + table.insert(&0.to_string().as_str(), 0 as u32)?; + // The resulting table should have a different "a" value each time this example is run + table.insert("a".to_string().as_str(), 0 as u32)?; + } + write_txn.commit()?; + + let read_threads = 8; + let write_threads = 2; + let mut handles = Vec::with_capacity(read_threads + write_threads); + for i in 0..read_threads { + let db = db.clone(); + let h = std::thread::spawn(move || -> Result<(), Error> { + let start = Instant::now(); + while start.elapsed() < Duration::from_millis(100) { + let read_txn = db.begin_read()?; + // Print every (key, value) pair in the table + let table = read_txn.open_table(definition)?; + for (k, v) in table.range("0"..)?.flatten() { + println!("From read_thread #{}: {:?}, {:?}", i, k.value(), v.value()); + } + } + Ok(()) + }); + handles.push(h); + } - let threads = 10; - let mut handles = Vec::with_capacity(threads); - for i in 0..threads { + for i in 0..write_threads { let db = db.clone(); - let a = std::thread::spawn(move || -> Result<(), Error> { - // Sleep a little bit to add some non-determinism to execution order - thread::sleep(Duration::from_millis(100)); - let write_txn = db.begin_write()?; - { - let mut table = write_txn.open_table(definition)?; - table.insert(&i.to_string().as_str(), i as u32)?; - // The resulting table should have a different "a" value each time this example is run - table.insert("a".to_string().as_str(), i as u32)?; + let h = std::thread::spawn(move || -> Result<(), Error> { + let start = Instant::now(); + while start.elapsed() < Duration::from_millis(100) { + let write_txn = db.begin_write()?; + { + let mut table = write_txn.open_table(definition)?; + table.insert(&i.to_string().as_str(), i as u32)?; + // The resulting table should have a different "a" value each time this example is run + table.insert("a".to_string().as_str(), i as u32)?; + println!("Inserted data from write_thread #{}", i); + } + write_txn.commit()?; } - write_txn.commit()?; Ok(()) }); - handles.push(a); + handles.push(h); } + // See if there any errors were returned from the threads for handle in handles { if let Err(e) = handle.join() { From b61afe6542a138f68cf432aea9ed53924b13575c Mon Sep 17 00:00:00 2001 From: chrism Date: Sun, 2 Feb 2025 13:03:16 -0500 Subject: [PATCH 3/4] Remove unused import --- examples/multithread.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/multithread.rs b/examples/multithread.rs index 8098c792..ac13c76d 100644 --- a/examples/multithread.rs +++ b/examples/multithread.rs @@ -1,7 +1,7 @@ use redb::TableHandle; use redb::{Database, Error, TableDefinition}; use std::time::Instant; -use std::{sync::Arc, thread, time::Duration}; +use std::{sync::Arc, time::Duration}; fn main() -> Result<(), Error> { let db = Database::create("my_db.redb")?; From 59dcd39664f65dbd64c19e802b5b7940ae924c6a Mon Sep 17 00:00:00 2001 From: chrism Date: Sun, 2 Feb 2025 17:26:50 -0500 Subject: [PATCH 4/4] Try to satisfy clippy --- examples/multithread.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/multithread.rs b/examples/multithread.rs index ac13c76d..8550f8dd 100644 --- a/examples/multithread.rs +++ b/examples/multithread.rs @@ -12,9 +12,9 @@ fn main() -> Result<(), Error> { let write_txn = db.begin_write()?; { let mut table = write_txn.open_table(definition)?; - table.insert(&0.to_string().as_str(), 0 as u32)?; + table.insert(&0.to_string().as_str(), 0_u32)?; // The resulting table should have a different "a" value each time this example is run - table.insert("a".to_string().as_str(), 0 as u32)?; + table.insert("a".to_string().as_str(), 0_u32)?; } write_txn.commit()?;