Skip to main content

fifo/
fifo.rs

1//   Copyright 2015 Colin Sherratt
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15extern crate atom;
16
17use atom::*;
18use std::mem;
19use std::sync::{atomic::Ordering, Arc, Barrier};
20use std::thread;
21
22const THREADS: usize = 100;
23
24#[derive(Debug)]
25struct Link {
26    next: AtomSetOnce<Box<Link>>,
27}
28
29impl Drop for Link {
30    fn drop(&mut self) {
31        // This is done to avoid a recusive drop of the List
32        while let Some(mut h) = self.next.atom().take(Ordering::Acquire) {
33            self.next = mem::replace(&mut h.next, AtomSetOnce::empty());
34        }
35    }
36}
37
38fn main() {
39    let b = Arc::new(Barrier::new(THREADS + 1));
40
41    let head = Arc::new(Link {
42        next: AtomSetOnce::empty(),
43    });
44
45    for _ in 0..THREADS {
46        let b = b.clone();
47        let head = head.clone();
48        thread::spawn(move || {
49            let mut hptr = &*head;
50
51            for _ in 0..10_000 {
52                let mut my_awesome_node = Box::new(Link {
53                    next: AtomSetOnce::empty(),
54                });
55
56                loop {
57                    while let Some(h) = hptr.next.get(Ordering::Acquire) {
58                        hptr = h;
59                    }
60
61                    my_awesome_node =
62                        match hptr.next.set_if_none(my_awesome_node, Ordering::Release) {
63                            Some(v) => v,
64                            None => break,
65                        };
66                }
67            }
68            b.wait();
69        });
70    }
71
72    b.wait();
73
74    let mut hptr = &*head;
75    let mut count = 0;
76    while let Some(h) = hptr.next.get(Ordering::Acquire) {
77        hptr = h;
78        count += 1;
79    }
80    println!(
81        "Using {} threads we wrote {} links at the same time!",
82        THREADS, count
83    );
84}