summary refs log tree commit diff
path: root/src/libstd/collections
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-11-14 14:20:57 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-11-23 23:37:16 -0800
commita9c1152c4bf72132806cb76045b3464d59db07da (patch)
tree89ba92d5f5788e3323b75ca003bf74661a94e4de /src/libstd/collections
parent4e5259503cd8aac9905c7ac6d68d0c4caab1d28c (diff)
downloadrust-a9c1152c4bf72132806cb76045b3464d59db07da.tar.gz
rust-a9c1152c4bf72132806cb76045b3464d59db07da.zip
std: Add a new top-level thread_local module
This commit removes the `std::local_data` module in favor of a new
`std::thread_local` module providing thread local storage. The module provides
two variants of TLS: one which owns its contents and one which is based on
scoped references. Each implementation has pros and cons listed in the
documentation.

Both flavors have accessors through a function called `with` which yield a
reference to a closure provided. Both flavors also panic if a reference cannot
be yielded and provide a function to test whether an access would panic or not.
This is an implementation of [RFC 461][rfc] and full details can be found in
that RFC.

This is a breaking change due to the removal of the `std::local_data` module.
All users can migrate to the new thread local system like so:

    thread_local!(static FOO: Rc<RefCell<Option<T>>> = Rc::new(RefCell::new(None)))

The old `local_data` module inherently contained the `Rc<RefCell<Option<T>>>` as
an implementation detail which must now be explicitly stated by users.

[rfc]: https://github.com/rust-lang/rfcs/pull/461
[breaking-change]
Diffstat (limited to 'src/libstd/collections')
-rw-r--r--src/libstd/collections/hash/map.rs133
1 files changed, 72 insertions, 61 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 69375e8d4f8..662ae913764 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1471,7 +1471,7 @@ mod test_map {
         assert_eq!(*m.get(&2).unwrap(), 4);
     }
 
-    local_data_key!(drop_vector: RefCell<Vec<int>>)
+    thread_local!(static DROP_VECTOR: RefCell<Vec<int>> = RefCell::new(Vec::new()))
 
     #[deriving(Hash, PartialEq, Eq)]
     struct Dropable {
@@ -1480,8 +1480,9 @@ mod test_map {
 
     impl Dropable {
         fn new(k: uint) -> Dropable {
-            let v = drop_vector.get().unwrap();
-            v.borrow_mut().as_mut_slice()[k] += 1;
+            DROP_VECTOR.with(|slot| {
+                slot.borrow_mut()[k] += 1;
+            });
 
             Dropable { k: k }
         }
@@ -1489,8 +1490,9 @@ mod test_map {
 
     impl Drop for Dropable {
         fn drop(&mut self) {
-            let v = drop_vector.get().unwrap();
-            v.borrow_mut().as_mut_slice()[self.k] -= 1;
+            DROP_VECTOR.with(|slot| {
+                slot.borrow_mut()[self.k] -= 1;
+            });
         }
     }
 
@@ -1502,16 +1504,18 @@ mod test_map {
 
     #[test]
     fn test_drops() {
-        drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i))));
+        DROP_VECTOR.with(|slot| {
+            *slot.borrow_mut() = Vec::from_elem(200, 0i);
+        });
 
         {
             let mut m = HashMap::new();
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 0);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow().as_slice()[i], 0);
+                }
+            });
 
             for i in range(0u, 100) {
                 let d1 = Dropable::new(i);
@@ -1519,11 +1523,11 @@ mod test_map {
                 m.insert(d1, d2);
             }
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow().as_slice()[i], 1);
+                }
+            });
 
             for i in range(0u, 50) {
                 let k = Dropable::new(i);
@@ -1531,41 +1535,46 @@ mod test_map {
 
                 assert!(v.is_some());
 
-                let v = drop_vector.get().unwrap();
-                assert_eq!(v.borrow().as_slice()[i], 1);
-                assert_eq!(v.borrow().as_slice()[i+100], 1);
+                DROP_VECTOR.with(|v| {
+                    assert_eq!(v.borrow().as_slice()[i], 1);
+                    assert_eq!(v.borrow().as_slice()[i+100], 1);
+                });
             }
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 50) {
-                assert_eq!(v.borrow().as_slice()[i], 0);
-                assert_eq!(v.borrow().as_slice()[i+100], 0);
-            }
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 50) {
+                    assert_eq!(v.borrow().as_slice()[i], 0);
+                    assert_eq!(v.borrow().as_slice()[i+100], 0);
+                }
 
-            for i in range(50u, 100) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-                assert_eq!(v.borrow().as_slice()[i+100], 1);
-            }
+                for i in range(50u, 100) {
+                    assert_eq!(v.borrow().as_slice()[i], 1);
+                    assert_eq!(v.borrow().as_slice()[i+100], 1);
+                }
+            });
         }
 
-        let v = drop_vector.get().unwrap();
-        for i in range(0u, 200) {
-            assert_eq!(v.borrow().as_slice()[i], 0);
-        }
+        DROP_VECTOR.with(|v| {
+            for i in range(0u, 200) {
+                assert_eq!(v.borrow().as_slice()[i], 0);
+            }
+        });
     }
 
     #[test]
     fn test_move_iter_drops() {
-        drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i))));
+        DROP_VECTOR.with(|v| {
+            *v.borrow_mut() = Vec::from_elem(200, 0i);
+        });
 
         let hm = {
             let mut hm = HashMap::new();
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 0);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow().as_slice()[i], 0);
+                }
+            });
 
             for i in range(0u, 100) {
                 let d1 = Dropable::new(i);
@@ -1573,11 +1582,11 @@ mod test_map {
                 hm.insert(d1, d2);
             }
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow().as_slice()[i], 1);
+                }
+            });
 
             hm
         };
@@ -1588,31 +1597,33 @@ mod test_map {
         {
             let mut half = hm.into_iter().take(50);
 
-            let v = drop_vector.get().unwrap();
-            for i in range(0u, 200) {
-                assert_eq!(v.borrow().as_slice()[i], 1);
-            }
-            drop(v);
+            DROP_VECTOR.with(|v| {
+                for i in range(0u, 200) {
+                    assert_eq!(v.borrow().as_slice()[i], 1);
+                }
+            });
 
             for _ in half {}
 
-            let v = drop_vector.get().unwrap();
-            let nk = range(0u, 100).filter(|&i| {
-                v.borrow().as_slice()[i] == 1
-            }).count();
+            DROP_VECTOR.with(|v| {
+                let nk = range(0u, 100).filter(|&i| {
+                    v.borrow().as_slice()[i] == 1
+                }).count();
 
-            let nv = range(0u, 100).filter(|&i| {
-                v.borrow().as_slice()[i+100] == 1
-            }).count();
+                let nv = range(0u, 100).filter(|&i| {
+                    v.borrow().as_slice()[i+100] == 1
+                }).count();
 
-            assert_eq!(nk, 50);
-            assert_eq!(nv, 50);
+                assert_eq!(nk, 50);
+                assert_eq!(nv, 50);
+            });
         };
 
-        let v = drop_vector.get().unwrap();
-        for i in range(0u, 200) {
-            assert_eq!(v.borrow().as_slice()[i], 0);
-        }
+        DROP_VECTOR.with(|v| {
+            for i in range(0u, 200) {
+                assert_eq!(v.borrow().as_slice()[i], 0);
+            }
+        });
     }
 
     #[test]