From 64106c4d3d4ddba8c7bc2af75376e6d3d3d75601 Mon Sep 17 00:00:00 2001
From:
Date: Mon, 29 Jun 2015 20:16:15 +0000
Subject: Update documentation
---
src/carboxyl/transaction.rs.html | 459 +++++++++++++++++++++++++++++++++++++++
1 file changed, 459 insertions(+)
create mode 100644 src/carboxyl/transaction.rs.html
(limited to 'src/carboxyl/transaction.rs.html')
diff --git a/src/carboxyl/transaction.rs.html b/src/carboxyl/transaction.rs.html
new file mode 100644
index 0000000..e9cc7b6
--- /dev/null
+++ b/src/carboxyl/transaction.rs.html
@@ -0,0 +1,459 @@
+
+
+
+ 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
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+
+
+
+
+
+
+use std::sync::Mutex;
+use std::cell::RefCell;
+use std::boxed::FnBox;
+
+
+
+
+
+
+lazy_static! {
+ static ref TRANSACTION_MUTEX: Mutex<()> = Mutex::new(());
+}
+
+
+thread_local!(
+ static CURRENT_TRANSACTION: RefCell<Option<Transaction>> =
+ RefCell::new(None)
+);
+
+
+
+type Callback = Box<FnBox() + 'static>;
+
+
+
+pub struct Transaction {
+ intermediate: Vec<Callback>,
+ finalizers: Vec<Callback>,
+}
+
+impl Transaction {
+
+ fn new() -> Transaction {
+ Transaction {
+ intermediate: vec![],
+ finalizers: vec![],
+ }
+ }
+
+
+
+ pub fn later<F: FnOnce() + 'static>(&mut self, callback: F) {
+ self.intermediate.push(Box::new(callback));
+ }
+
+
+
+
+ pub fn end<F: FnOnce() + 'static>(&mut self, callback: F) {
+ self.finalizers.push(Box::new(callback));
+ }
+
+
+ fn advance(&mut self) -> Vec<Callback> {
+ use std::mem;
+ let mut intermediate = vec![];
+ mem::swap(&mut intermediate, &mut self.intermediate);
+ intermediate
+ }
+
+
+ fn finalize(self) {
+ for finalizer in self.finalizers {
+ finalizer.call_box(());
+ }
+ }
+}
+
+
+
+
+
+
+
+pub fn commit<A, F: FnOnce() -> A>(body: F) -> A {
+ use std::mem;
+
+ let mut prev = CURRENT_TRANSACTION.with(|current| {
+ let mut prev = Some(Transaction::new());
+ mem::swap(&mut prev, &mut current.borrow_mut());
+ prev
+ });
+
+ let _lock = match prev {
+ None => Some(TRANSACTION_MUTEX.lock().ok()
+ .expect("global transaction mutex poisoned")
+ ),
+ Some(_) => None,
+ };
+
+ let result = body();
+
+ loop {
+ let callbacks = with_current(Transaction::advance);
+ if callbacks.is_empty() { break }
+ for callback in callbacks {
+ callback.call_box(());
+ }
+ }
+
+ CURRENT_TRANSACTION.with(|current|
+ mem::swap(&mut prev, &mut current.borrow_mut())
+ );
+ prev.unwrap().finalize();
+
+ result
+}
+
+
+
+pub fn with_current<A, F: FnOnce(&mut Transaction) -> A>(action: F) -> A {
+ CURRENT_TRANSACTION.with(|current|
+ match &mut *current.borrow_mut() {
+ &mut Some(ref mut trans) => action(trans),
+ _ => panic!("there is no active transaction to register a callback"),
+ }
+ )
+}
+
+pub fn later<F: FnOnce() + 'static>(action: F) {
+ with_current(|c| c.later(action))
+}
+
+pub fn end<F: FnOnce() + 'static>(action: F) {
+ with_current(|c| c.end(action))
+}
+
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn commit_single() {
+ let mut v = 3;
+ commit(|| v += 5);
+ assert_eq!(v, 8);
+ }
+
+ #[test]
+ fn commit_nested() {
+ let mut v = 3;
+ commit(|| {
+ commit(|| v *= 2);
+ v += 4;
+ });
+ assert_eq!(v, 10);
+ }
+
+ #[test]
+ fn commits_parallel() {
+ use std::sync::{Arc, Mutex};
+ use std::thread;
+
+
+ let v = Arc::new(Mutex::new(3));
+
+ let guards: Vec<_> = (0..3)
+ .map(|_| {
+ let v = v.clone();
+ thread::spawn(move || commit(move || {
+
+
+ *v.lock().unwrap() *= 2;
+
+ thread::sleep_ms(1);
+ *v.lock().unwrap() -= 1;
+ }))
+ })
+ .collect();
+
+ for guard in guards { guard.join().ok().expect("thread failed"); }
+
+ assert_eq!(&*v.lock().unwrap(), &17);
+ }
+}
+
+
+