Struct someday::Transaction

source ·
pub struct Transaction<'writer, T: Clone> { /* private fields */ }
Expand description

Mutate the data T directly without going through a Patch.

This structure is returned by Writer::tx, and can be seen as a temporary handle for mutating your data T.

§Mutable access to T

Transaction gives direct mutable access to the Writer’s inner data T via:

Each call to any of these functions will increment the Timestamp by 1, regardless if the data was changed or not.

§Drop

After Transaction has been Transaction::commit()’ed or drop()’ed:

  1. All previous Patch’s get cleared
  2. A Patch that simply clones all the data gets added

It is worth noting that this only happens if a mutable reference is created (even if it is not used).

§Transaction vs Patch

Using Transaction instead of Patch when you are just cloning data anyway may be preferred as it avoids:

  • Potential use of Box/Arc
  • Overhead of storing/re-applying Patch’s

Patch’s allow for turning cheaply reclaimed old Reader data back into a viable copy, however, if your Patch is simply cloning the data anyway, Transaction makes more sense.

§Example

// Create `Reader/Writer` pair of a `String`.
let (reader, mut writer) = someday::new(String::new());

// Open up a transaction.
let mut tx: Transaction<'_, String> = writer.tx();
// Each one of these is silently calling `deref_mut()`
// into the target `&mut String`, which increments the
// timestamp each call, so in total, 4 times.
tx.push_str("hello");
tx.push_str(" ");
tx.push_str("world");
tx.push_str("!");

// We started with a timestamp of 0,
// and after mutating a bit, are now at 4.
assert_eq!(tx.original_timestamp(), 0);
assert_eq!(tx.current_timestamp(), 4);

// Finish the transaction by dropping,
// we don't want the `CommitInfo` data
// from `Transaction::commit()`.
drop(tx);
// We can see dropping the `Transaction` added
// a `Patch` - this just clones the data.
assert_eq!(writer.staged().len(), 1);

// Our changes were applied
// to the `Writer` data directly.
assert_eq!(writer.data(), "hello world!");
assert_eq!(writer.timestamp(), 4);
// Although, we haven't `push()`'ed yet,
// so `Reader`'s still don't see changes.
assert_eq!(reader.head().data, "");
assert_eq!(reader.head().timestamp, 0);

// `Reader`'s can see our changes after `push()`.
writer.push();
assert_eq!(reader.head().data, "hello world!");
assert_eq!(reader.head().timestamp, 4);

Implementations§

source§

impl<'writer, T: Clone> Transaction<'writer, T>

source

pub fn new(writer: &'writer mut Writer<T>) -> Transaction<'writer, T>

Create a new Transaction associated with a Writer.

This is the same as Writer::tx.

source

pub fn data(&self) -> &T

Immutably borrow the Writer’s data T.

This will not increment the Timestamp.

source

pub fn data_mut(&mut self) -> &mut T

Mutably borrow the Writer’s data T.

Each call to this function will increment the Timestamp by 1, regardless if the data was changed or not.

All mutable borrow trait functions use this function internally, which means they also increase the timestamp.

source

pub fn writer(&self) -> &Writer<T>

Immutably borrow the Writer’s associated with this Transaction.

let (_, mut writer) = someday::new(String::new());

let mut tx = writer.tx();
let writer = tx.writer();

// We can access anything even while
// a `Transaction` is in-scope.
assert!(writer.data().is_empty());

// But not after it is actually being used.
tx.push_str("");
// writer.head();
source

pub const fn original_timestamp(&self) -> Timestamp

Get the original Timestamp of when this Transaction was created.

let (_, mut writer) = someday::new(String::new());

let mut tx = writer.tx();
tx.push_str(""); // 1
tx.push_str(""); // 2
tx.push_str(""); // 3
assert_eq!(tx.original_timestamp(), 0);

drop(tx);
assert_eq!(writer.timestamp(), 3);

let tx = writer.tx();
assert_eq!(tx.original_timestamp(), 3);
source

pub const fn current_timestamp(&self) -> Timestamp

Get the current Timestamp of the Writer associated with this Transaction.

let (_, mut writer) = someday::new(String::new());

let mut tx = writer.tx();
tx.push_str(""); // 1
tx.push_str(""); // 2
tx.push_str(""); // 3

assert_eq!(tx.current_timestamp(), 3);
assert_eq!(tx.original_timestamp(), 0);
source

pub fn commit(self) -> CommitInfo

Return information about the changes made and complete the Transaction.

This is the same as drop()’ing the Transaction, except it will return a CommitInfo.

CommitInfo::patches in this case will represent how many times the Transaction was mutably referenced.

let (_, mut writer) = someday::new(String::new());

let mut tx = writer.tx();
tx.push_str(""); // 1
tx.push_str(""); // 2
tx.push_str(""); // 3
let commit_info = tx.commit();

assert_eq!(commit_info.patches, 3);
source

pub fn abort(self) -> Result<(), Self>

Attempt to abort the Transaction.

This cancels the Transaction and returns Ok(()) if no mutable references to T were created.

§Errors

If a mutable reference to T was created with Transaction::data_mut, this will return self back inside Err.

§Example
let (_, mut writer) = someday::new(String::new());

//---------- No changes made, abort is ok
let mut tx = writer.tx();
assert!(tx.abort().is_ok());
assert_eq!(writer.data(), "");
assert_eq!(writer.timestamp(), 0);
assert_eq!(writer.staged().len(), 0);

//---------- `T` was mutated, abort fails
let mut tx = writer.tx();
tx.push_str("");
assert!(tx.abort().is_err());

//---------- Mutable reference was created, abort fails
let mut tx = writer.tx();
tx.data_mut();
assert!(tx.abort().is_err());

Trait Implementations§

source§

impl<T: Clone> AsMut<T> for Transaction<'_, T>

source§

fn as_mut(&mut self) -> &mut T

Converts this type into a mutable reference of the (usually inferred) input type.
source§

impl<T: Clone> AsRef<T> for Transaction<'_, T>

source§

fn as_ref(&self) -> &T

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<T: Clone> Borrow<T> for Transaction<'_, T>

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T: Clone> BorrowMut<T> for Transaction<'_, T>

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T: Clone> Deref for Transaction<'_, T>

§

type Target = T

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<T: Clone> DerefMut for Transaction<'_, T>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<T: Clone> Drop for Transaction<'_, T>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'writer, T> !RefUnwindSafe for Transaction<'writer, T>

§

impl<'writer, T> Send for Transaction<'writer, T>
where T: Sync + Send,

§

impl<'writer, T> !Sync for Transaction<'writer, T>

§

impl<'writer, T> Unpin for Transaction<'writer, T>

§

impl<'writer, T> !UnwindSafe for Transaction<'writer, T>

Blanket Implementations§

source§

impl<T, A, P> Access<T> for P
where A: Access<T> + ?Sized, P: Deref<Target = A>,

§

type Guard = <A as Access<T>>::Guard

A guard object containing the value and keeping it alive. Read more
source§

fn load(&self) -> <P as Access<T>>::Guard

The loading method. Read more
source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T, A> DynAccess<T> for A
where A: Access<T>, <A as Access<T>>::Guard: 'static,

source§

fn load(&self) -> DynGuard<T>

The equivalent of Access::load.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.