Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  select.rs

  Sprache: Rust
 

//! Tests for channel selection using the `Select` struct.

use std::any::Any;
use std::cell::Cell;
use std::thread;
use std::time::{Duration, Instant};

use crossbeam_channel::{after, bounded, tick, unbounded, Receiver, Select, TryRecvError};
use crossbeam_utils::thread::scope;

fn ms(ms: u64) -> Duration {
    Duration::from_millis(ms)
}

#[test]
fn smoke1() {
    let (s1, r1) = unbounded::<usize>();
    let (s2, r2) = unbounded::<usize>();

    s1.send(1).unwrap();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r1);
    let oper2 = sel.recv(&r2);
    let oper = sel.select();
    match oper.index() {
        i if i == oper1 => assert_eq!(oper.recv(&r1), Ok(1)),
        i if i == oper2 => panic!(),
        _ => unreachable!(),
    }

    s2.send(2).unwrap();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r1);
    let oper2 = sel.recv(&r2);
    let oper = sel.select();
    match oper.index() {
        i if i == oper1 => panic!(),
        i if i == oper2 => assert_eq!(oper.recv(&r2), Ok(2)),
        _ => unreachable!(),
    }
}

#[test]
fn smoke2() {
    let (_s1, r1) = unbounded::<i32>();
    let (_s2, r2) = unbounded::<i32>();
    let (_s3, r3) = unbounded::<i32>();
    let (_s4, r4) = unbounded::<i32>();
    let (s5, r5) = unbounded::<i32>();

    s5.send(5).unwrap();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r1);
    let oper2 = sel.recv(&r2);
    let oper3 = sel.recv(&r3);
    let oper4 = sel.recv(&r4);
    let oper5 = sel.recv(&r5);
    let oper = sel.select();
    match oper.index() {
        i if i == oper1 => panic!(),
        i if i == oper2 => panic!(),
        i if i == oper3 => panic!(),
        i if i == oper4 => panic!(),
        i if i == oper5 => assert_eq!(oper.recv(&r5), Ok(5)),
        _ => unreachable!(),
    }
}

#[test]
fn disconnected() {
    let (s1, r1) = unbounded::<i32>();
    let (s2, r2) = unbounded::<i32>();

    scope(|scope| {
        scope.spawn(|_| {
            drop(s1);
            thread::sleep(ms(500));
            s2.send(5).unwrap();
        });

        let mut sel = Select::new();
        let oper1 = sel.recv(&r1);
        let oper2 = sel.recv(&r2);
        let oper = sel.select_timeout(ms(1000));
        match oper {
            Err(_) => panic!(),
            Ok(oper) => match oper.index() {
                i if i == oper1 => assert!(oper.recv(&r1).is_err()),
                i if i == oper2 => panic!(),
                _ => unreachable!(),
            },
        }

        r2.recv().unwrap();
    })
    .unwrap();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r1);
    let oper2 = sel.recv(&r2);
    let oper = sel.select_timeout(ms(1000));
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            i if i == oper1 => assert!(oper.recv(&r1).is_err()),
            i if i == oper2 => panic!(),
            _ => unreachable!(),
        },
    }

    scope(|scope| {
        scope.spawn(|_| {
            thread::sleep(ms(500));
            drop(s2);
        });

        let mut sel = Select::new();
        let oper1 = sel.recv(&r2);
        let oper = sel.select_timeout(ms(1000));
        match oper {
            Err(_) => panic!(),
            Ok(oper) => match oper.index() {
                i if i == oper1 => assert!(oper.recv(&r2).is_err()),
                _ => unreachable!(),
            },
        }
    })
    .unwrap();
}

#[test]
fn default() {
    let (s1, r1) = unbounded::<i32>();
    let (s2, r2) = unbounded::<i32>();

    let mut sel = Select::new();
    let _oper1 = sel.recv(&r1);
    let _oper2 = sel.recv(&r2);
    let oper = sel.try_select();
    match oper {
        Err(_) => {}
        Ok(_) => panic!(),
    }

    drop(s1);

    let mut sel = Select::new();
    let oper1 = sel.recv(&r1);
    let oper2 = sel.recv(&r2);
    let oper = sel.try_select();
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            i if i == oper1 => assert!(oper.recv(&r1).is_err()),
            i if i == oper2 => panic!(),
            _ => unreachable!(),
        },
    }

    s2.send(2).unwrap();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r2);
    let oper = sel.try_select();
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            i if i == oper1 => assert_eq!(oper.recv(&r2), Ok(2)),
            _ => unreachable!(),
        },
    }

    let mut sel = Select::new();
    let _oper1 = sel.recv(&r2);
    let oper = sel.try_select();
    match oper {
        Err(_) => {}
        Ok(_) => panic!(),
    }

    let mut sel = Select::new();
    let oper = sel.try_select();
    match oper {
        Err(_) => {}
        Ok(_) => panic!(),
    }
}

#[test]
fn timeout() {
    let (_s1, r1) = unbounded::<i32>();
    let (s2, r2) = unbounded::<i32>();

    scope(|scope| {
        scope.spawn(|_| {
            thread::sleep(ms(1500));
            s2.send(2).unwrap();
        });

        let mut sel = Select::new();
        let oper1 = sel.recv(&r1);
        let oper2 = sel.recv(&r2);
        let oper = sel.select_timeout(ms(1000));
        match oper {
            Err(_) => {}
            Ok(oper) => match oper.index() {
                i if i == oper1 => panic!(),
                i if i == oper2 => panic!(),
                _ => unreachable!(),
            },
        }

        let mut sel = Select::new();
        let oper1 = sel.recv(&r1);
        let oper2 = sel.recv(&r2);
        let oper = sel.select_timeout(ms(1000));
        match oper {
            Err(_) => panic!(),
            Ok(oper) => match oper.index() {
                i if i == oper1 => panic!(),
                i if i == oper2 => assert_eq!(oper.recv(&r2), Ok(2)),
                _ => unreachable!(),
            },
        }
    })
    .unwrap();

    scope(|scope| {
        let (s, r) = unbounded::<i32>();

        scope.spawn(move |_| {
            thread::sleep(ms(500));
            drop(s);
        });

        let mut sel = Select::new();
        let oper = sel.select_timeout(ms(1000));
        match oper {
            Err(_) => {
                let mut sel = Select::new();
                let oper1 = sel.recv(&r);
                let oper = sel.try_select();
                match oper {
                    Err(_) => panic!(),
                    Ok(oper) => match oper.index() {
                        i if i == oper1 => assert!(oper.recv(&r).is_err()),
                        _ => unreachable!(),
                    },
                }
            }
            Ok(_) => unreachable!(),
        }
    })
    .unwrap();
}

#[test]
fn default_when_disconnected() {
    let (_, r) = unbounded::<i32>();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r);
    let oper = sel.try_select();
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            i if i == oper1 => assert!(oper.recv(&r).is_err()),
            _ => unreachable!(),
        },
    }

    let (_, r) = unbounded::<i32>();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r);
    let oper = sel.select_timeout(ms(1000));
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            i if i == oper1 => assert!(oper.recv(&r).is_err()),
            _ => unreachable!(),
        },
    }

    let (s, _) = bounded::<i32>(0);

    let mut sel = Select::new();
    let oper1 = sel.send(&s);
    let oper = sel.try_select();
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            i if i == oper1 => assert!(oper.send(&s, 0).is_err()),
            _ => unreachable!(),
        },
    }

    let (s, _) = bounded::<i32>(0);

    let mut sel = Select::new();
    let oper1 = sel.send(&s);
    let oper = sel.select_timeout(ms(1000));
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            i if i == oper1 => assert!(oper.send(&s, 0).is_err()),
            _ => unreachable!(),
        },
    }
}

#[test]
fn default_only() {
    let start = Instant::now();

    let mut sel = Select::new();
    let oper = sel.try_select();
    assert!(oper.is_err());
    let now = Instant::now();
    assert!(now - start <= ms(50));

    let start = Instant::now();
    let mut sel = Select::new();
    let oper = sel.select_timeout(ms(500));
    assert!(oper.is_err());
    let now = Instant::now();
    assert!(now - start >= ms(450));
    assert!(now - start <= ms(550));
}

#[test]
fn unblocks() {
    let (s1, r1) = bounded::<i32>(0);
    let (s2, r2) = bounded::<i32>(0);

    scope(|scope| {
        scope.spawn(|_| {
            thread::sleep(ms(500));
            s2.send(2).unwrap();
        });

        let mut sel = Select::new();
        let oper1 = sel.recv(&r1);
        let oper2 = sel.recv(&r2);
        let oper = sel.select_timeout(ms(1000));
        match oper {
            Err(_) => panic!(),
            Ok(oper) => match oper.index() {
                i if i == oper1 => panic!(),
                i if i == oper2 => assert_eq!(oper.recv(&r2), Ok(2)),
                _ => unreachable!(),
            },
        }
    })
    .unwrap();

    scope(|scope| {
        scope.spawn(|_| {
            thread::sleep(ms(500));
            assert_eq!(r1.recv().unwrap(), 1);
        });

        let mut sel = Select::new();
        let oper1 = sel.send(&s1);
        let oper2 = sel.send(&s2);
        let oper = sel.select_timeout(ms(1000));
        match oper {
            Err(_) => panic!(),
            Ok(oper) => match oper.index() {
                i if i == oper1 => oper.send(&s1, 1).unwrap(),
                i if i == oper2 => panic!(),
                _ => unreachable!(),
            },
        }
    })
    .unwrap();
}

#[test]
fn both_ready() {
    let (s1, r1) = bounded(0);
    let (s2, r2) = bounded(0);

    scope(|scope| {
        scope.spawn(|_| {
            thread::sleep(ms(500));
            s1.send(1).unwrap();
            assert_eq!(r2.recv().unwrap(), 2);
        });

        for _ in 0..2 {
            let mut sel = Select::new();
            let oper1 = sel.recv(&r1);
            let oper2 = sel.send(&s2);
            let oper = sel.select();
            match oper.index() {
                i if i == oper1 => assert_eq!(oper.recv(&r1), Ok(1)),
                i if i == oper2 => oper.send(&s2, 2).unwrap(),
                _ => unreachable!(),
            }
        }
    })
    .unwrap();
}

#[test]
fn loop_try() {
    const RUNS: usize = 20;

    for _ in 0..RUNS {
        let (s1, r1) = bounded::<i32>(0);
        let (s2, r2) = bounded::<i32>(0);
        let (s_end, r_end) = bounded::<()>(0);

        scope(|scope| {
            scope.spawn(|_| loop {
                let mut done = false;

                let mut sel = Select::new();
                let oper1 = sel.send(&s1);
                let oper = sel.try_select();
                match oper {
                    Err(_) => {}
                    Ok(oper) => match oper.index() {
                        i if i == oper1 => {
                            let _ = oper.send(&s1, 1);
                            done = true;
                        }
                        _ => unreachable!(),
                    },
                }
                if done {
                    break;
                }

                let mut sel = Select::new();
                let oper1 = sel.recv(&r_end);
                let oper = sel.try_select();
                match oper {
                    Err(_) => {}
                    Ok(oper) => match oper.index() {
                        i if i == oper1 => {
                            let _ = oper.recv(&r_end);
                            done = true;
                        }
                        _ => unreachable!(),
                    },
                }
                if done {
                    break;
                }
            });

            scope.spawn(|_| loop {
                if let Ok(x) = r2.try_recv() {
                    assert_eq!(x, 2);
                    break;
                }

                let mut done = false;
                let mut sel = Select::new();
                let oper1 = sel.recv(&r_end);
                let oper = sel.try_select();
                match oper {
                    Err(_) => {}
                    Ok(oper) => match oper.index() {
                        i if i == oper1 => {
                            let _ = oper.recv(&r_end);
                            done = true;
                        }
                        _ => unreachable!(),
                    },
                }
                if done {
                    break;
                }
            });

            scope.spawn(|_| {
                thread::sleep(ms(500));

                let mut sel = Select::new();
                let oper1 = sel.recv(&r1);
                let oper2 = sel.send(&s2);
                let oper = sel.select_timeout(ms(1000));
                match oper {
                    Err(_) => {}
                    Ok(oper) => match oper.index() {
                        i if i == oper1 => assert_eq!(oper.recv(&r1), Ok(1)),
                        i if i == oper2 => assert!(oper.send(&s2, 2).is_ok()),
                        _ => unreachable!(),
                    },
                }

                drop(s_end);
            });
        })
        .unwrap();
    }
}

#[test]
fn cloning1() {
    scope(|scope| {
        let (s1, r1) = unbounded::<i32>();
        let (_s2, r2) = unbounded::<i32>();
        let (s3, r3) = unbounded::<()>();

        scope.spawn(move |_| {
            r3.recv().unwrap();
            drop(s1.clone());
            assert!(r3.try_recv().is_err());
            s1.send(1).unwrap();
            r3.recv().unwrap();
        });

        s3.send(()).unwrap();

        let mut sel = Select::new();
        let oper1 = sel.recv(&r1);
        let oper2 = sel.recv(&r2);
        let oper = sel.select();
        match oper.index() {
            i if i == oper1 => drop(oper.recv(&r1)),
            i if i == oper2 => drop(oper.recv(&r2)),
            _ => unreachable!(),
        }

        s3.send(()).unwrap();
    })
    .unwrap();
}

#[test]
fn cloning2() {
    let (s1, r1) = unbounded::<()>();
    let (s2, r2) = unbounded::<()>();
    let (_s3, _r3) = unbounded::<()>();

    scope(|scope| {
        scope.spawn(move |_| {
            let mut sel = Select::new();
            let oper1 = sel.recv(&r1);
            let oper2 = sel.recv(&r2);
            let oper = sel.select();
            match oper.index() {
                i if i == oper1 => panic!(),
                i if i == oper2 => drop(oper.recv(&r2)),
                _ => unreachable!(),
            }
        });

        thread::sleep(ms(500));
        drop(s1.clone());
        s2.send(()).unwrap();
    })
    .unwrap();
}

#[test]
fn preflight1() {
    let (s, r) = unbounded();
    s.send(()).unwrap();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r);
    let oper = sel.select();
    match oper.index() {
        i if i == oper1 => drop(oper.recv(&r)),
        _ => unreachable!(),
    }
}

#[test]
fn preflight2() {
    let (s, r) = unbounded();
    drop(s.clone());
    s.send(()).unwrap();
    drop(s);

    let mut sel = Select::new();
    let oper1 = sel.recv(&r);
    let oper = sel.select();
    match oper.index() {
        i if i == oper1 => assert_eq!(oper.recv(&r), Ok(())),
        _ => unreachable!(),
    }

    assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
}

#[test]
fn preflight3() {
    let (s, r) = unbounded();
    drop(s.clone());
    s.send(()).unwrap();
    drop(s);
    r.recv().unwrap();

    let mut sel = Select::new();
    let oper1 = sel.recv(&r);
    let oper = sel.select();
    match oper.index() {
        i if i == oper1 => assert!(oper.recv(&r).is_err()),
        _ => unreachable!(),
    }
}

#[test]
fn duplicate_operations() {
    let (s, r) = unbounded::<i32>();
    let hit = vec![Cell::new(false); 4];

    while hit.iter().map(|h| h.get()).any(|hit| !hit) {
        let mut sel = Select::new();
        let oper0 = sel.recv(&r);
        let oper1 = sel.recv(&r);
        let oper2 = sel.send(&s);
        let oper3 = sel.send(&s);
        let oper = sel.select();
        match oper.index() {
            i if i == oper0 => {
                assert!(oper.recv(&r).is_ok());
                hit[0].set(true);
            }
            i if i == oper1 => {
                assert!(oper.recv(&r).is_ok());
                hit[1].set(true);
            }
            i if i == oper2 => {
                assert!(oper.send(&s, 0).is_ok());
                hit[2].set(true);
            }
            i if i == oper3 => {
                assert!(oper.send(&s, 0).is_ok());
                hit[3].set(true);
            }
            _ => unreachable!(),
        }
    }
}

#[test]
fn nesting() {
    let (s, r) = unbounded::<i32>();

    let mut sel = Select::new();
    let oper1 = sel.send(&s);
    let oper = sel.select();
    match oper.index() {
        i if i == oper1 => {
            assert!(oper.send(&s, 0).is_ok());

            let mut sel = Select::new();
            let oper1 = sel.recv(&r);
            let oper = sel.select();
            match oper.index() {
                i if i == oper1 => {
                    assert_eq!(oper.recv(&r), Ok(0));

                    let mut sel = Select::new();
                    let oper1 = sel.send(&s);
                    let oper = sel.select();
                    match oper.index() {
                        i if i == oper1 => {
                            assert!(oper.send(&s, 1).is_ok());

                            let mut sel = Select::new();
                            let oper1 = sel.recv(&r);
                            let oper = sel.select();
                            match oper.index() {
                                i if i == oper1 => {
                                    assert_eq!(oper.recv(&r), Ok(1));
                                }
                                _ => unreachable!(),
                            }
                        }
                        _ => unreachable!(),
                    }
                }
                _ => unreachable!(),
            }
        }
        _ => unreachable!(),
    }
}

#[test]
fn stress_recv() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 10_000;

    let (s1, r1) = unbounded();
    let (s2, r2) = bounded(5);
    let (s3, r3) = bounded(100);

    scope(|scope| {
        scope.spawn(|_| {
            for i in 0..COUNT {
                s1.send(i).unwrap();
                r3.recv().unwrap();

                s2.send(i).unwrap();
                r3.recv().unwrap();
            }
        });

        for i in 0..COUNT {
            for _ in 0..2 {
                let mut sel = Select::new();
                let oper1 = sel.recv(&r1);
                let oper2 = sel.recv(&r2);
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert_eq!(oper.recv(&r1), Ok(i)),
                    ix if ix == oper2 => assert_eq!(oper.recv(&r2), Ok(i)),
                    _ => unreachable!(),
                }

                s3.send(()).unwrap();
            }
        }
    })
    .unwrap();
}

#[test]
fn stress_send() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 10_000;

    let (s1, r1) = bounded(0);
    let (s2, r2) = bounded(0);
    let (s3, r3) = bounded(100);

    scope(|scope| {
        scope.spawn(|_| {
            for i in 0..COUNT {
                assert_eq!(r1.recv().unwrap(), i);
                assert_eq!(r2.recv().unwrap(), i);
                r3.recv().unwrap();
            }
        });

        for i in 0..COUNT {
            for _ in 0..2 {
                let mut sel = Select::new();
                let oper1 = sel.send(&s1);
                let oper2 = sel.send(&s2);
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert!(oper.send(&s1, i).is_ok()),
                    ix if ix == oper2 => assert!(oper.send(&s2, i).is_ok()),
                    _ => unreachable!(),
                }
            }
            s3.send(()).unwrap();
        }
    })
    .unwrap();
}

#[test]
fn stress_mixed() {
    #[cfg(miri)]
    const COUNT: usize = 100;
    #[cfg(not(miri))]
    const COUNT: usize = 10_000;

    let (s1, r1) = bounded(0);
    let (s2, r2) = bounded(0);
    let (s3, r3) = bounded(100);

    scope(|scope| {
        scope.spawn(|_| {
            for i in 0..COUNT {
                s1.send(i).unwrap();
                assert_eq!(r2.recv().unwrap(), i);
                r3.recv().unwrap();
            }
        });

        for i in 0..COUNT {
            for _ in 0..2 {
                let mut sel = Select::new();
                let oper1 = sel.recv(&r1);
                let oper2 = sel.send(&s2);
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert_eq!(oper.recv(&r1), Ok(i)),
                    ix if ix == oper2 => assert!(oper.send(&s2, i).is_ok()),
                    _ => unreachable!(),
                }
            }
            s3.send(()).unwrap();
        }
    })
    .unwrap();
}

#[test]
fn stress_timeout_two_threads() {
    const COUNT: usize = 20;

    let (s, r) = bounded(2);

    scope(|scope| {
        scope.spawn(|_| {
            for i in 0..COUNT {
                if i % 2 == 0 {
                    thread::sleep(ms(500));
                }

                loop {
                    let mut sel = Select::new();
                    let oper1 = sel.send(&s);
                    let oper = sel.select_timeout(ms(100));
                    match oper {
                        Err(_) => {}
                        Ok(oper) => match oper.index() {
                            ix if ix == oper1 => {
                                assert!(oper.send(&s, i).is_ok());
                                break;
                            }
                            _ => unreachable!(),
                        },
                    }
                }
            }
        });

        scope.spawn(|_| {
            for i in 0..COUNT {
                if i % 2 == 0 {
                    thread::sleep(ms(500));
                }

                loop {
                    let mut sel = Select::new();
                    let oper1 = sel.recv(&r);
                    let oper = sel.select_timeout(ms(100));
                    match oper {
                        Err(_) => {}
                        Ok(oper) => match oper.index() {
                            ix if ix == oper1 => {
                                assert_eq!(oper.recv(&r), Ok(i));
                                break;
                            }
                            _ => unreachable!(),
                        },
                    }
                }
            }
        });
    })
    .unwrap();
}

#[test]
fn send_recv_same_channel() {
    let (s, r) = bounded::<i32>(0);
    let mut sel = Select::new();
    let oper1 = sel.send(&s);
    let oper2 = sel.recv(&r);
    let oper = sel.select_timeout(ms(100));
    match oper {
        Err(_) => {}
        Ok(oper) => match oper.index() {
            ix if ix == oper1 => panic!(),
            ix if ix == oper2 => panic!(),
            _ => unreachable!(),
        },
    }

    let (s, r) = unbounded::<i32>();
    let mut sel = Select::new();
    let oper1 = sel.send(&s);
    let oper2 = sel.recv(&r);
    let oper = sel.select_timeout(ms(100));
    match oper {
        Err(_) => panic!(),
        Ok(oper) => match oper.index() {
            ix if ix == oper1 => assert!(oper.send(&s, 0).is_ok()),
            ix if ix == oper2 => panic!(),
            _ => unreachable!(),
        },
    }
}

#[test]
fn matching() {
    const THREADS: usize = 44;

    let (s, r) = &bounded::<usize>(0);

    scope(|scope| {
        for i in 0..THREADS {
            scope.spawn(move |_| {
                let mut sel = Select::new();
                let oper1 = sel.recv(r);
                let oper2 = sel.send(s);
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                    _ => unreachable!(),
                }
            });
        }
    })
    .unwrap();

    assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
}

#[test]
fn matching_with_leftover() {
    const THREADS: usize = 55;

    let (s, r) = &bounded::<usize>(0);

    scope(|scope| {
        for i in 0..THREADS {
            scope.spawn(move |_| {
                let mut sel = Select::new();
                let oper1 = sel.recv(r);
                let oper2 = sel.send(s);
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                    _ => unreachable!(),
                }
            });
        }
        s.send(!0).unwrap();
    })
    .unwrap();

    assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
}

#[test]
fn channel_through_channel() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 1000;

    type T = Box<dyn Any + Send>;

    for cap in 0..3 {
        let (s, r) = bounded::<T>(cap);

        scope(|scope| {
            scope.spawn(move |_| {
                let mut s = s;

                for _ in 0..COUNT {
                    let (new_s, new_r) = bounded(cap);
                    let new_r: T = Box::new(Some(new_r));

                    {
                        let mut sel = Select::new();
                        let oper1 = sel.send(&s);
                        let oper = sel.select();
                        match oper.index() {
                            ix if ix == oper1 => assert!(oper.send(&s, new_r).is_ok()),
                            _ => unreachable!(),
                        }
                    }

                    s = new_s;
                }
            });

            scope.spawn(move |_| {
                let mut r = r;

                for _ in 0..COUNT {
                    let new = {
                        let mut sel = Select::new();
                        let oper1 = sel.recv(&r);
                        let oper = sel.select();
                        match oper.index() {
                            ix if ix == oper1 => oper
                                .recv(&r)
                                .unwrap()
                                .downcast_mut::<Option<Receiver<T>>>()
                                .unwrap()
                                .take()
                                .unwrap(),
                            _ => unreachable!(),
                        }
                    };
                    r = new;
                }
            });
        })
        .unwrap();
    }
}

#[test]
fn linearizable_try() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 100_000;

    for step in 0..2 {
        let (start_s, start_r) = bounded::<()>(0);
        let (end_s, end_r) = bounded::<()>(0);

        let ((s1, r1), (s2, r2)) = if step == 0 {
            (bounded::<i32>(1), bounded::<i32>(1))
        } else {
            (unbounded::<i32>(), unbounded::<i32>())
        };

        scope(|scope| {
            scope.spawn(|_| {
                for _ in 0..COUNT {
                    start_s.send(()).unwrap();

                    s1.send(1).unwrap();

                    let mut sel = Select::new();
                    let oper1 = sel.recv(&r1);
                    let oper2 = sel.recv(&r2);
                    let oper = sel.try_select();
                    match oper {
                        Err(_) => unreachable!(),
                        Ok(oper) => match oper.index() {
                            ix if ix == oper1 => assert!(oper.recv(&r1).is_ok()),
                            ix if ix == oper2 => assert!(oper.recv(&r2).is_ok()),
                            _ => unreachable!(),
                        },
                    }

                    end_s.send(()).unwrap();
                    let _ = r2.try_recv();
                }
            });

            for _ in 0..COUNT {
                start_r.recv().unwrap();

                s2.send(1).unwrap();
                let _ = r1.try_recv();

                end_r.recv().unwrap();
            }
        })
        .unwrap();
    }
}

#[test]
fn linearizable_timeout() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 100_000;

    for step in 0..2 {
        let (start_s, start_r) = bounded::<()>(0);
        let (end_s, end_r) = bounded::<()>(0);

        let ((s1, r1), (s2, r2)) = if step == 0 {
            (bounded::<i32>(1), bounded::<i32>(1))
        } else {
            (unbounded::<i32>(), unbounded::<i32>())
        };

        scope(|scope| {
            scope.spawn(|_| {
                for _ in 0..COUNT {
                    start_s.send(()).unwrap();

                    s1.send(1).unwrap();

                    let mut sel = Select::new();
                    let oper1 = sel.recv(&r1);
                    let oper2 = sel.recv(&r2);
                    let oper = sel.select_timeout(ms(0));
                    match oper {
                        Err(_) => unreachable!(),
                        Ok(oper) => match oper.index() {
                            ix if ix == oper1 => assert!(oper.recv(&r1).is_ok()),
                            ix if ix == oper2 => assert!(oper.recv(&r2).is_ok()),
                            _ => unreachable!(),
                        },
                    }

                    end_s.send(()).unwrap();
                    let _ = r2.try_recv();
                }
            });

            for _ in 0..COUNT {
                start_r.recv().unwrap();

                s2.send(1).unwrap();
                let _ = r1.try_recv();

                end_r.recv().unwrap();
            }
        })
        .unwrap();
    }
}

#[test]
fn fairness1() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 10_000;

    let (s1, r1) = bounded::<()>(COUNT);
    let (s2, r2) = unbounded::<()>();

    for _ in 0..COUNT {
        s1.send(()).unwrap();
        s2.send(()).unwrap();
    }

    let hits = vec![Cell::new(0usize); 4];
    for _ in 0..COUNT {
        let after = after(ms(0));
        let tick = tick(ms(0));

        let mut sel = Select::new();
        let oper1 = sel.recv(&r1);
        let oper2 = sel.recv(&r2);
        let oper3 = sel.recv(&after);
        let oper4 = sel.recv(&tick);
        let oper = sel.select();
        match oper.index() {
            i if i == oper1 => {
                oper.recv(&r1).unwrap();
                hits[0].set(hits[0].get() + 1);
            }
            i if i == oper2 => {
                oper.recv(&r2).unwrap();
                hits[1].set(hits[1].get() + 1);
            }
            i if i == oper3 => {
                oper.recv(&after).unwrap();
                hits[2].set(hits[2].get() + 1);
            }
            i if i == oper4 => {
                oper.recv(&tick).unwrap();
                hits[3].set(hits[3].get() + 1);
            }
            _ => unreachable!(),
        }
    }
    assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 2));
}

#[test]
fn fairness2() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 10_000;

    let (s1, r1) = unbounded::<()>();
    let (s2, r2) = bounded::<()>(1);
    let (s3, r3) = bounded::<()>(0);

    scope(|scope| {
        scope.spawn(|_| {
            for _ in 0..COUNT {
                let mut sel = Select::new();
                let mut oper1 = None;
                let mut oper2 = None;
                if s1.is_empty() {
                    oper1 = Some(sel.send(&s1));
                }
                if s2.is_empty() {
                    oper2 = Some(sel.send(&s2));
                }
                let oper3 = sel.send(&s3);
                let oper = sel.select();
                match oper.index() {
                    i if Some(i) == oper1 => assert!(oper.send(&s1, ()).is_ok()),
                    i if Some(i) == oper2 => assert!(oper.send(&s2, ()).is_ok()),
                    i if i == oper3 => assert!(oper.send(&s3, ()).is_ok()),
                    _ => unreachable!(),
                }
            }
        });

        let hits = vec![Cell::new(0usize); 3];
        for _ in 0..COUNT {
            let mut sel = Select::new();
            let oper1 = sel.recv(&r1);
            let oper2 = sel.recv(&r2);
            let oper3 = sel.recv(&r3);
            let oper = sel.select();
            match oper.index() {
                i if i == oper1 => {
                    oper.recv(&r1).unwrap();
                    hits[0].set(hits[0].get() + 1);
                }
                i if i == oper2 => {
                    oper.recv(&r2).unwrap();
                    hits[1].set(hits[1].get() + 1);
                }
                i if i == oper3 => {
                    oper.recv(&r3).unwrap();
                    hits[2].set(hits[2].get() + 1);
                }
                _ => unreachable!(),
            }
        }
        assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 50));
    })
    .unwrap();
}

#[test]
fn sync_and_clone() {
    const THREADS: usize = 20;

    let (s, r) = &bounded::<usize>(0);

    let mut sel = Select::new();
    let oper1 = sel.recv(r);
    let oper2 = sel.send(s);
    let sel = &sel;

    scope(|scope| {
        for i in 0..THREADS {
            scope.spawn(move |_| {
                let mut sel = sel.clone();
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                    _ => unreachable!(),
                }
            });
        }
    })
    .unwrap();

    assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
}

#[test]
fn send_and_clone() {
    const THREADS: usize = 20;

    let (s, r) = &bounded::<usize>(0);

    let mut sel = Select::new();
    let oper1 = sel.recv(r);
    let oper2 = sel.send(s);

    scope(|scope| {
        for i in 0..THREADS {
            let mut sel = sel.clone();
            scope.spawn(move |_| {
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                    _ => unreachable!(),
                }
            });
        }
    })
    .unwrap();

    assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
}

#[test]
fn reuse() {
    #[cfg(miri)]
    const COUNT: usize = 50;
    #[cfg(not(miri))]
    const COUNT: usize = 10_000;

    let (s1, r1) = bounded(0);
    let (s2, r2) = bounded(0);
    let (s3, r3) = bounded(100);

    scope(|scope| {
        scope.spawn(|_| {
            for i in 0..COUNT {
                s1.send(i).unwrap();
                assert_eq!(r2.recv().unwrap(), i);
                r3.recv().unwrap();
            }
        });

        let mut sel = Select::new();
        let oper1 = sel.recv(&r1);
        let oper2 = sel.send(&s2);

        for i in 0..COUNT {
            for _ in 0..2 {
                let oper = sel.select();
                match oper.index() {
                    ix if ix == oper1 => assert_eq!(oper.recv(&r1), Ok(i)),
                    ix if ix == oper2 => assert!(oper.send(&s2, i).is_ok()),
                    _ => unreachable!(),
                }
            }
            s3.send(()).unwrap();
        }
    })
    .unwrap();
}

Messung V0.5 in Prozent
C=93 H=92 G=92

¤ Dauer der Verarbeitung: 0.13 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002