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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
//! A crate providing lock-free data structures and a solution for the "ABA //! problem" related to pointers. //! //! The incinerator is the API which tries to solve the "ABA problem" when //! related to pointer dropping. With incinerator, every thread has a local //! deletion queue. Dropping a shared consist of first removing the pointer //! from the shared context, then adding the pointer to the local queue. Then, //! a global counter is checked. If the counter is zero, then the whole queue //! is deleted, otherwise, the queue will only be deleted later. //! //! This counter is counting how many times the incinerator was asked to //! "pause". A thread may pause the incinerator to load and use the shared //! pointer, and this is why it is important to remove the pointer from the //! shared context before deleting. //! //! This crate is under development, and there are plans for some structures. //! We have: //! - [x] Stack //! - [x] Queue //! - [ ] Deque //! - [ ] Map //! - [ ] Set /// Provides convenient re-exports. pub mod prelude; /// Incinerator API. The purpouse of this module is to solve the "ABA problem" /// related to pointers while still being lock-free. Incinerator is a garbage /// deleter which does not necessarilly deletes all garbage at the moment it /// was added to the queue, i.e. it can be paused while still not-blocking any /// thread. /// # Example /// ```rust /// extern crate lockfree; /// /// use lockfree::prelude::*; /// use std::{ /// ptr::{null_mut, NonNull}, /// sync::{Arc, atomic::{AtomicPtr, Ordering::*}}, /// thread, /// }; /// /// unsafe fn create_ptr<T>(val: T) -> NonNull<T> { /// NonNull::new_unchecked(Box::into_raw(Box::new(val))) /// } /// /// unsafe fn drop_ptr<T>(ptr: NonNull<T>) { /// Box::from_raw(ptr.as_ptr()); /// } /// /// let ptr = unsafe { create_ptr(55).as_ptr() }; /// let dummy_state = Arc::new(AtomicPtr::new(ptr)); /// /// let mut threads = Vec::with_capacity(16); /// /// for i in 0..16 { /// let state = dummy_state.clone(); /// threads.push(thread::spawn(move || { /// let ptr = incinerator::pause(|| { /// let loaded = state.load(SeqCst); /// let new = if let Some(num) = unsafe { loaded.as_ref() } { /// i + num /// } else { /// i /// }; /// state.swap(unsafe { create_ptr(new).as_ptr() }, SeqCst) /// }); /// /// if let Some(nnptr) = NonNull::new(ptr) { /// // dropping /// unsafe { incinerator::add(nnptr, drop_ptr) } /// } /// })); /// } /// /// for thread in threads { /// thread.join().unwrap(); /// } /// /// if let Some(ptr) = NonNull::new(dummy_state.load(SeqCst)) { /// assert!(unsafe { *ptr.as_ref() } <= 15 * 15); /// unsafe { drop_ptr(ptr) } /// } /// ``` pub mod incinerator; /// A lock-free queue. pub mod queue; /// A lock-free stack. pub mod stack; /// Provides a doubly atomic reference counter. pub mod darc; #[allow(dead_code)] mod alloc;