<commit_before>//
// sprocketnes/apu.rs
//
// Author: Patrick Walton
//

use audio::OutputBuffer;
use mem::Mem;
use speex::Resampler;
use util::{Fd, Save};
use util;

use core::cast::{forget, transmute};
use core::libc::c_int;
use core::vec::each_mut;
use sdl::audio;

const CYCLES_PER_EVEN_TICK: u64 = 7438;
const CYCLES_PER_ODD_TICK: u64 = 7439;

const NES_SAMPLE_RATE: u32 = 1789920;   // Actual is 1789800, but this is divisible by 240.
const OUTPUT_SAMPLE_RATE: u32 = 44100;
const TICK_FREQUENCY: u32 = 240;
const NES_SAMPLES_PER_TICK: u32 = NES_SAMPLE_RATE / TICK_FREQUENCY;

const PULSE_WAVEFORMS: [u8 * 4] = [ 0b01000000, 0b01100000, 0b01111000, 0b10011111 ];

const LENGTH_COUNTERS: [u8 * 32] = [
    10, 254, 20,  2, 40,  4, 80,  6, 160,  8, 60, 10, 14, 12, 26, 14,
    12,  16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30,
];

//
// Volume envelopes
//

struct ApuEnvelope {
    enabled: bool,
    volume: u8,

    period: u8,
    counter: u8,

    disable_length: bool,
    length_id: u8,
    length_left: u8,
}

save_struct!(ApuEnvelope {
    enabled, volume, period, counter, disable_length, length_id, length_left
})

impl ApuEnvelope {
    static fn new() -> ApuEnvelope {
        ApuEnvelope {
            enabled: false,
            volume: 0,

            period: 0,
            counter: 0,

            disable_length: false,
            length_id: 0,
            length_left: 0,
        }
    }

    fn loops(self) -> bool { self.disable_length }

    // Channels that support the APU Envelope support writing to the registers in the same way.
    fn storeb(&mut self, addr: u16, val: u8) {
        match addr & 0x3 {
            0 => {
                self.disable_length = ((val >> 5) & 1) != 0;
                self.enabled = ((val >> 4) & 1) == 0;
                if self.enabled {
                    self.volume = 15;
                    self.period = val & 0xf;
                    self.counter = 0;
                } else {
                    self.volume = val & 0xf;
                }
            }
            1 | 2 => {}
            3 => {
                self.length_id = val >> 3;

                // FIXME: Only set length_left if APUSTATUS has enabled this channel.
                self.length_left = LENGTH_COUNTERS[self.length_id];
            }
            _ => fail!(~"can't happen"),
        }
    }
}

//
// APUPULSE: [0x4000, 0x4008)
//

struct ApuPulse {
    duty: u8,
    envelope: ApuEnvelope,
    sweep: ApuPulseSweep,
    timer: u16,

    sweep_cycle: u8,

    waveform_index: u8,
    wavelen_count: u64,
}

save_struct!(ApuPulse { duty, envelope, sweep, timer, sweep_cycle, waveform_index, wavelen_count })

//
// APU pulse sweep
//

struct ApuPulseSweep(u8);

impl ApuPulseSweep {
    fn enabled(self) -> bool   { (*self >> 7) != 0         }
    fn period(self) -> u8      { ((*self >> 4) & 0x7) + 1  }
    fn negate(self) -> bool    { ((*self >> 3) & 0x1) != 0 }
    fn shift_count(self) -> u8 { *self & 0x7               }
}

struct ApuStatus(u8);

impl ApuStatus {
    fn pulse_enabled(self, channel: u8) -> bool { ((*self >> channel) & 1) != 0 }
}

struct Regs {
    pulses: [ApuPulse * 2],
    status: ApuStatus,  // $4015: APUSTATUS
}

impl Save for Regs {
    fn save(&mut self, fd: &Fd) {
        self.pulses[0].save(fd);
        self.pulses[1].save(fd);
        self.status.save(fd);
    }
    fn load(&mut self, fd: &Fd) {
        self.pulses[0].load(fd);
        self.pulses[1].load(fd);
        self.status.load(fd);
    }
}

//
// Sample buffers
//

struct SampleBuffer {
    samples: [i16 * 178992],
}

//
// General operation
//

pub struct Apu {
    regs: Regs,

    sample_buffers: ~([SampleBuffer * 5]),
    sample_buffer_offset: uint,
    output_buffer: *mut OutputBuffer,
    resampler: Resampler,

    cy: u64,
    ticks: u64,
}

save_struct!(Apu { regs, cy, ticks })

impl Mem for Apu {
    fn loadb(&mut self, addr: u16) -> u8 {
        match addr {
            0x4015 => *self.regs.status,
            _ => 0
        }
    }
    fn storeb(&mut self, addr: u16, val: u8) {
        match addr {
            0x4000..0x4003 => self.update_pulse(addr, val, 0),
            0x4004..0x4007 => self.update_pulse(addr, val, 1),
            0x4015 => self.update_status(val),
            _ => {} // TODO
        }
    }
}

impl Apu {
    static pub fn new(output_buffer: *mut OutputBuffer) -> Apu {
        Apu {
            regs: Regs {
                pulses: [
                    ApuPulse {
                        duty: 0,
                        envelope: ApuEnvelope::new(),
                        sweep: ApuPulseSweep(0),
                        timer: 0,

                        sweep_cycle: 0,

                        waveform_index: 0,
                        wavelen_count: 0,
                    }, ..2
                ],
                status: ApuStatus(0),
            },

            sample_buffers: ~[ SampleBuffer { samples: [ 0, ..178992 ] }, ..5 ],
            sample_buffer_offset: 0,
            output_buffer: output_buffer,
            resampler: Resampler::new(1, NES_SAMPLE_RATE, OUTPUT_SAMPLE_RATE, 0).unwrap(),

            cy: 0,
            ticks: 0,
        }
    }

    fn update_status(&mut self, val: u8) {
        self.regs.status = ApuStatus(val);

        for uint::range(0, 2) |i| {
            if !self.regs.status.pulse_enabled(i as u8) {
                self.regs.pulses[i].envelope.length_left = 0;
            }
        }
    }

    fn update_pulse(&mut self, addr: u16, val: u8, pulse_number: uint) {
        let pulse = &mut self.regs.pulses[pulse_number];
        pulse.envelope.storeb(addr, val);   // Write to the envelope.
        match addr & 0x3 {
            0 => pulse.duty = val >> 6,
            1 => {
                // TODO: Set reload flag.
                pulse.sweep = ApuPulseSweep(val);
                pulse.sweep_cycle = 0;
            }
            2 => pulse.timer = (pulse.timer & 0xff00) | (val as u16),
            3 => pulse.timer = (pulse.timer & 0x00ff) | ((val as u16 & 0x7) << 8),
            _ => fail!(~"can't happen"),
        }
    }

    //
    // Playback
    //

    pub fn step(&mut self, run_to_cycle: u64) {
        loop {
            let mut next_tick_cycle = self.cy;
            if self.ticks % 2 == 0 {
                next_tick_cycle += CYCLES_PER_EVEN_TICK;
            } else {
                next_tick_cycle += CYCLES_PER_ODD_TICK;
            }

            if next_tick_cycle > run_to_cycle {
                break;
            }

            self.tick();

            self.cy = next_tick_cycle;
        }
    }

    fn tick(&mut self) {
        // 120 Hz operations: length counter and sweep.
        if self.ticks % 2 == 0 {
            // TODO: Remember that triangle wave has a different length disable bit.
            for uint::range(0, 2) |i| {
                let pulse = &mut self.regs.pulses[i];

                // Length counter.
                if pulse.envelope.length_left > 0 && !pulse.envelope.disable_length {
                    pulse.envelope.length_left -= 1;
                }

                // Sweep.
                pulse.sweep_cycle += 1;
                if pulse.sweep_cycle >= pulse.sweep.period() {
                    pulse.sweep_cycle = 0;

                    if pulse.sweep.enabled() {
                        let delta = pulse.timer >> pulse.sweep.shift_count();
                        if !pulse.sweep.negate() {
                            pulse.timer += delta;
                        } else {
                            pulse.timer -= delta;
                        }
                    }
                }
            }
        }

        // 240 Hz operations: envelope and linear counter.
        for uint::range(0, 2) |i| {
            let pulse = &mut self.regs.pulses[i];
            if pulse.envelope.enabled {
                pulse.envelope.counter += 1;
                if pulse.envelope.counter >= pulse.envelope.period {
                    pulse.envelope.counter = 0;
                    if pulse.envelope.volume == 0 {
                        if pulse.envelope.loops() {
                            pulse.envelope.volume = 15;
                        }
                    } else {
                        pulse.envelope.volume -= 1;
                        if pulse.envelope.volume == 0 && !pulse.envelope.loops() {
                            pulse.envelope.length_left = 0;
                        }
                    }
                }
            }
        }

        // Fill the sample buffers.
        self.play_pulse(0, 0);
        self.play_pulse(1, 1);
        self.sample_buffer_offset += NES_SAMPLES_PER_TICK as uint;

        // Now play the channels, flushing the sample buffers, if necessary.
        self.play_channels();

        // TODO: 60 Hz IRQ.

        self.ticks += 1;
    }

    fn play_pulse(&mut self, pulse_number: uint, channel: c_int) {
        let pulse = &mut self.regs.pulses[pulse_number];
        let timer = pulse.timer as uint;

        let mut sample_buffer = &mut self.sample_buffers[channel];
        let start_offset = self.sample_buffer_offset;
        let end_offset = start_offset + NES_SAMPLES_PER_TICK as uint;

        // Process sound.
        if timer > 0 && pulse.envelope.volume > 0 && pulse.envelope.length_left > 0 {
            let volume = (pulse.envelope.volume as i16 * 4) << 8;
            let wavelen = (pulse.timer as u64 + 1) * 2;
            let waveform: u8 = PULSE_WAVEFORMS[pulse.duty];

            // Fill the buffer.
            let mut buffer = vec::mut_slice(sample_buffer.samples, start_offset, end_offset);

            // TODO: Vectorize this for speed.
            let mut waveform_index = pulse.waveform_index;
            let mut wavelen_count = pulse.wavelen_count;

            for vec::each_mut(buffer) |dest| {
                wavelen_count += 1;
                if wavelen_count >= wavelen {
                    wavelen_count = 0;
                    waveform_index = (waveform_index + 1) % 8;
                }

                *dest = if ((waveform >> (7 - waveform_index)) & 1) != 0 { volume } else { 0 };
            }

            pulse.waveform_index = waveform_index;
            pulse.wavelen_count = wavelen_count;
        } else {
            for uint::range(start_offset, end_offset) |i| {
                sample_buffer.samples[i] = 0;
            }
        }
    }

    // Resamples and flushes channel buffers to the audio output device if necessary.
    fn play_channels(&mut self) {
        let sample_buffer_length = self.sample_buffers[0].samples.len();
        if self.sample_buffer_offset < sample_buffer_length {
            return;
        }
        self.sample_buffer_offset = 0;

        // First, mix all sample buffers into the first one.
        //
        // FIXME: This should not be a linear mix, for accuracy.
        for uint::range(0, self.sample_buffers[0].samples.len()) |i| {
            let mut val = 0;
            for uint::range(0, 5) |j| {
                val += self.sample_buffers[j].samples[i] as i32;
            }

            if val > 32767 {
                val = 32767;
            } else if val < -32768 {
                val = -32768;
            }

            self.sample_buffers[0].samples[i] = val as i16;
        }

        // Wait for the audio callback to catch up if necessary.
        // FIXME: This is a racy spinlock; use condvars instead.
        loop {
            let played = do audio::with_lock {
                unsafe {
                    (*self.output_buffer).play_offset == (*self.output_buffer).samples.len()
                }
            };
            if played {
                break;
            }
        }

        // Resample and output the audio.
        do audio::with_lock {
            unsafe {
                let _ = self.resampler.process(0,
                                               self.sample_buffers[0].samples,
                                               (*self.output_buffer).samples);
                (*self.output_buffer).play_offset = 0;
            }
        }
    }
}

<commit_msg>Factor the tick routine out of the pulse and into the envelope<commit_after>//
// sprocketnes/apu.rs
//
// Author: Patrick Walton
//

use audio::OutputBuffer;
use mem::Mem;
use speex::Resampler;
use util::{Fd, Save};
use util;

use core::cast::{forget, transmute};
use core::libc::c_int;
use core::vec::each_mut;
use sdl::audio;

const CYCLES_PER_EVEN_TICK: u64 = 7438;
const CYCLES_PER_ODD_TICK: u64 = 7439;

const NES_SAMPLE_RATE: u32 = 1789920;   // Actual is 1789800, but this is divisible by 240.
const OUTPUT_SAMPLE_RATE: u32 = 44100;
const TICK_FREQUENCY: u32 = 240;
const NES_SAMPLES_PER_TICK: u32 = NES_SAMPLE_RATE / TICK_FREQUENCY;

const PULSE_WAVEFORMS: [u8 * 4] = [ 0b01000000, 0b01100000, 0b01111000, 0b10011111 ];

const LENGTH_COUNTERS: [u8 * 32] = [
    10, 254, 20,  2, 40,  4, 80,  6, 160,  8, 60, 10, 14, 12, 26, 14,
    12,  16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30,
];

//
// Volume envelopes
//

struct ApuEnvelope {
    enabled: bool,
    volume: u8,

    period: u8,
    counter: u8,

    disable_length: bool,
    length_id: u8,
    length_left: u8,
}

save_struct!(ApuEnvelope {
    enabled, volume, period, counter, disable_length, length_id, length_left
})

impl ApuEnvelope {
    static fn new() -> ApuEnvelope {
        ApuEnvelope {
            enabled: false,
            volume: 0,

            period: 0,
            counter: 0,

            disable_length: false,
            length_id: 0,
            length_left: 0,
        }
    }

    fn loops(self) -> bool { self.disable_length }

    // Channels that support the APU Envelope support writing to the registers in the same way.
    fn storeb(&mut self, addr: u16, val: u8) {
        match addr & 0x3 {
            0 => {
                self.disable_length = ((val >> 5) & 1) != 0;
                self.enabled = ((val >> 4) & 1) == 0;
                if self.enabled {
                    self.volume = 15;
                    self.period = val & 0xf;
                    self.counter = 0;
                } else {
                    self.volume = val & 0xf;
                }
            }
            1 | 2 => {}
            3 => {
                self.length_id = val >> 3;

                // FIXME: Only set length_left if APUSTATUS has enabled this channel.
                self.length_left = LENGTH_COUNTERS[self.length_id];
            }
            _ => fail!(~"can't happen"),
        }
    }

    fn decrement_length(&mut self) {
        if self.length_left > 0 && !self.disable_length {
            self.length_left -= 1;
        }
    }

    // This routine executes at 240 Hz and adjusts the volume and counter appropriately.
    fn tick(&mut self) {
        if self.enabled {
            self.counter += 1;
            if self.counter >= self.period {
                self.counter = 0;
                if self.volume == 0 {
                    if self.loops() {
                        self.volume = 15;
                    }
                } else {
                    self.volume -= 1;
                    if self.volume == 0 && !self.loops() {
                        self.length_left = 0;
                    }
                }
            }
        }
    }
}

//
// APUPULSE: [0x4000, 0x4008)
//

struct ApuPulse {
    duty: u8,
    envelope: ApuEnvelope,
    sweep: ApuPulseSweep,
    timer: u16,

    sweep_cycle: u8,

    waveform_index: u8,
    wavelen_count: u64,
}

save_struct!(ApuPulse { duty, envelope, sweep, timer, sweep_cycle, waveform_index, wavelen_count })

//
// APU pulse sweep
//

struct ApuPulseSweep(u8);

impl ApuPulseSweep {
    fn enabled(self) -> bool   { (*self >> 7) != 0         }
    fn period(self) -> u8      { ((*self >> 4) & 0x7) + 1  }
    fn negate(self) -> bool    { ((*self >> 3) & 0x1) != 0 }
    fn shift_count(self) -> u8 { *self & 0x7               }
}

struct ApuStatus(u8);

impl ApuStatus {
    fn pulse_enabled(self, channel: u8) -> bool { ((*self >> channel) & 1) != 0 }
}

struct Regs {
    pulses: [ApuPulse * 2],
    status: ApuStatus,  // $4015: APUSTATUS
}

impl Save for Regs {
    fn save(&mut self, fd: &Fd) {
        self.pulses[0].save(fd);
        self.pulses[1].save(fd);
        self.status.save(fd);
    }
    fn load(&mut self, fd: &Fd) {
        self.pulses[0].load(fd);
        self.pulses[1].load(fd);
        self.status.load(fd);
    }
}

//
// Sample buffers
//

struct SampleBuffer {
    samples: [i16 * 178992],
}

//
// General operation
//

pub struct Apu {
    regs: Regs,

    sample_buffers: ~([SampleBuffer * 5]),
    sample_buffer_offset: uint,
    output_buffer: *mut OutputBuffer,
    resampler: Resampler,

    cy: u64,
    ticks: u64,
}

save_struct!(Apu { regs, cy, ticks })

impl Mem for Apu {
    fn loadb(&mut self, addr: u16) -> u8 {
        match addr {
            0x4015 => *self.regs.status,
            _ => 0
        }
    }
    fn storeb(&mut self, addr: u16, val: u8) {
        match addr {
            0x4000..0x4003 => self.update_pulse(addr, val, 0),
            0x4004..0x4007 => self.update_pulse(addr, val, 1),
            0x4015 => self.update_status(val),
            _ => {} // TODO
        }
    }
}

impl Apu {
    static pub fn new(output_buffer: *mut OutputBuffer) -> Apu {
        Apu {
            regs: Regs {
                pulses: [
                    ApuPulse {
                        duty: 0,
                        envelope: ApuEnvelope::new(),
                        sweep: ApuPulseSweep(0),
                        timer: 0,

                        sweep_cycle: 0,

                        waveform_index: 0,
                        wavelen_count: 0,
                    }, ..2
                ],
                status: ApuStatus(0),
            },

            sample_buffers: ~[ SampleBuffer { samples: [ 0, ..178992 ] }, ..5 ],
            sample_buffer_offset: 0,
            output_buffer: output_buffer,
            resampler: Resampler::new(1, NES_SAMPLE_RATE, OUTPUT_SAMPLE_RATE, 0).unwrap(),

            cy: 0,
            ticks: 0,
        }
    }

    fn update_status(&mut self, val: u8) {
        self.regs.status = ApuStatus(val);

        for uint::range(0, 2) |i| {
            if !self.regs.status.pulse_enabled(i as u8) {
                self.regs.pulses[i].envelope.length_left = 0;
            }
        }
    }

    fn update_pulse(&mut self, addr: u16, val: u8, pulse_number: uint) {
        let pulse = &mut self.regs.pulses[pulse_number];
        pulse.envelope.storeb(addr, val);   // Write to the envelope.
        match addr & 0x3 {
            0 => pulse.duty = val >> 6,
            1 => {
                // TODO: Set reload flag.
                pulse.sweep = ApuPulseSweep(val);
                pulse.sweep_cycle = 0;
            }
            2 => pulse.timer = (pulse.timer & 0xff00) | (val as u16),
            3 => pulse.timer = (pulse.timer & 0x00ff) | ((val as u16 & 0x7) << 8),
            _ => fail!(~"can't happen"),
        }
    }

    //
    // Playback
    //

    pub fn step(&mut self, run_to_cycle: u64) {
        loop {
            let mut next_tick_cycle = self.cy;
            if self.ticks % 2 == 0 {
                next_tick_cycle += CYCLES_PER_EVEN_TICK;
            } else {
                next_tick_cycle += CYCLES_PER_ODD_TICK;
            }

            if next_tick_cycle > run_to_cycle {
                break;
            }

            self.tick();

            self.cy = next_tick_cycle;
        }
    }

    fn tick(&mut self) {
        // 120 Hz operations: length counter and sweep.
        if self.ticks % 2 == 0 {
            // TODO: Remember that triangle wave has a different length disable bit.
            for uint::range(0, 2) |i| {
                let pulse = &mut self.regs.pulses[i];

                // Length counter.
                pulse.envelope.decrement_length();

                // Sweep.
                pulse.sweep_cycle += 1;
                if pulse.sweep_cycle >= pulse.sweep.period() {
                    pulse.sweep_cycle = 0;

                    if pulse.sweep.enabled() {
                        let delta = pulse.timer >> pulse.sweep.shift_count();
                        if !pulse.sweep.negate() {
                            pulse.timer += delta;
                        } else {
                            pulse.timer -= delta;
                        }
                    }
                }
            }
        }

        // 240 Hz operations: envelope and linear counter.
        self.regs.pulses[0].envelope.tick();
        self.regs.pulses[1].envelope.tick();

        // Fill the sample buffers.
        self.play_pulse(0, 0);
        self.play_pulse(1, 1);
        self.sample_buffer_offset += NES_SAMPLES_PER_TICK as uint;

        // Now play the channels, flushing the sample buffers, if necessary.
        self.play_channels();

        // TODO: 60 Hz IRQ.

        self.ticks += 1;
    }

    fn play_pulse(&mut self, pulse_number: uint, channel: c_int) {
        let pulse = &mut self.regs.pulses[pulse_number];
        let timer = pulse.timer as uint;

        let mut sample_buffer = &mut self.sample_buffers[channel];
        let start_offset = self.sample_buffer_offset;
        let end_offset = start_offset + NES_SAMPLES_PER_TICK as uint;

        // Process sound.
        if timer > 0 && pulse.envelope.volume > 0 && pulse.envelope.length_left > 0 {
            let volume = (pulse.envelope.volume as i16 * 4) << 8;
            let wavelen = (pulse.timer as u64 + 1) * 2;
            let waveform: u8 = PULSE_WAVEFORMS[pulse.duty];

            // Fill the buffer.
            let mut buffer = vec::mut_slice(sample_buffer.samples, start_offset, end_offset);

            // TODO: Vectorize this for speed.
            let mut waveform_index = pulse.waveform_index;
            let mut wavelen_count = pulse.wavelen_count;

            for vec::each_mut(buffer) |dest| {
                wavelen_count += 1;
                if wavelen_count >= wavelen {
                    wavelen_count = 0;
                    waveform_index = (waveform_index + 1) % 8;
                }

                *dest = if ((waveform >> (7 - waveform_index)) & 1) != 0 { volume } else { 0 };
            }

            pulse.waveform_index = waveform_index;
            pulse.wavelen_count = wavelen_count;
        } else {
            for uint::range(start_offset, end_offset) |i| {
                sample_buffer.samples[i] = 0;
            }
        }
    }

    // Resamples and flushes channel buffers to the audio output device if necessary.
    fn play_channels(&mut self) {
        let sample_buffer_length = self.sample_buffers[0].samples.len();
        if self.sample_buffer_offset < sample_buffer_length {
            return;
        }
        self.sample_buffer_offset = 0;

        // First, mix all sample buffers into the first one.
        //
        // FIXME: This should not be a linear mix, for accuracy.
        for uint::range(0, self.sample_buffers[0].samples.len()) |i| {
            let mut val = 0;
            for uint::range(0, 5) |j| {
                val += self.sample_buffers[j].samples[i] as i32;
            }

            if val > 32767 {
                val = 32767;
            } else if val < -32768 {
                val = -32768;
            }

            self.sample_buffers[0].samples[i] = val as i16;
        }

        // Wait for the audio callback to catch up if necessary.
        // FIXME: This is a racy spinlock; use condvars instead.
        loop {
            let played = do audio::with_lock {
                unsafe {
                    (*self.output_buffer).play_offset == (*self.output_buffer).samples.len()
                }
            };
            if played {
                break;
            }
        }

        // Resample and output the audio.
        do audio::with_lock {
            unsafe {
                let _ = self.resampler.process(0,
                                               self.sample_buffers[0].samples,
                                               (*self.output_buffer).samples);
                (*self.output_buffer).play_offset = 0;
            }
        }
    }
}

<|endoftext|>


<commit_before>use constants::*;
use std::ffi::OsString;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = ".kic";
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let config_file    = "config.toml";
    let path_to_config = path_to_dir.clone().join(config_file);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let ignore_file    = "ignore";
    let path_to_ignore = path_to_dir.clone().join(ignore_file);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut fp) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match fp.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

fn walk_dir<P: AsRef<Path>>(path: P) -> Vec<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter(|de| de.is_ok())
            .flat_map(|de| {
                let path = de.unwrap().path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).iter()
        .map(|f| f.clone().into_string())
        .filter(|f| f.is_ok())
        .map(|f| f.unwrap())
        .collect::<Vec<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with("."))
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    println!("sweep");
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("destroy");
}
<commit_msg>Implement "destroy" command<commit_after>use constants::*;
use std::ffi::OsString;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = ".kic";
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let config_file    = "config.toml";
    let path_to_config = path_to_dir.clone().join(config_file);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let ignore_file    = "ignore";
    let path_to_ignore = path_to_dir.clone().join(ignore_file);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut fp) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match fp.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

fn walk_dir<P: AsRef<Path>>(path: P) -> Vec<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter(|de| de.is_ok())
            .flat_map(|de| {
                let path = de.unwrap().path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).iter()
        .map(|f| f.clone().into_string())
        .filter(|f| f.is_ok())
        .map(|f| f.unwrap())
        .collect::<Vec<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with("."))
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    println!("sweep");
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("Destroy ...");

    let dir_name = ".kic";
    match fs::remove_dir_all(dir_name) {
        Ok(_)    => println!("  OK: Removed \"{}\" directory.", dir_name),
        Err(why) => panic!("{:?}", why),
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_name = "gfx_macros"]
#![comment = "Helper macros for gfx-rs"]
#![license = "ASL2"]
#![crate_type = "dylib"]

#![feature(macro_rules, plugin_registrar, quote)]

//! Macro extensions crate.
//! Implements `shaders!` macro as well as `#[shader_param]` and
//! `#[vertex_format]` attributes.

extern crate rustc;
extern crate syntax;

use syntax::{ast, attr, ext, codemap};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::fold::Folder;
use std::gc::Gc;

pub mod shader_param;
pub mod vertex_format;

/// Entry point for the plugin phase
#[plugin_registrar]
pub fn registrar(reg: &mut rustc::plugin::Registry) {
    use syntax::parse::token::intern;
    use syntax::ext::base;
    // Register the `#[shader_param]` attribute.
    reg.register_syntax_extension(intern("shader_param"),
        base::ItemDecorator(shader_param::expand));
    // Register the `#[vertex_format]` attribute.
    reg.register_syntax_extension(intern("vertex_format"),
        base::ItemDecorator(vertex_format::expand));
}

/// A hacky thing to get around 'moved value' errors when using `quote_expr!`
/// with `ext::base::ExtCtxt`s.
fn ugh<T, U>(x: &mut T, f: |&mut T| -> U) -> U { f(x) }

/// Scan through the field's attributes and extract the field vertex name. If
/// multiple names are found, use the first name and emit a warning.
fn find_name(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
             attributes: &[ast::Attribute]) -> Option<token::InternedString> {
    attributes.iter().fold(None, |name, attribute| {
        match attribute.node.value.node {
            ast::MetaNameValue(ref attr_name, ref attr_value) => {
                match (attr_name.get(), &attr_value.node) {
                    ("name", &ast::LitStr(ref new_name, _)) => {
                        attr::mark_used(attribute);
                        name.map_or(Some(new_name.clone()), |name| {
                            cx.span_warn(span, format!(
                                "Extra field name detected: {} - \
                                ignoring in favour of: {}", new_name, name
                            ).as_slice());
                            None
                        })
                    }
                    _ => None,
                }
            }
            _ => name,
        }
    })
}

/// Marker string to base the unique identifier generated by `extern_crate_hack()` on
static EXTERN_CRATE_HACK: &'static str = "__gfx_extern_crate_hack";

/// Inserts a module with a unique identifier that reexports
/// The `gfx` crate, and returns that identifier
fn extern_crate_hack(context: &mut ext::base::ExtCtxt,
                     span: codemap::Span,
                     push: |Gc<ast::Item>|) -> ast::Ident {
    let extern_crate_hack = token::gensym_ident(EXTERN_CRATE_HACK);
    // mod $EXTERN_CRATE_HACK {
    //     extern crate gfx_ = "gfx";
    //     pub use gfx_ as gfx;
    // }
    let item = context.item_mod(
        span,
        span,
        extern_crate_hack,
        vec![],
        vec![
            ast::ViewItem {
                span: span,
                vis: ast::Inherited,
                attrs: vec![],
                node: ast::ViewItemExternCrate(
                    context.ident_of("gfx_"),
                    Some((
                        token::InternedString::new("gfx"),
                        ast::CookedStr
                    )),
                    ast::DUMMY_NODE_ID
                )
            },
            context.view_use_simple_(
                span,
                ast::Public,
                context.ident_of("gfx"),
                context.path(span, vec![
                    context.ident_of("self"),
                    context.ident_of("gfx_")
                ])
            )
        ],
        vec![]
    );
    push(item);
    extern_crate_hack
}

/// This Folder gets used to fixup all paths generated by the
/// deriving trait impl to point to the unique module
/// containing the `gfx` reexport.
struct ExternCrateHackFolder {
    path_root: ast::Ident
}

impl Folder for ExternCrateHackFolder {
    fn fold_path(&mut self, p: &ast::Path) -> ast::Path {
        let p = syntax::fold::noop_fold_path(p, self);
        let needs_fix = p.segments.as_slice().get(0)
                         .map(|s| s.identifier.as_str() == EXTERN_CRATE_HACK)
                         .unwrap_or(false);
        let needs_fix_self = p.segments.as_slice().get(0)
                              .map(|s| s.identifier.as_str() == "self")
                              .unwrap_or(false) &&
                             p.segments.as_slice().get(1)
                              .map(|s| s.identifier.as_str() == EXTERN_CRATE_HACK)
                              .unwrap_or(false);

        if needs_fix {
            let mut p = p.clone();
            p.segments.get_mut(0).identifier = self.path_root;
            p.global = false;
            p
        } else if needs_fix_self {
            let mut p = p.clone();
            p.segments.get_mut(1).identifier = self.path_root;
            p.global = false;
            p
        } else {
            p
        }

    }
}

/// Simply applies the `ExternCrateHackFolder`
fn fixup_extern_crate_paths(item: Gc<ast::Item>, path_root: ast::Ident) -> Gc<ast::Item> {
    ExternCrateHackFolder {
        path_root: path_root
    }.fold_item(item).move_iter().next().unwrap()
}

// The `gfx` reexport module here does not need a unique name,
// as it gets inserted in a new block and thus doesn't conflict with
// any names outside its lexical scope.
#[macro_export]
macro_rules! shaders {
    (GLSL_120: $v:expr $($t:tt)*) => {
        {
            mod __gfx_extern_crate_hack {
                extern crate "gfx" as gfx_;
                pub use self::gfx_ as gfx;
            }
            __gfx_extern_crate_hack::gfx::ShaderSource {
                glsl_120: Some(__gfx_extern_crate_hack::gfx::StaticBytes($v)),
                ..shaders!($($t)*)
            }
        }
    };
    (GLSL_150: $v:expr $($t:tt)*) => {
        {
            mod __gfx_extern_crate_hack {
                extern crate "gfx" as gfx_;
                pub use self::gfx_ as gfx;
            }
            __gfx_extern_crate_hack::gfx::ShaderSource {
                glsl_150: Some(__gfx_extern_crate_hack::gfx::StaticBytes($v)),
                ..shaders!($($t)*)
            }
        }
    };
    () => {
        {
            mod __gfx_extern_crate_hack {
                extern crate "gfx" as gfx_;
                pub use self::gfx_ as gfx;
            }
            __gfx_extern_crate_hack::gfx::ShaderSource {
                glsl_120: None,
                glsl_150: None,
            }
        }
    }
}
<commit_msg>Update to nightly<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_name = "gfx_macros"]
#![comment = "Helper macros for gfx-rs"]
#![license = "ASL2"]
#![crate_type = "dylib"]

#![feature(macro_rules, plugin_registrar, quote)]

//! Macro extensions crate.
//! Implements `shaders!` macro as well as `#[shader_param]` and
//! `#[vertex_format]` attributes.

extern crate rustc;
extern crate syntax;

use syntax::{ast, attr, ext, codemap};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::fold::Folder;
use std::gc::Gc;

pub mod shader_param;
pub mod vertex_format;

/// Entry point for the plugin phase
#[plugin_registrar]
pub fn registrar(reg: &mut rustc::plugin::Registry) {
    use syntax::parse::token::intern;
    use syntax::ext::base;
    // Register the `#[shader_param]` attribute.
    reg.register_syntax_extension(intern("shader_param"),
        base::ItemDecorator(box shader_param::expand));
    // Register the `#[vertex_format]` attribute.
    reg.register_syntax_extension(intern("vertex_format"),
        base::ItemDecorator(box vertex_format::expand));
}

/// A hacky thing to get around 'moved value' errors when using `quote_expr!`
/// with `ext::base::ExtCtxt`s.
fn ugh<T, U>(x: &mut T, f: |&mut T| -> U) -> U { f(x) }

/// Scan through the field's attributes and extract the field vertex name. If
/// multiple names are found, use the first name and emit a warning.
fn find_name(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
             attributes: &[ast::Attribute]) -> Option<token::InternedString> {
    attributes.iter().fold(None, |name, attribute| {
        match attribute.node.value.node {
            ast::MetaNameValue(ref attr_name, ref attr_value) => {
                match (attr_name.get(), &attr_value.node) {
                    ("name", &ast::LitStr(ref new_name, _)) => {
                        attr::mark_used(attribute);
                        name.map_or(Some(new_name.clone()), |name| {
                            cx.span_warn(span, format!(
                                "Extra field name detected: {} - \
                                ignoring in favour of: {}", new_name, name
                            ).as_slice());
                            None
                        })
                    }
                    _ => None,
                }
            }
            _ => name,
        }
    })
}

/// Marker string to base the unique identifier generated by `extern_crate_hack()` on
static EXTERN_CRATE_HACK: &'static str = "__gfx_extern_crate_hack";

/// Inserts a module with a unique identifier that reexports
/// The `gfx` crate, and returns that identifier
fn extern_crate_hack(context: &mut ext::base::ExtCtxt,
                     span: codemap::Span,
                     push: |Gc<ast::Item>|) -> ast::Ident {
    let extern_crate_hack = token::gensym_ident(EXTERN_CRATE_HACK);
    // mod $EXTERN_CRATE_HACK {
    //     extern crate gfx_ = "gfx";
    //     pub use gfx_ as gfx;
    // }
    let item = context.item_mod(
        span,
        span,
        extern_crate_hack,
        vec![],
        vec![
            ast::ViewItem {
                span: span,
                vis: ast::Inherited,
                attrs: vec![],
                node: ast::ViewItemExternCrate(
                    context.ident_of("gfx_"),
                    Some((
                        token::InternedString::new("gfx"),
                        ast::CookedStr
                    )),
                    ast::DUMMY_NODE_ID
                )
            },
            context.view_use_simple_(
                span,
                ast::Public,
                context.ident_of("gfx"),
                context.path(span, vec![
                    context.ident_of("self"),
                    context.ident_of("gfx_")
                ])
            )
        ],
        vec![]
    );
    push(item);
    extern_crate_hack
}

/// This Folder gets used to fixup all paths generated by the
/// deriving trait impl to point to the unique module
/// containing the `gfx` reexport.
struct ExternCrateHackFolder {
    path_root: ast::Ident
}

impl Folder for ExternCrateHackFolder {
    fn fold_path(&mut self, p: &ast::Path) -> ast::Path {
        let p = syntax::fold::noop_fold_path(p, self);
        let needs_fix = p.segments.as_slice().get(0)
                         .map(|s| s.identifier.as_str() == EXTERN_CRATE_HACK)
                         .unwrap_or(false);
        let needs_fix_self = p.segments.as_slice().get(0)
                              .map(|s| s.identifier.as_str() == "self")
                              .unwrap_or(false) &&
                             p.segments.as_slice().get(1)
                              .map(|s| s.identifier.as_str() == EXTERN_CRATE_HACK)
                              .unwrap_or(false);

        if needs_fix {
            let mut p = p.clone();
            p.segments.get_mut(0).identifier = self.path_root;
            p.global = false;
            p
        } else if needs_fix_self {
            let mut p = p.clone();
            p.segments.get_mut(1).identifier = self.path_root;
            p.global = false;
            p
        } else {
            p
        }

    }
}

/// Simply applies the `ExternCrateHackFolder`
fn fixup_extern_crate_paths(item: Gc<ast::Item>, path_root: ast::Ident) -> Gc<ast::Item> {
    ExternCrateHackFolder {
        path_root: path_root
    }.fold_item(item).move_iter().next().unwrap()
}

// The `gfx` reexport module here does not need a unique name,
// as it gets inserted in a new block and thus doesn't conflict with
// any names outside its lexical scope.
#[macro_export]
macro_rules! shaders {
    (GLSL_120: $v:expr $($t:tt)*) => {
        {
            mod __gfx_extern_crate_hack {
                extern crate "gfx" as gfx_;
                pub use self::gfx_ as gfx;
            }
            __gfx_extern_crate_hack::gfx::ShaderSource {
                glsl_120: Some(__gfx_extern_crate_hack::gfx::StaticBytes($v)),
                ..shaders!($($t)*)
            }
        }
    };
    (GLSL_150: $v:expr $($t:tt)*) => {
        {
            mod __gfx_extern_crate_hack {
                extern crate "gfx" as gfx_;
                pub use self::gfx_ as gfx;
            }
            __gfx_extern_crate_hack::gfx::ShaderSource {
                glsl_150: Some(__gfx_extern_crate_hack::gfx::StaticBytes($v)),
                ..shaders!($($t)*)
            }
        }
    };
    () => {
        {
            mod __gfx_extern_crate_hack {
                extern crate "gfx" as gfx_;
                pub use self::gfx_ as gfx;
            }
            __gfx_extern_crate_hack::gfx::ShaderSource {
                glsl_120: None,
                glsl_150: None,
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Construction of dataflow for general graph motifs.
//!
//! A graph motif is a small graph on nodes which each correspond to variables. An instance of a motif in a larger graph
//! is a binding of graph nodes to these variables, so that for each edge in motif the corresponding edge between the bound
//! graph nodes exists in the graph.
//!
//! For example, we can describe a "triangle" as a motif on three variables, `x0`, `x1`, and `x2` with motif edges
//! `(x0, x1)`, `(x0,x2)`, and `(x1, x2)`. In a larger graph, each setting of these three variables so that the three edges
//! exist is an instance of the triangle motif.

use std::rc::Rc;
use std::cell::RefCell;

use timely::Data;
use timely::dataflow::*;
use timely::dataflow::operators::*;

use index::Index;
use extender::Indexable;
use ::{IndexStream, StreamPrefixExtender, GenericJoin};

/// Handles to the forward and reverse graph indices.
pub struct GraphStreamIndexHandle<T> {
    forward: Rc<RefCell<Index<u32, T>>>,
    reverse: Rc<RefCell<Index<u32, T>>>,
}

impl<T: Ord+Clone+::std::fmt::Debug> GraphStreamIndexHandle<T> {
    /// Merges both handles up to the specified time, compacting their representations.
    pub fn merge_to(&self, time: &T) {
        self.forward.borrow_mut().merge_to(time);
        self.reverse.borrow_mut().merge_to(time);
    }
}

/// Indices and updates for a graph stream.
pub struct GraphStreamIndex<G: Scope>
    where G::Timestamp: Ord+::std::hash::Hash {
    updates: Stream<G, ((u32, u32), i32)>,
    forward: IndexStream<G>,
    reverse: IndexStream<G>,
}

impl<G: Scope> GraphStreamIndex<G> where G::Timestamp: Ord+::std::hash::Hash {

    /// Constructs a new graph stream index from initial edges and an update stream.
    pub fn from(initially: Stream<G, (u32, u32)>,
                updates: Stream<G, ((u32, u32), i32)>) -> (Self, GraphStreamIndexHandle<G::Timestamp>) {
        let (forward, f_handle) = updates.index_from(&initially);
        let (reverse, r_handle) = updates.map(|((src,dst),wgt)| ((dst,src),wgt))
                                         .index_from(&initially.map(|(src,dst)| (dst,src)));
        let index = GraphStreamIndex {
            updates: updates,
            forward: forward,
            reverse: reverse,
        };
        let handles = GraphStreamIndexHandle {
            forward: f_handle,
            reverse: r_handle,
        };
        (index, handles)
    }

    /// Constructs a dataflow subgraph to track a described motif.
    pub fn track_motif<'a>(&self, description: &[(usize, usize)]) -> Stream<G, (Vec<u32>, i32)> where G: 'a {
        let mut result: Option<Stream<G, (Vec<u32>, i32)>> = None;
        for relation in 0 .. description.len() {
            let stream = self.relation_update(relation, &description);
            result = result.map(|x| x.concat(&stream)).or(Some(stream));
        }
        result.unwrap()
    }
}

trait Indexable64 {
    fn index(&self, index: usize) -> u64;
}

impl Indexable64 for Vec<u32> {
    fn index(&self, index: usize) -> u64 { self[index] as u64 }
}
impl Indexable64 for [u32; 2] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }
impl Indexable64 for [u32; 3] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }
impl Indexable64 for [u32; 4] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }
impl Indexable64 for [u32; 5] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }

impl<G: Scope> GraphStreamIndex<G> where G::Timestamp: Ord+::std::hash::Hash {

    // produces updates for changes in the indicated relation only.
    fn relation_update<'a>(&self, relation: usize, relations: &[(usize, usize)]) -> Stream<G, (Vec<u32>, i32)>
        where G: 'a {

        // we need to determine an order on the attributes that ensures that each are bound by preceding attributes.
        let (attrs, _remap, relations) = order_attributes(relation, &relations);
        let query_plan = plan_query(&relations, relation);

        // we do the first extension using arrays rather than vecs, to prove a point.
        let stream = self.updates.map(|((x,y),w)| ([x, y], w));
        let mut stream = self.extend_attribute(&stream, &query_plan[0])
                             .flat_map(|(p, es, w)|
                                    es.into_iter().map(move |e|  {
                                        (vec![p[0], p[1], e], w)
                                    })
                             );

        // now stream contains vecs, and so we use vec extensions4.
        for stage in &query_plan[1..] {
            stream = self.extend_attribute(&stream, &stage)
                         .flat_map(|(p, es, w)|
                                es.into_iter().map(move |e|  {
                                   let mut clone = p.clone();
                                   clone.push(e);
                                   (clone, w)
                                })
                           );
        }

        // undo the attribute re-ordering.
        stream.map(move |(vec, w)| {
            let mut new_vec = vec![0; vec.len()];
            for (index, &val) in vec.iter().enumerate() {
                new_vec[attrs[index]] = val;
            }
            (new_vec, w)
        })
    }
    /// Extends an indexable prefix, using a plan described by several (attr, is_forward, is_prior) cues.
    fn extend_attribute<'a, P>(&self, stream: &Stream<G, (P, i32)>, plan: &[(usize, bool, bool)]) -> Stream<G, (P, Vec<u32>, i32)>
        where G: 'a,
              P: ::std::fmt::Debug+Data+Indexable64 {
        let mut extenders: Vec<Box<StreamPrefixExtender<G, Prefix=P, Extension=u32>+'a>> = vec![];
        for &(attribute, is_forward, prior) in plan {
            extenders.push(match (is_forward, prior) {
                (true, true)    => Box::new(self.forward.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.le(t2))),
                (true, false)   => Box::new(self.forward.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.lt(t2))),
                (false, true)   => Box::new(self.reverse.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.le(t2))),
                (false, false)  => Box::new(self.reverse.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.lt(t2))),
            })
        }
        stream.extend(extenders)
    }
}

// orders the numbers 0 .. so that each has at least one relation binding it to a prior attribute,
// starting from those found in `query`.
fn order_attributes(relation_index: usize, relations: &[(usize, usize)]) -> (Vec<usize>, Vec<usize>, Vec<(usize, usize)>) {

	// 1. Determine an order on the attributes.
	//    The order may not introduce an attribute until it is are constrained by at least one relation to an existing attribute.
	//    The order may otherwise be arbitrary, for example selecting the most constrained attribute first.
	//    Presently, we just pick attributes arbitrarily.
    let mut active = vec![];
    active.push(relations[relation_index].0);
    active.push(relations[relation_index].1);

    let mut done = false;
    while !done {
        done = true;
        for &(src, dst) in relations {
            if active.contains(&src) && !active.contains(&dst) {
                active.push(dst);
                done = false;
            }
            if active.contains(&dst) && !active.contains(&src) {
                active.push(src);
                done = false;
            }
        }
    }

    // 2. Re-map each of the relations to treat attributes in order, avoiding weird re-indexing later on.
    let mut relabel = vec![0; active.len()];
    for (position, &attribute) in active.iter().enumerate() {
    	relabel[attribute] = position;
    }

    let relations = relations.iter().map(|&(src,dst)| (relabel[src], relabel[dst])).collect::<Vec<_>>();

    // 3. Return the attribute order, the relabeling, and the relabeled relations
    (active, relabel, relations)
}

/// Determines constraints on each of a sequence of attributes.
///
/// Given relations on attributes, presumed to be introduced in increasing order, this method identifies
/// for each attribute the constraints on it in terms of triples of
///    1. prior attributes,
///    2. which index is required (forward: true, reverse: false), and
///    3. whether the relation comes before or after `source_index`.
fn plan_query(relations: &[(usize, usize)], source_index: usize) -> Vec<Vec<(usize, bool, bool)>> {

	let mut attributes = 0;
	for &(src,dst) in relations {
		if attributes < src { attributes = src; }
		if attributes < dst { attributes = dst; }
	}
	attributes += 1;

	// for each attribute, determine relations constraining that attribute.
	let mut plan = vec![];
	for attribute in 2 .. attributes {
		let mut constraints = vec![];
		for (index, &(src, dst)) in relations.iter().enumerate() {
			// if src is our attribute and dst is already bound ...
			if src == attribute && dst < attribute {
				constraints.push((dst, false, index < source_index));
			}
			// if dst is our attribute and src is already bound ...
			if dst == attribute && src < attribute {
				constraints.push((src, true, index < source_index));
			}
		}
		plan.push(constraints);
	}

	plan
}<commit_msg>reworked to crash less on trivial motifs<commit_after>//! Construction of dataflow for general graph motifs.
//!
//! A graph motif is a small graph on nodes which each correspond to variables. An instance of a motif in a larger graph
//! is a binding of graph nodes to these variables, so that for each edge in motif the corresponding edge between the bound
//! graph nodes exists in the graph.
//!
//! For example, we can describe a "triangle" as a motif on three variables, `x0`, `x1`, and `x2` with motif edges
//! `(x0, x1)`, `(x0,x2)`, and `(x1, x2)`. In a larger graph, each setting of these three variables so that the three edges
//! exist is an instance of the triangle motif.

use std::rc::Rc;
use std::cell::RefCell;

use timely::Data;
use timely::dataflow::*;
use timely::dataflow::operators::*;

use index::Index;
use extender::Indexable;
use ::{IndexStream, StreamPrefixExtender, GenericJoin};

/// Handles to the forward and reverse graph indices.
pub struct GraphStreamIndexHandle<T> {
    forward: Rc<RefCell<Index<u32, T>>>,
    reverse: Rc<RefCell<Index<u32, T>>>,
}

impl<T: Ord+Clone+::std::fmt::Debug> GraphStreamIndexHandle<T> {
    /// Merges both handles up to the specified time, compacting their representations.
    pub fn merge_to(&self, time: &T) {
        self.forward.borrow_mut().merge_to(time);
        self.reverse.borrow_mut().merge_to(time);
    }
}

/// Indices and updates for a graph stream.
pub struct GraphStreamIndex<G: Scope>
    where G::Timestamp: Ord+::std::hash::Hash {
    updates: Stream<G, ((u32, u32), i32)>,
    forward: IndexStream<G>,
    reverse: IndexStream<G>,
}

impl<G: Scope> GraphStreamIndex<G> where G::Timestamp: Ord+::std::hash::Hash {

    /// Constructs a new graph stream index from initial edges and an update stream.
    pub fn from(initially: Stream<G, (u32, u32)>,
                updates: Stream<G, ((u32, u32), i32)>) -> (Self, GraphStreamIndexHandle<G::Timestamp>) {
        let (forward, f_handle) = updates.index_from(&initially);
        let (reverse, r_handle) = updates.map(|((src,dst),wgt)| ((dst,src),wgt))
                                         .index_from(&initially.map(|(src,dst)| (dst,src)));
        let index = GraphStreamIndex {
            updates: updates,
            forward: forward,
            reverse: reverse,
        };
        let handles = GraphStreamIndexHandle {
            forward: f_handle,
            reverse: r_handle,
        };
        (index, handles)
    }

    /// Constructs a dataflow subgraph to track a described motif.
    pub fn track_motif<'a>(&self, description: &[(usize, usize)]) -> Stream<G, (Vec<u32>, i32)> where G: 'a {
        let mut result = self.updates.filter(|_| false).map(|_| (Vec::new(), 0));
        for relation in 0 .. description.len() {
            result = result.concat(&self.relation_update(relation, &description));
        }
        result
    }
}

trait Indexable64 {
    fn index(&self, index: usize) -> u64;
}

impl Indexable64 for Vec<u32> {
    fn index(&self, index: usize) -> u64 { self[index] as u64 }
}
impl Indexable64 for [u32; 2] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }
impl Indexable64 for [u32; 3] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }
impl Indexable64 for [u32; 4] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }
impl Indexable64 for [u32; 5] { fn index(&self, index: usize) -> u64 { self[index] as u64 } }

impl<G: Scope> GraphStreamIndex<G> where G::Timestamp: Ord+::std::hash::Hash {

    // produces updates for changes in the indicated relation only.
    fn relation_update<'a>(&self, relation: usize, relations: &[(usize, usize)]) -> Stream<G, (Vec<u32>, i32)>
        where G: 'a {

        // we need to determine an order on the attributes that ensures that each are bound by preceding attributes.
        let (attrs, _remap, relations) = order_attributes(relation, &relations);
        let query_plan = plan_query(&relations, relation);

        let source = self.updates.map(|((x,y),w)| ([x, y], w));
        let stream = if query_plan.len() > 0 {

            // we do the first extension using arrays rather than vecs, to prove a point.
            let mut stream = self.extend_attribute(&source, &query_plan[0])
                                 .flat_map(|(p, es, w)| es.into_iter().map(move |e| (vec![p[0], p[1], e], w)));

            // now stream contains vecs, and so we use vec extensions4.
            for stage in &query_plan[1..] {
                stream = self.extend_attribute(&stream, &stage)
                             .flat_map(|(p, es, w)|
                                    es.into_iter().map(move |e|  {
                                       let mut clone = p.clone();
                                       clone.push(e);
                                       (clone, w)
                                    }));
            }

            stream
        }
        else {
            source.map(|p| (vec![p.0[0], p.0[1]], p.1))
        };

        // undo the attribute re-ordering.
        stream.map(move |(vec, w)| {
            let mut new_vec = vec![0; vec.len()];
            for (index, &val) in vec.iter().enumerate() {
                new_vec[attrs[index]] = val;
            }
            (new_vec, w)
        })
    }
    /// Extends an indexable prefix, using a plan described by several (attr, is_forward, is_prior) cues.
    fn extend_attribute<'a, P>(&self, stream: &Stream<G, (P, i32)>, plan: &[(usize, bool, bool)]) -> Stream<G, (P, Vec<u32>, i32)>
        where G: 'a,
              P: ::std::fmt::Debug+Data+Indexable64 {
        let mut extenders: Vec<Box<StreamPrefixExtender<G, Prefix=P, Extension=u32>+'a>> = vec![];
        for &(attribute, is_forward, prior) in plan {
            extenders.push(match (is_forward, prior) {
                (true, true)    => Box::new(self.forward.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.le(t2))),
                (true, false)   => Box::new(self.forward.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.lt(t2))),
                (false, true)   => Box::new(self.reverse.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.le(t2))),
                (false, false)  => Box::new(self.reverse.extend_using(move |x: &P| x.index(attribute), |t1, t2| t1.lt(t2))),
            })
        }
        stream.extend(extenders)
    }
}

// orders the numbers 0 .. so that each has at least one relation binding it to a prior attribute,
// starting from those found in `query`.
fn order_attributes(relation_index: usize, relations: &[(usize, usize)]) -> (Vec<usize>, Vec<usize>, Vec<(usize, usize)>) {

	// 1. Determine an order on the attributes.
	//    The order may not introduce an attribute until it is are constrained by at least one relation to an existing attribute.
	//    The order may otherwise be arbitrary, for example selecting the most constrained attribute first.
	//    Presently, we just pick attributes arbitrarily.
    let mut active = vec![];
    active.push(relations[relation_index].0);
    active.push(relations[relation_index].1);

    let mut done = false;
    while !done {
        done = true;
        for &(src, dst) in relations {
            if active.contains(&src) && !active.contains(&dst) {
                active.push(dst);
                done = false;
            }
            if active.contains(&dst) && !active.contains(&src) {
                active.push(src);
                done = false;
            }
        }
    }

    // 2. Re-map each of the relations to treat attributes in order, avoiding weird re-indexing later on.
    let mut relabel = vec![0; active.len()];
    for (position, &attribute) in active.iter().enumerate() {
    	relabel[attribute] = position;
    }

    let relations = relations.iter().map(|&(src,dst)| (relabel[src], relabel[dst])).collect::<Vec<_>>();

    // 3. Return the attribute order, the relabeling, and the relabeled relations
    (active, relabel, relations)
}

/// Determines constraints on each of a sequence of attributes.
///
/// Given relations on attributes, presumed to be introduced in increasing order, this method identifies
/// for each attribute the constraints on it in terms of triples of
///    1. prior attributes,
///    2. which index is required (forward: true, reverse: false), and
///    3. whether the relation comes before or after `source_index`.
fn plan_query(relations: &[(usize, usize)], source_index: usize) -> Vec<Vec<(usize, bool, bool)>> {

	let mut attributes = 0;
	for &(src,dst) in relations {
		if attributes < src { attributes = src; }
		if attributes < dst { attributes = dst; }
	}
	attributes += 1;

	// for each attribute, determine relations constraining that attribute.
	let mut plan = vec![];
	for attribute in 2 .. attributes {
		let mut constraints = vec![];
		for (index, &(src, dst)) in relations.iter().enumerate() {
			// if src is our attribute and dst is already bound ...
			if src == attribute && dst < attribute {
				constraints.push((dst, false, index < source_index));
			}
			// if dst is our attribute and src is already bound ...
			if dst == attribute && src < attribute {
				constraints.push((src, true, index < source_index));
			}
		}
		plan.push(constraints);
	}

	plan
}<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use lock_api;
use raw_mutex::RawMutex;

/// A mutual exclusion primitive useful for protecting shared data
///
/// This mutex will block threads waiting for the lock to become available. The
/// mutex can also be statically initialized or created via a `new`
/// constructor. Each mutex has a type parameter which represents the data that
/// it is protecting. The data can only be accessed through the RAII guards
/// returned from `lock` and `try_lock`, which guarantees that the data is only
/// ever accessed when the mutex is locked.
///
/// # Fairness
///
/// A typical unfair lock can often end up in a situation where a single thread
/// quickly acquires and releases the same mutex in succession, which can starve
/// other threads waiting to acquire the mutex. While this improves performance
/// because it doesn't force a context switch when a thread tries to re-acquire
/// a mutex it has just released, this can starve other threads.
///
/// This mutex uses [eventual fairness](https://trac.webkit.org/changeset/203350)
/// to ensure that the lock will be fair on average without sacrificing
/// performance. This is done by forcing a fair unlock on average every 0.5ms,
/// which will force the lock to go to the next thread waiting for the mutex.
///
/// Additionally, any critical section longer than 1ms will always use a fair
/// unlock, which has a negligible performance impact compared to the length of
/// the critical section.
///
/// You can also force a fair unlock by calling `MutexGuard::unlock_fair` when
/// unlocking a mutex instead of simply dropping the `MutexGuard`.
///
/// # Differences from the standard library `Mutex`
///
/// - No poisoning, the lock is released normally on panic.
/// - Only requires 1 byte of space, whereas the standard library boxes the
///   `Mutex` due to platform limitations.
/// - Can be statically constructed (requires the `const_fn` nightly feature).
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
/// - Efficient handling of micro-contention using adaptive spinning.
/// - Allows raw locking & unlocking without a guard.
/// - Supports eventual fairness so that the mutex is fair on average.
/// - Optionally allows making the mutex fair by calling `MutexGuard::unlock_fair`.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use parking_lot::Mutex;
/// use std::thread;
/// use std::sync::mpsc::channel;
///
/// const N: usize = 10;
///
/// // Spawn a few threads to increment a shared variable (non-atomically), and
/// // let the main thread know once all increments are done.
/// //
/// // Here we're using an Arc to share memory among threads, and the data inside
/// // the Arc is protected with a mutex.
/// let data = Arc::new(Mutex::new(0));
///
/// let (tx, rx) = channel();
/// for _ in 0..10 {
///     let (data, tx) = (data.clone(), tx.clone());
///     thread::spawn(move || {
///         // The shared state can only be accessed once the lock is held.
///         // Our non-atomic increment is safe because we're the only thread
///         // which can access the shared state when the lock is held.
///         let mut data = data.lock();
///         *data += 1;
///         if *data == N {
///             tx.send(()).unwrap();
///         }
///         // the lock is unlocked here when `data` goes out of scope.
///     });
/// }
///
/// rx.recv().unwrap();
/// ```
pub type Mutex<T> = lock_api::Mutex<RawMutex, T>;

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// `Deref` and `DerefMut` implementations.
pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, RawMutex, T>;

/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
/// subfield of the protected data.
///
/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the
/// former doesn't support temporarily unlocking and re-locking, since that
/// could introduce soundness issues if the locked object is modified by another
/// thread.
pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>;

#[cfg(test)]
mod tests {
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::sync::mpsc::channel;
    use std::sync::Arc;
    use std::thread;
    use {Condvar, Mutex};

    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    unsafe impl<T: Send> Send for Packet<T> {}
    unsafe impl<T> Sync for Packet<T> {}

    #[test]
    fn smoke() {
        let m = Mutex::new(());
        drop(m.lock());
        drop(m.lock());
    }

    #[test]
    fn lots_and_lots() {
        const J: u32 = 1000;
        const K: u32 = 3;

        let m = Arc::new(Mutex::new(0));

        fn inc(m: &Mutex<u32>) {
            for _ in 0..J {
                *m.lock() += 1;
            }
        }

        let (tx, rx) = channel();
        for _ in 0..K {
            let tx2 = tx.clone();
            let m2 = m.clone();
            thread::spawn(move || {
                inc(&m2);
                tx2.send(()).unwrap();
            });
            let tx2 = tx.clone();
            let m2 = m.clone();
            thread::spawn(move || {
                inc(&m2);
                tx2.send(()).unwrap();
            });
        }

        drop(tx);
        for _ in 0..2 * K {
            rx.recv().unwrap();
        }
        assert_eq!(*m.lock(), J * K * 2);
    }

    #[test]
    fn try_lock() {
        let m = Mutex::new(());
        *m.try_lock().unwrap() = ();
    }

    #[test]
    fn test_into_inner() {
        let m = Mutex::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = Mutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_get_mut() {
        let mut m = Mutex::new(NonCopy(10));
        *m.get_mut() = NonCopy(20);
        assert_eq!(m.into_inner(), NonCopy(20));
    }

    #[test]
    fn test_mutex_arc_condvar() {
        let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
        let packet2 = Packet(packet.0.clone());
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            // wait until parent gets in
            rx.recv().unwrap();
            let &(ref lock, ref cvar) = &*packet2.0;
            let mut lock = lock.lock();
            *lock = true;
            cvar.notify_one();
        });

        let &(ref lock, ref cvar) = &*packet.0;
        let mut lock = lock.lock();
        tx.send(()).unwrap();
        assert!(!*lock);
        while !*lock {
            cvar.wait(&mut lock);
        }
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
        let arc = Arc::new(Mutex::new(1));
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            let lock = arc2.lock();
            let lock2 = lock.lock();
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move || -> () {
            struct Unwinder {
                i: Arc<Mutex<i32>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    *self.i.lock() += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
        })
        .join();
        let lock = arc.lock();
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_mutex_unsized() {
        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
        {
            let b = &mut *mutex.lock();
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*mutex.lock(), comp);
    }

    #[test]
    fn test_mutexguard_sync() {
        fn sync<T: Sync>(_: T) {}

        let mutex = Mutex::new(());
        sync(mutex.lock());
    }

    #[test]
    fn test_mutex_debug() {
        let mutex = Mutex::new(vec![0u8, 10]);

        assert_eq!(format!("{:?}", mutex), "Mutex { data: [0, 10] }");
        assert_eq!(
            format!("{:#?}", mutex),
            "Mutex {
    data: [
        0,
        10
    ]
}"
        );
        let _lock = mutex.lock();
        assert_eq!(format!("{:?}", mutex), "Mutex { data: <locked> }");
    }
}
<commit_msg>Update example in Mutex<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use lock_api;
use raw_mutex::RawMutex;

/// A mutual exclusion primitive useful for protecting shared data
///
/// This mutex will block threads waiting for the lock to become available. The
/// mutex can also be statically initialized or created via a `new`
/// constructor. Each mutex has a type parameter which represents the data that
/// it is protecting. The data can only be accessed through the RAII guards
/// returned from `lock` and `try_lock`, which guarantees that the data is only
/// ever accessed when the mutex is locked.
///
/// # Fairness
///
/// A typical unfair lock can often end up in a situation where a single thread
/// quickly acquires and releases the same mutex in succession, which can starve
/// other threads waiting to acquire the mutex. While this improves performance
/// because it doesn't force a context switch when a thread tries to re-acquire
/// a mutex it has just released, this can starve other threads.
///
/// This mutex uses [eventual fairness](https://trac.webkit.org/changeset/203350)
/// to ensure that the lock will be fair on average without sacrificing
/// performance. This is done by forcing a fair unlock on average every 0.5ms,
/// which will force the lock to go to the next thread waiting for the mutex.
///
/// Additionally, any critical section longer than 1ms will always use a fair
/// unlock, which has a negligible performance impact compared to the length of
/// the critical section.
///
/// You can also force a fair unlock by calling `MutexGuard::unlock_fair` when
/// unlocking a mutex instead of simply dropping the `MutexGuard`.
///
/// # Differences from the standard library `Mutex`
///
/// - No poisoning, the lock is released normally on panic.
/// - Only requires 1 byte of space, whereas the standard library boxes the
///   `Mutex` due to platform limitations.
/// - Can be statically constructed (requires the `const_fn` nightly feature).
/// - Does not require any drop glue when dropped.
/// - Inline fast path for the uncontended case.
/// - Efficient handling of micro-contention using adaptive spinning.
/// - Allows raw locking & unlocking without a guard.
/// - Supports eventual fairness so that the mutex is fair on average.
/// - Optionally allows making the mutex fair by calling `MutexGuard::unlock_fair`.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use parking_lot::Mutex;
/// use std::thread;
/// use std::sync::mpsc::channel;
///
/// const N: usize = 10;
///
/// // Spawn a few threads to increment a shared variable (non-atomically), and
/// // let the main thread know once all increments are done.
/// //
/// // Here we're using an Arc to share memory among threads, and the data inside
/// // the Arc is protected with a mutex.
/// let data = Arc::new(Mutex::new(0));
///
/// let (tx, rx) = channel();
/// for _ in 0..10 {
///     let (data, tx) = (Arc::clone(&data), tx.clone());
///     thread::spawn(move || {
///         // The shared state can only be accessed once the lock is held.
///         // Our non-atomic increment is safe because we're the only thread
///         // which can access the shared state when the lock is held.
///         let mut data = data.lock();
///         *data += 1;
///         if *data == N {
///             tx.send(()).unwrap();
///         }
///         // the lock is unlocked here when `data` goes out of scope.
///     });
/// }
///
/// rx.recv().unwrap();
/// ```
pub type Mutex<T> = lock_api::Mutex<RawMutex, T>;

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// `Deref` and `DerefMut` implementations.
pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, RawMutex, T>;

/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
/// subfield of the protected data.
///
/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the
/// former doesn't support temporarily unlocking and re-locking, since that
/// could introduce soundness issues if the locked object is modified by another
/// thread.
pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>;

#[cfg(test)]
mod tests {
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::sync::mpsc::channel;
    use std::sync::Arc;
    use std::thread;
    use {Condvar, Mutex};

    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);

    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

    unsafe impl<T: Send> Send for Packet<T> {}
    unsafe impl<T> Sync for Packet<T> {}

    #[test]
    fn smoke() {
        let m = Mutex::new(());
        drop(m.lock());
        drop(m.lock());
    }

    #[test]
    fn lots_and_lots() {
        const J: u32 = 1000;
        const K: u32 = 3;

        let m = Arc::new(Mutex::new(0));

        fn inc(m: &Mutex<u32>) {
            for _ in 0..J {
                *m.lock() += 1;
            }
        }

        let (tx, rx) = channel();
        for _ in 0..K {
            let tx2 = tx.clone();
            let m2 = m.clone();
            thread::spawn(move || {
                inc(&m2);
                tx2.send(()).unwrap();
            });
            let tx2 = tx.clone();
            let m2 = m.clone();
            thread::spawn(move || {
                inc(&m2);
                tx2.send(()).unwrap();
            });
        }

        drop(tx);
        for _ in 0..2 * K {
            rx.recv().unwrap();
        }
        assert_eq!(*m.lock(), J * K * 2);
    }

    #[test]
    fn try_lock() {
        let m = Mutex::new(());
        *m.try_lock().unwrap() = ();
    }

    #[test]
    fn test_into_inner() {
        let m = Mutex::new(NonCopy(10));
        assert_eq!(m.into_inner(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = Mutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_get_mut() {
        let mut m = Mutex::new(NonCopy(10));
        *m.get_mut() = NonCopy(20);
        assert_eq!(m.into_inner(), NonCopy(20));
    }

    #[test]
    fn test_mutex_arc_condvar() {
        let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
        let packet2 = Packet(packet.0.clone());
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            // wait until parent gets in
            rx.recv().unwrap();
            let &(ref lock, ref cvar) = &*packet2.0;
            let mut lock = lock.lock();
            *lock = true;
            cvar.notify_one();
        });

        let &(ref lock, ref cvar) = &*packet.0;
        let mut lock = lock.lock();
        tx.send(()).unwrap();
        assert!(!*lock);
        while !*lock {
            cvar.wait(&mut lock);
        }
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
        let arc = Arc::new(Mutex::new(1));
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
        let _t = thread::spawn(move || {
            let lock = arc2.lock();
            let lock2 = lock.lock();
            assert_eq!(*lock2, 1);
            tx.send(()).unwrap();
        });
        rx.recv().unwrap();
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
        let arc = Arc::new(Mutex::new(1));
        let arc2 = arc.clone();
        let _ = thread::spawn(move || -> () {
            struct Unwinder {
                i: Arc<Mutex<i32>>,
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
                    *self.i.lock() += 1;
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
        })
        .join();
        let lock = arc.lock();
        assert_eq!(*lock, 2);
    }

    #[test]
    fn test_mutex_unsized() {
        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
        {
            let b = &mut *mutex.lock();
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*mutex.lock(), comp);
    }

    #[test]
    fn test_mutexguard_sync() {
        fn sync<T: Sync>(_: T) {}

        let mutex = Mutex::new(());
        sync(mutex.lock());
    }

    #[test]
    fn test_mutex_debug() {
        let mutex = Mutex::new(vec![0u8, 10]);

        assert_eq!(format!("{:?}", mutex), "Mutex { data: [0, 10] }");
        assert_eq!(
            format!("{:#?}", mutex),
            "Mutex {
    data: [
        0,
        10
    ]
}"
        );
        let _lock = mutex.lock();
        assert_eq!(format!("{:?}", mutex), "Mutex { data: <locked> }");
    }
}
<|endoftext|>


<commit_before>
use error::MpdResult;
use connection::{FromConn, MpdConnection, mpd_connection};
use songs::{MpdSong, MpdSongs, mpd_song};
use std::c_str::CString;
use libc::{c_uint, c_int, c_char};

extern {
    fn mpd_run_get_queue_song_pos(connection: *mut mpd_connection, pos: c_uint) -> *mut mpd_song;
    fn mpd_run_get_queue_song_id(connection: *mut mpd_connection, id: c_uint) -> *mut mpd_song;
    fn mpd_run_move_id(connection: *mut mpd_connection, from: c_uint, to: c_uint) -> bool;
    fn mpd_run_swap_id(connection: *mut mpd_connection, id1: c_uint, id2: c_uint) -> bool;
    fn mpd_run_swap(connection: *mut mpd_connection, pos1: c_uint, pos2: c_uint) -> bool;
    fn mpd_run_add_id(connection: *mut mpd_connection, file: *const c_char) -> c_int;
    fn mpd_run_add_id_to(connection: *mut mpd_connection, uri: *const c_char, to: c_uint) -> c_int;
    fn mpd_send_list_queue_meta(connection: *mut mpd_connection) -> bool;
    fn mpd_send_list_queue_range_meta(connection: *mut mpd_connection, start: c_uint, end: c_uint) -> bool;
}

pub struct MpdQueue<'a> {
    pub conn: &'a MpdConnection
}

impl<'a> MpdQueue<'a> {
    pub fn from_conn(conn: &'a MpdConnection) -> MpdQueue<'a> {
        MpdQueue { conn: conn }
    }

    pub fn get_by_id(&self, id: uint) -> MpdResult<MpdSong> {
        let song = unsafe { mpd_run_get_queue_song_id(self.conn.conn, id as c_uint) };
        if song.is_null() {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(MpdSong { song: song })
        }
    }

    pub fn get(&self, index: uint) -> MpdResult<MpdSong> {
        let song = unsafe { mpd_run_get_queue_song_pos(self.conn.conn, index as c_uint) };
        if song.is_null() {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(MpdSong { song: song })
        }
    }

    pub fn move_to(&mut self, pos: uint, song: &MpdSong) -> MpdResult<()> {
        if unsafe { mpd_run_move_id(self.conn.conn, song.id() as c_uint, pos as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    pub fn insert<T: ToSongUri>(&mut self, pos: uint, song: &T) -> MpdResult<uint> {
        let uid = unsafe { mpd_run_add_id_to(self.conn.conn, song.song_uri().as_ptr(), pos as c_uint) };
        if uid < 0 {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(uid as uint)
        }
    }

    pub fn push<T: ToSongUri>(&mut self, song: &T) -> MpdResult<uint> {
        let uid = unsafe { mpd_run_add_id(self.conn.conn, song.song_uri().as_ptr()) };
        if uid < 0 {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(uid as uint)
        }
    }

    pub fn swap_id(&mut self, song1: &MpdSong, song2: &MpdSong) -> MpdResult<()> {
        if unsafe { mpd_run_swap_id(self.conn.conn, song1.id() as c_uint, song2.id() as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    pub fn swap<T: ToSongPos>(&mut self, song1: T, song2: T) -> MpdResult<()> {
        if unsafe { mpd_run_swap(self.conn.conn, song1.song_pos() as c_uint, song2.song_pos() as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    pub fn songs(&self) -> MpdResult<MpdSongs> {
        if unsafe { mpd_send_list_queue_meta(self.conn.conn) } {
            Ok(MpdSongs { conn: self.conn })
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    pub fn songs_at(&self, start: uint, end: uint) -> MpdResult<MpdSongs> {
        if unsafe { mpd_send_list_queue_range_meta(self.conn.conn, start as c_uint, end as c_uint) } {
            Ok(MpdSongs { conn: self.conn })
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    pub fn len(&self) -> MpdResult<uint> {
        self.conn.status().map(|s| s.queue_len())
    }
}

pub trait ToSongPos {
    fn song_pos(&self) -> uint;
}

impl ToSongPos for uint {
    #[inline] fn song_pos(&self) -> uint { *self }
}

impl ToSongPos for MpdSong {
    #[inline] fn song_pos(&self) -> uint { self.pos() }
}

pub trait ToSongUri {
    fn song_uri(&self) -> CString;
}

impl ToSongUri for MpdSong {
    #[inline] fn song_uri(&self) -> CString {
        self.uri().to_c_str()
    }
}

impl ToSongUri for String {
    #[inline] fn song_uri(&self) -> CString {
        self.to_c_str()
    }
}
<commit_msg>queue interface unified<commit_after>
use error::MpdResult;
use connection::{FromConn, MpdConnection, mpd_connection};
use songs::{MpdSong, MpdSongs, mpd_song};
use std::c_str::CString;
use libc::{c_uint, c_int, c_char};

extern {
    fn mpd_run_get_queue_song_pos(connection: *mut mpd_connection, pos: c_uint) -> *mut mpd_song;
    fn mpd_run_get_queue_song_id(connection: *mut mpd_connection, id: c_uint) -> *mut mpd_song;
    fn mpd_run_move_id(connection: *mut mpd_connection, from: c_uint, to: c_uint) -> bool;
    fn mpd_run_move(connection: *mut mpd_connection, from: c_uint, to: c_uint) -> bool;
    fn mpd_run_move_range(connection: *mut mpd_connection, start: c_uint, end: c_uint, to: c_uint) -> bool;
    fn mpd_run_swap_id(connection: *mut mpd_connection, id1: c_uint, id2: c_uint) -> bool;
    fn mpd_run_swap(connection: *mut mpd_connection, pos1: c_uint, pos2: c_uint) -> bool;
    fn mpd_run_add_id(connection: *mut mpd_connection, file: *const c_char) -> c_int;
    fn mpd_run_add_id_to(connection: *mut mpd_connection, uri: *const c_char, to: c_uint) -> c_int;
    fn mpd_send_list_queue_meta(connection: *mut mpd_connection) -> bool;
    fn mpd_send_list_queue_range_meta(connection: *mut mpd_connection, start: c_uint, end: c_uint) -> bool;
    fn mpd_run_delete(connection: *mut mpd_connection, pos: c_uint) -> bool;
    fn mpd_run_delete_range(connection: *mut mpd_connection, start: c_uint, end: c_uint) -> bool;
    fn mpd_run_delete_id(connection: *mut mpd_connection, id: c_uint) -> bool;
}

pub struct MpdQueue<'a> {
    pub conn: &'a MpdConnection
}

impl<'a> MpdQueue<'a> {
    pub fn from_conn(conn: &'a MpdConnection) -> MpdQueue<'a> {
        MpdQueue { conn: conn }
    }

    /// Get song at some position in queue
    pub fn nth(&self, index: uint) -> MpdResult<MpdSong> {
        let song = unsafe { mpd_run_get_queue_song_pos(self.conn.conn, index as c_uint) };
        if song.is_null() {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(MpdSong { song: song })
        }
    }

    /// Get song by queue id
    pub fn get(&self, id: uint) -> MpdResult<MpdSong> {
        let song = unsafe { mpd_run_get_queue_song_id(self.conn.conn, id as c_uint) };
        if song.is_null() {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(MpdSong { song: song })
        }
    }

    /// Insert new song into queue at given position
    pub fn insert<T: ToSongUri>(&mut self, pos: uint, song: T) -> MpdResult<uint> {
        let uid = unsafe { mpd_run_add_id_to(self.conn.conn, song.song_uri().as_ptr(), pos as c_uint) };
        if uid < 0 {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(uid as uint)
        }
    }

    /// Add song at the end of the queue
    pub fn push<T: ToSongUri>(&mut self, song: T) -> MpdResult<uint> {
        let uid = unsafe { mpd_run_add_id(self.conn.conn, song.song_uri().as_ptr()) };
        if uid < 0 {
            Err(FromConn::from_conn(self.conn).unwrap())
        } else {
            Ok(uid as uint)
        }
    }

    /// Move song to some position in queue
    pub fn move_pos(&mut self, to: uint, from: uint) -> MpdResult<()> {
        if unsafe { mpd_run_move(self.conn.conn, from as c_uint, to as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Move songs in given range
    pub fn move_range(&mut self, pos: uint, start: uint, end: uint) -> MpdResult<()> {
        if unsafe { mpd_run_move_range(self.conn.conn, start as c_uint, end as c_uint, pos as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Move song to some position in queue by id
    pub fn move_to(&mut self, pos: uint, song: &MpdSong) -> MpdResult<()> {
        if unsafe { mpd_run_move_id(self.conn.conn, song.id() as c_uint, pos as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Swap two songs in given positions
    pub fn swap_pos(&mut self, song1: uint, song2: uint) -> MpdResult<()> {
        if unsafe { mpd_run_swap(self.conn.conn, song1 as c_uint, song2 as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Swap two songs in given positions by id
    pub fn swap(&mut self, song1: &MpdSong, song2: &MpdSong) -> MpdResult<()> {
        if unsafe { mpd_run_swap_id(self.conn.conn, song1.id() as c_uint, song2.id() as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Remove a song
    pub fn remove(&mut self, song: &MpdSong) -> MpdResult<()> {
        if unsafe { mpd_run_delete_id(self.conn.conn, song.id() as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Remove songs at given position
    pub fn remove_pos(&mut self, pos: uint) -> MpdResult<()> {
        if unsafe { mpd_run_delete(self.conn.conn, pos as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Remove songs in given range
    pub fn remove_range(&mut self, start: uint, end: uint) -> MpdResult<()> {
        if unsafe { mpd_run_delete_range(self.conn.conn, start as c_uint, end as c_uint) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Iterate over songs in the queue
    pub fn iter(&self) -> MpdResult<MpdSongs> {
        if unsafe { mpd_send_list_queue_meta(self.conn.conn) } {
            Ok(MpdSongs { conn: self.conn })
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Iterate over songs in given range
    pub fn iter_range(&self, start: uint, end: uint) -> MpdResult<MpdSongs> {
        if unsafe { mpd_send_list_queue_range_meta(self.conn.conn, start as c_uint, end as c_uint) } {
            Ok(MpdSongs { conn: self.conn })
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }

    /// Length of the queue
    pub fn len(&self) -> MpdResult<uint> {
        self.conn.status().map(|s| s.queue_len())
    }

    /// Returns true if queue is empty
    pub fn is_empty(&self) -> MpdResult<bool> {
        self.len().map(|v| v == 0)
    }
}

pub trait ToSongUri {
    fn song_uri(&self) -> CString;
}

impl ToSongUri for MpdSong {
    #[inline] fn song_uri(&self) -> CString {
        self.uri().to_c_str()
    }
}

impl<T: ToCStr> ToSongUri for T {
    #[inline] fn song_uri(&self) -> CString {
        self.to_c_str()
    }
}
<|endoftext|>