fn gen_block<W: io::Write>(
    submitter: Arc<Mutex<BlockSubmitter<W>>>,
    lookup_table: Arc<[(u8, f32)]>,
    mut rng: Rng,
    mut length: usize,
    mut block_num: usize,
    block_stride: usize,
) -> io::Result<()>
{
    // Include newlines in block
    length += length / LINE_LEN;
    let block: &mut [u8] = &mut [b'\n'; BLOCK_LEN];

    while length > 0 {
        {
            let gen_into = &mut block[..min(length, BLOCK_LEN)];

            // Write random numbers, skipping newlines
            for (i, byte) in gen_into.iter_mut().enumerate() {
                if (i + 1) % (LINE_LEN + 1) != 0 {
                    let p = rng.gen() as f32 * (LOOKUP_SCALE / MODULUS as f32);
                    *byte = lookup_table[p as usize..LOOKUP_SIZE].iter().find(
                        |le| le.1 >= p).unwrap().0;
                }
            }
        }

        let write_out = {
            if length >= BLOCK_LEN               { &mut *block }
            else if length % (LINE_LEN + 1) == 0 { &mut block[..length] }
            else                                 { &mut block[..length + 1] }
        };

        *write_out.last_mut().unwrap() = b'\n';
        loop {
            // Make sure to release lock before calling `yield_now`
            let res = { submitter.lock().unwrap().submit(write_out, block_num) };

            match res {
                Some(result) => { try!(result); break; }
                None => std::thread::yield_now()
            }
        }
        block_num += block_stride;
        rng = rng.future((BLOCK_THOROUGHPUT * (block_stride - 1)) as u32);
        length = length.saturating_sub(BLOCK_LEN * (block_stride - 1));

        length = length.saturating_sub(BLOCK_LEN);
    }

    Ok(())
}
// A very optimized writer.
// I have a feeling a simpler version wouldn't slow
// things down too much, though, since the RNG
// is the really heavy hitter.
A very optimized writer.
I have a feeling a simpler version wouldn't slow
things down too much, though, since the RNG
is the really heavy hitter.
A very optimized writer . I have a feeling a simpler version wouldn ' t slow things down too much though since the RNG is the really heavy hitter .
fn gen_block<W: io::Write>(
    submitter: Arc<Mutex<BlockSubmitter<W>>>,
    lookup_table: Arc<[(u8, f32)]>,
    mut rng: Rng,
    mut length: usize,
    mut block_num: usize,
    block_stride: usize,
) -> io::Result<()>
{
    // Include newlines in block
    length += length / LINE_LEN;
    let block: &mut [u8] = &mut [b'\n'; BLOCK_LEN];
    while length > 0 {
        {
            let gen_into = &mut block[..min(length, BLOCK_LEN)];
            // Write random numbers, skipping newlines
            for (i, byte) in gen_into.iter_mut().enumerate() {
                if (i + 1) % (LINE_LEN + 1) != 0 {
                    let p = rng.gen() as f32 * (LOOKUP_SCALE / MODULUS as f32);
                    *byte = lookup_table[p as usize..LOOKUP_SIZE].iter().find(
                        |le| le.1 >= p).unwrap().0;
                }
            }
        }
        let write_out = {
            if length >= BLOCK_LEN               { &mut *block }
            else if length % (LINE_LEN + 1) == 0 { &mut block[..length] }
            else                                 { &mut block[..length + 1] }
        };
        *write_out.last_mut().unwrap() = b'\n';
        loop {
            // Make sure to release lock before calling `yield_now`
            let res = { submitter.lock().unwrap().submit(write_out, block_num) };
            match res {
                Some(result) => { try!(result); break; }
                None => std::thread::yield_now()
            }
        }
        block_num += block_stride;
        rng = rng.future((BLOCK_THOROUGHPUT * (block_stride - 1)) as u32);
        length = length.saturating_sub(BLOCK_LEN * (block_stride - 1));
        length = length.saturating_sub(BLOCK_LEN);
    }
    Ok(())
}
fn gen_block < W : io :: Write > ( submitter : Arc < Mutex < BlockSubmitter < W > > > , lookup_table : Arc < [ ( u8 , f32 ) ] > , mut rng : Rng , mut length : usize , mut block_num : usize , block_stride : usize , ) -> io :: Result < ( ) > { // Include newlines in block length += length / LINE_LEN ; let block : & mut [ u8 ] = & mut [ b'\n' ; BLOCK_LEN ] ; while length > 0 { { let gen_into = & mut block [ .. min ( length , BLOCK_LEN ) ] ; // Write random numbers, skipping newlines for ( i , byte ) in gen_into . iter_mut ( ) . enumerate ( ) { if ( i + 1 ) % ( LINE_LEN + 1 ) != 0 { let p = rng . gen ( ) as f32 * ( LOOKUP_SCALE / MODULUS as f32 ) ; * byte = lookup_table [ p as usize .. LOOKUP_SIZE ] . iter ( ) . find ( | le | le . 1 >= p ) . unwrap ( ) . 0 ; } } } let write_out = { if length >= BLOCK_LEN { & mut * block } else if length % ( LINE_LEN + 1 ) == 0 { & mut block [ .. length ] } else { & mut block [ .. length + 1 ] } } ; * write_out . last_mut ( ) . unwrap ( ) = b'\n' ; loop { // Make sure to release lock before calling `yield_now` let res = { submitter . lock ( ) . unwrap ( ) . submit ( write_out , block_num ) } ; match res { Some ( result ) => { try ! ( result ) ; break ; } None => std :: thread :: yield_now ( ) } } block_num += block_stride ; rng = rng . future ( ( BLOCK_THOROUGHPUT * ( block_stride - 1 ) ) as u32 ) ; length = length . saturating_sub ( BLOCK_LEN * ( block_stride - 1 ) ) ; length = length . saturating_sub ( BLOCK_LEN ) ; } Ok ( ( ) ) }
A very optimized writer.
A very optimized writer .
submitter
Arc<Mutex<BlockSubmitter<W>>>
lookup_table
Arc<[(u8, f32)]>
rng
Rng
length
usize
block_num
usize
block_stride
usize