1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
//! A concurrency library for high concurrency reads with a single writer. //! //! This library is named after the 2 (identical) tables that we hold //! internally: //! - Active - this is the table that all Readers view. This table will never be //! write locked, so readers never face contention. //! - Standby - this is the table the the Writer mutates. A writer should face //! minimal contention retrieving this table for mutation since Readers move //! to reading the Active table when they are swapped. //! //! The cost of providing no contention to readers, and minimal contention to //! writers is: //! 1. Memory - Internally we hold 2 copies of the underlying type the user //! created. This is needed to allow there to always be a table that Readers //! can check out without contention. //! 2. Writer thread CPU usage - The writer must apply all updates twice, once //! to each table. Lock contention for the writer should be less than with a //! plain RwLock due to Readers using the active_table. //! //! The usage is meant to be similar to a RwLock. Instead of multiple threads //! holding an RwLock though and calling read/write, there is a single Writer //! that acquire a write guard to the tables, and N Readers which can acquire //! read guards to the tables. Some of the inspiration came from the left_right //! crate, so feel free to check that out. We don't implement aliasing, so each //! table is a true deepcopy of the other. We also don't optimize for startup. //! //! Minimizing lock contention also makes batching a more effective strategy for //! Reader performance. Now you can grab a ReadGuard, and handle multiple //! requests without worrying about starving the writer since it will be able to //! work on the standby table. This means multiple requests can be handled //! without having to relock the active_table. Similarly you can batch with the //! Writer without starving the Readers. //! //! Creation is done through the Writer, which can then spawn Readers (Readers //! are clonable). //! //! We provide 2 modules: //! 1. primitives - these are building blocks that can be used similarly to a //! RwLock. //! 2. collections - these are common collections that use primitives to offer //! users an interface very similar to the collections themselves, but //! conforming to the requirements of active_standby. //! //! For examples, check out the tests from the collections. mod read; mod table; mod write; pub mod primitives { pub use crate::read::{ReadGuard, Reader}; pub use crate::write::{SendWriteGuard, SendWriter, UpdateTables, WriteGuard, Writer}; } mod btreemap; mod btreeset; mod hashmap; mod hashset; mod vec; pub mod collections { pub use crate::btreemap::btreemap; pub use crate::btreeset::btreeset; pub use crate::hashmap::hashmap; pub use crate::hashset::hashset; pub use crate::vec::vec; }