<commit_before>use alloc::arc::{Arc, Weak};
use collections::BTreeMap;
use core::sync::atomic::{AtomicU64, Ordering};
use core::{mem, slice, usize};
use spin::{Mutex, RwLock};

use arch;
use arch::paging::{InactivePageTable, Page, VirtualAddress, entry};
use arch::paging::temporary_page::TemporaryPage;
use context::{self, Context};
use context::memory::Grant;
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
use sync::{WaitQueue, WaitMap};
use syscall::data::{Packet, Stat, StatVfs};
use syscall::error::*;
use syscall::flag::{EVENT_READ, O_NONBLOCK};
use syscall::number::*;
use syscall::scheme::Scheme;

pub struct UserInner {
    root_id: SchemeId,
    handle_id: usize,
    flags: usize,
    pub scheme_id: AtomicSchemeId,
    next_id: AtomicU64,
    context: Weak<RwLock<Context>>,
    todo: WaitQueue<Packet>,
    fmap: Mutex<BTreeMap<u64, (Weak<RwLock<Context>>, usize)>>,
    done: WaitMap<u64, usize>
}

impl UserInner {
    pub fn new(root_id: SchemeId, handle_id: usize, flags: usize, context: Weak<RwLock<Context>>) -> UserInner {
        UserInner {
            root_id: root_id,
            handle_id: handle_id,
            flags: flags,
            scheme_id: ATOMIC_SCHEMEID_INIT,
            next_id: AtomicU64::new(1),
            context: context,
            todo: WaitQueue::new(),
            fmap: Mutex::new(BTreeMap::new()),
            done: WaitMap::new()
        }
    }

    pub fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        let (pid, uid, gid) = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            (context.id, context.euid, context.egid)
        };

        self.call_inner(Packet {
            id: self.next_id.fetch_add(1, Ordering::SeqCst),
            pid: pid.into(),
            uid: uid,
            gid: gid,
            a: a,
            b: b,
            c: c,
            d: d
        })
    }

    fn call_inner(&self, packet: Packet) -> Result<usize> {
        let id = packet.id;

        let len = self.todo.send(packet);
        context::event::trigger(self.root_id, self.handle_id, EVENT_READ, mem::size_of::<Packet>() * len);

        Error::demux(self.done.receive(&id))
    }

    pub fn capture(&self, buf: &[u8]) -> Result<usize> {
        UserInner::capture_inner(&self.context, buf.as_ptr() as usize, buf.len(), false)
    }

    pub fn capture_mut(&self, buf: &mut [u8]) -> Result<usize> {
        UserInner::capture_inner(&self.context, buf.as_mut_ptr() as usize, buf.len(), true)
    }

    fn capture_inner(context_weak: &Weak<RwLock<Context>>, address: usize, size: usize, writable: bool) -> Result<usize> {
        if size == 0 {
            Ok(0)
        } else {
            let context_lock = context_weak.upgrade().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();

            let mut grants = context.grants.lock();

            let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) };
            let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET)));

            let from_address = (address/4096) * 4096;
            let offset = address - from_address;
            let full_size = ((offset + size + 4095)/4096) * 4096;
            let mut to_address = arch::USER_GRANT_OFFSET;

            let mut flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE;
            if writable {
                flags |= entry::WRITABLE;
            }

            for i in 0 .. grants.len() {
                let start = grants[i].start_address().get();
                if to_address + full_size < start {
                    {
                        let name = context.name.lock();
                        println!("{}: {}: Can grant {:X} to {:X} size {}", context.id.into(), ::core::str::from_utf8(&name).unwrap_or(""), from_address, to_address, full_size);
                    }
                    grants.insert(i, Grant::map_inactive(
                        VirtualAddress::new(from_address),
                        VirtualAddress::new(to_address),
                        full_size,
                        flags,
                        &mut new_table,
                        &mut temporary_page
                    ));

                    return Ok(to_address + offset);
                } else {
                    let pages = (grants[i].size() + 4095) / 4096;
                    let end = start + pages * 4096;
                    to_address = end;
                }
            }

            {
                let name = context.name.lock();
                println!("{}: {}: Can grant {:X} to {:X} size {}", context.id.into(), ::core::str::from_utf8(&name).unwrap_or(""), from_address, to_address, full_size);
            }
            grants.push(Grant::map_inactive(
                VirtualAddress::new(from_address),
                VirtualAddress::new(to_address),
                full_size,
                flags,
                &mut new_table,
                &mut temporary_page
            ));

            Ok(to_address + offset)
        }
    }

    pub fn release(&self, address: usize) -> Result<()> {
        if address == 0 {
            Ok(())
        } else {
            let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();

            let mut grants = context.grants.lock();

            let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) };
            let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET)));

            for i in 0 .. grants.len() {
                let start = grants[i].start_address().get();
                let end = start + grants[i].size();
                if address >= start && address < end {
                    grants.remove(i).unmap_inactive(&mut new_table, &mut temporary_page);

                    return Ok(());
                }
            }

            Err(Error::new(EFAULT))
        }
    }

    pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
        let packet_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Packet, buf.len()/mem::size_of::<Packet>()) };
        Ok(self.todo.receive_into(packet_buf, self.flags & O_NONBLOCK != O_NONBLOCK) * mem::size_of::<Packet>())
    }

    pub fn write(&self, buf: &[u8]) -> Result<usize> {
        let packet_size = mem::size_of::<Packet>();
        let len = buf.len()/packet_size;
        let mut i = 0;
        while i < len {
            let mut packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) };
            if packet.id == 0 {
                match packet.a {
                    SYS_FEVENT => context::event::trigger(self.scheme_id.load(Ordering::SeqCst), packet.b, packet.c, packet.d),
                    _ => println!("Unknown scheme -> kernel message {}", packet.a)
                }
            } else {
                if let Some((context_weak, size)) = self.fmap.lock().remove(&packet.id) {
                    if let Ok(address) = Error::demux(packet.a) {
                        packet.a = Error::mux(UserInner::capture_inner(&context_weak, address, size, true));
                    }
                }

                self.done.send(packet.id, packet.a);
            }
            i += 1;
        }

        Ok(i * packet_size)
    }

    pub fn fevent(&self, _flags: usize) -> Result<usize> {
        Ok(self.handle_id)
    }

    pub fn fsync(&self) -> Result<usize> {
        Ok(0)
    }
}

/// UserInner has to be wrapped
pub struct UserScheme {
    inner: Weak<UserInner>
}

impl UserScheme {
    pub fn new(inner: Weak<UserInner>) -> UserScheme {
        UserScheme {
            inner: inner
        }
    }
}

impl Scheme for UserScheme {
    fn open(&self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_OPEN, address, path.len(), flags);
        let _ = inner.release(address);
        result
    }

    fn chmod(&self, path: &[u8], mode: u16, _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_CHMOD, address, path.len(), mode as usize);
        let _ = inner.release(address);
        result
    }

    fn rmdir(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_RMDIR, address, path.len(), 0);
        let _ = inner.release(address);
        result
    }

    fn unlink(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_UNLINK, address, path.len(), 0);
        let _ = inner.release(address);
        result
    }

    fn dup(&self, file: usize, buf: &[u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(buf)?;
        let result = inner.call(SYS_DUP, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn read(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(buf)?;
        let result = inner.call(SYS_READ, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn write(&self, file: usize, buf: &[u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(buf)?;
        let result = inner.call(SYS_WRITE, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn seek(&self, file: usize, position: usize, whence: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_LSEEK, file, position, whence)
    }

    fn fcntl(&self, file: usize, cmd: usize, arg: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FCNTL, file, cmd, arg)
    }

    fn fevent(&self, file: usize, flags: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FEVENT, file, flags, 0)
    }

    fn fmap(&self, file: usize, offset: usize, size: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;

        let (pid, uid, gid, context_lock) = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            (context.id, context.euid, context.egid, Arc::downgrade(&context_lock))
        };

        let id = inner.next_id.fetch_add(1, Ordering::SeqCst);

        inner.fmap.lock().insert(id, (context_lock, size));

        inner.call_inner(Packet {
            id: id,
            pid: pid.into(),
            uid: uid,
            gid: gid,
            a: SYS_FMAP,
            b: file,
            c: offset,
            d: size
        })
    }

    fn fpath(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(buf)?;
        let result = inner.call(SYS_FPATH, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn fstat(&self, file: usize, stat: &mut Stat) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(stat)?;
        let result = inner.call(SYS_FSTAT, file, address, mem::size_of::<Stat>());
        let _ = inner.release(address);
        result
    }

    fn fstatvfs(&self, file: usize, stat: &mut StatVfs) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(stat)?;
        let result = inner.call(SYS_FSTATVFS, file, address, mem::size_of::<StatVfs>());
        let _ = inner.release(address);
        result
    }

    fn fsync(&self, file: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FSYNC, file, 0, 0)
    }

    fn ftruncate(&self, file: usize, len: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FTRUNCATE, file, len, 0)
    }

    fn close(&self, file: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_CLOSE, file, 0, 0)
    }
}
<commit_msg>Remove debug message<commit_after>use alloc::arc::{Arc, Weak};
use collections::BTreeMap;
use core::sync::atomic::{AtomicU64, Ordering};
use core::{mem, slice, usize};
use spin::{Mutex, RwLock};

use arch;
use arch::paging::{InactivePageTable, Page, VirtualAddress, entry};
use arch::paging::temporary_page::TemporaryPage;
use context::{self, Context};
use context::memory::Grant;
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
use sync::{WaitQueue, WaitMap};
use syscall::data::{Packet, Stat, StatVfs};
use syscall::error::*;
use syscall::flag::{EVENT_READ, O_NONBLOCK};
use syscall::number::*;
use syscall::scheme::Scheme;

pub struct UserInner {
    root_id: SchemeId,
    handle_id: usize,
    flags: usize,
    pub scheme_id: AtomicSchemeId,
    next_id: AtomicU64,
    context: Weak<RwLock<Context>>,
    todo: WaitQueue<Packet>,
    fmap: Mutex<BTreeMap<u64, (Weak<RwLock<Context>>, usize)>>,
    done: WaitMap<u64, usize>
}

impl UserInner {
    pub fn new(root_id: SchemeId, handle_id: usize, flags: usize, context: Weak<RwLock<Context>>) -> UserInner {
        UserInner {
            root_id: root_id,
            handle_id: handle_id,
            flags: flags,
            scheme_id: ATOMIC_SCHEMEID_INIT,
            next_id: AtomicU64::new(1),
            context: context,
            todo: WaitQueue::new(),
            fmap: Mutex::new(BTreeMap::new()),
            done: WaitMap::new()
        }
    }

    pub fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        let (pid, uid, gid) = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            (context.id, context.euid, context.egid)
        };

        self.call_inner(Packet {
            id: self.next_id.fetch_add(1, Ordering::SeqCst),
            pid: pid.into(),
            uid: uid,
            gid: gid,
            a: a,
            b: b,
            c: c,
            d: d
        })
    }

    fn call_inner(&self, packet: Packet) -> Result<usize> {
        let id = packet.id;

        let len = self.todo.send(packet);
        context::event::trigger(self.root_id, self.handle_id, EVENT_READ, mem::size_of::<Packet>() * len);

        Error::demux(self.done.receive(&id))
    }

    pub fn capture(&self, buf: &[u8]) -> Result<usize> {
        UserInner::capture_inner(&self.context, buf.as_ptr() as usize, buf.len(), false)
    }

    pub fn capture_mut(&self, buf: &mut [u8]) -> Result<usize> {
        UserInner::capture_inner(&self.context, buf.as_mut_ptr() as usize, buf.len(), true)
    }

    fn capture_inner(context_weak: &Weak<RwLock<Context>>, address: usize, size: usize, writable: bool) -> Result<usize> {
        if size == 0 {
            Ok(0)
        } else {
            let context_lock = context_weak.upgrade().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();

            let mut grants = context.grants.lock();

            let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) };
            let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET)));

            let from_address = (address/4096) * 4096;
            let offset = address - from_address;
            let full_size = ((offset + size + 4095)/4096) * 4096;
            let mut to_address = arch::USER_GRANT_OFFSET;

            let mut flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE;
            if writable {
                flags |= entry::WRITABLE;
            }

            for i in 0 .. grants.len() {
                let start = grants[i].start_address().get();
                if to_address + full_size < start {
                    grants.insert(i, Grant::map_inactive(
                        VirtualAddress::new(from_address),
                        VirtualAddress::new(to_address),
                        full_size,
                        flags,
                        &mut new_table,
                        &mut temporary_page
                    ));

                    return Ok(to_address + offset);
                } else {
                    let pages = (grants[i].size() + 4095) / 4096;
                    let end = start + pages * 4096;
                    to_address = end;
                }
            }

            grants.push(Grant::map_inactive(
                VirtualAddress::new(from_address),
                VirtualAddress::new(to_address),
                full_size,
                flags,
                &mut new_table,
                &mut temporary_page
            ));

            Ok(to_address + offset)
        }
    }

    pub fn release(&self, address: usize) -> Result<()> {
        if address == 0 {
            Ok(())
        } else {
            let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();

            let mut grants = context.grants.lock();

            let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) };
            let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET)));

            for i in 0 .. grants.len() {
                let start = grants[i].start_address().get();
                let end = start + grants[i].size();
                if address >= start && address < end {
                    grants.remove(i).unmap_inactive(&mut new_table, &mut temporary_page);

                    return Ok(());
                }
            }

            Err(Error::new(EFAULT))
        }
    }

    pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
        let packet_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Packet, buf.len()/mem::size_of::<Packet>()) };
        Ok(self.todo.receive_into(packet_buf, self.flags & O_NONBLOCK != O_NONBLOCK) * mem::size_of::<Packet>())
    }

    pub fn write(&self, buf: &[u8]) -> Result<usize> {
        let packet_size = mem::size_of::<Packet>();
        let len = buf.len()/packet_size;
        let mut i = 0;
        while i < len {
            let mut packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) };
            if packet.id == 0 {
                match packet.a {
                    SYS_FEVENT => context::event::trigger(self.scheme_id.load(Ordering::SeqCst), packet.b, packet.c, packet.d),
                    _ => println!("Unknown scheme -> kernel message {}", packet.a)
                }
            } else {
                if let Some((context_weak, size)) = self.fmap.lock().remove(&packet.id) {
                    if let Ok(address) = Error::demux(packet.a) {
                        packet.a = Error::mux(UserInner::capture_inner(&context_weak, address, size, true));
                    }
                }

                self.done.send(packet.id, packet.a);
            }
            i += 1;
        }

        Ok(i * packet_size)
    }

    pub fn fevent(&self, _flags: usize) -> Result<usize> {
        Ok(self.handle_id)
    }

    pub fn fsync(&self) -> Result<usize> {
        Ok(0)
    }
}

/// UserInner has to be wrapped
pub struct UserScheme {
    inner: Weak<UserInner>
}

impl UserScheme {
    pub fn new(inner: Weak<UserInner>) -> UserScheme {
        UserScheme {
            inner: inner
        }
    }
}

impl Scheme for UserScheme {
    fn open(&self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_OPEN, address, path.len(), flags);
        let _ = inner.release(address);
        result
    }

    fn chmod(&self, path: &[u8], mode: u16, _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_CHMOD, address, path.len(), mode as usize);
        let _ = inner.release(address);
        result
    }

    fn rmdir(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_RMDIR, address, path.len(), 0);
        let _ = inner.release(address);
        result
    }

    fn unlink(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(path)?;
        let result = inner.call(SYS_UNLINK, address, path.len(), 0);
        let _ = inner.release(address);
        result
    }

    fn dup(&self, file: usize, buf: &[u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(buf)?;
        let result = inner.call(SYS_DUP, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn read(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(buf)?;
        let result = inner.call(SYS_READ, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn write(&self, file: usize, buf: &[u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture(buf)?;
        let result = inner.call(SYS_WRITE, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn seek(&self, file: usize, position: usize, whence: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_LSEEK, file, position, whence)
    }

    fn fcntl(&self, file: usize, cmd: usize, arg: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FCNTL, file, cmd, arg)
    }

    fn fevent(&self, file: usize, flags: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FEVENT, file, flags, 0)
    }

    fn fmap(&self, file: usize, offset: usize, size: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;

        let (pid, uid, gid, context_lock) = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            (context.id, context.euid, context.egid, Arc::downgrade(&context_lock))
        };

        let id = inner.next_id.fetch_add(1, Ordering::SeqCst);

        inner.fmap.lock().insert(id, (context_lock, size));

        inner.call_inner(Packet {
            id: id,
            pid: pid.into(),
            uid: uid,
            gid: gid,
            a: SYS_FMAP,
            b: file,
            c: offset,
            d: size
        })
    }

    fn fpath(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(buf)?;
        let result = inner.call(SYS_FPATH, file, address, buf.len());
        let _ = inner.release(address);
        result
    }

    fn fstat(&self, file: usize, stat: &mut Stat) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(stat)?;
        let result = inner.call(SYS_FSTAT, file, address, mem::size_of::<Stat>());
        let _ = inner.release(address);
        result
    }

    fn fstatvfs(&self, file: usize, stat: &mut StatVfs) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        let address = inner.capture_mut(stat)?;
        let result = inner.call(SYS_FSTATVFS, file, address, mem::size_of::<StatVfs>());
        let _ = inner.release(address);
        result
    }

    fn fsync(&self, file: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FSYNC, file, 0, 0)
    }

    fn ftruncate(&self, file: usize, len: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_FTRUNCATE, file, len, 0)
    }

    fn close(&self, file: usize) -> Result<usize> {
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
        inner.call(SYS_CLOSE, file, 0, 0)
    }
}
<|endoftext|>


<commit_before>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;
static mut visitor_count: int = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {
				    println(format!("Received connection from: [{:s}]", pn.to_str()));
				    unsafe {visitor_count += 1;}
				},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            println(format!("Received request :\n{:s}", request_str));
	    unsafe{println(format!("{:d} visitors", visitor_count));}

            let response: ~str =
                ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

                 \r\n";
            stream.write(response.as_bytes());
            println!("Connection terminates.");
        }
    }
}
<commit_msg>WIP p4<commit_after>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;
static mut visitor_count: int = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {
				    println(format!("Received connection from: [{:s}]", pn.to_str()));
				    unsafe {visitor_count += 1;}
				},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
	    unsafe{println(format!("{:d} visitors", visitor_count));}
            println(format!("Received request :\n{:s}", request_str));
	    let r: ~[&str] = request_str.split(' ').collect();
	    if (r[0].contains("GET") && r[2].contains("HTTP/1.1")) {
		request(r[1]);

	    }
	    else {
		print("TEST");
 		let response: ~str =
                    ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                     <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

                     \r\n";
		stream.write(response.as_bytes());
	    }

            //let response: ~str =
              //  ~"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                // <doctype !html><title>Hello, Rust!</title>
                 //
                 //
                 //
Greetings, Krusty!

                 //\r\n";
            //stream.write(response.as_bytes());
            println!("Connection terminates.");
        }
    }
}

fn request(a: &str) {
    print!("{:s}", a);

}
<|endoftext|>


<commit_before>//! Abstractions for asynchronous programming
//!
//! This crate provides a number of core abstractions for writing asynchronous code:
//!
//! - [Futures](::Future) (sometimes called promises), which represent a single
//! asychronous computation that may result in a final value or an error.
//!
//! - [Streams](::Stream), which represent a series of values or errors produced asynchronously.
//!
//! - [Sinks](::Sink), which support asynchronous writing of data.
//!
//! - [Executors](::executor), which are responsible for running asynchronous tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](::io) and
//! [cross-task communication](::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.
//!
//! **The best way to learn about this crate is through the [Asynchronous
//! Programming in Rust](https://aturon.github.io/apr/) book**, which provides a
//! comprehensive introduction. The docs within this crate, by contrast, are
//! intended primarily as a reference.

#![no_std]
#![doc(html_root_url = "https://docs.rs/futures/0.2")]

extern crate futures_core;
extern crate futures_channel;
extern crate futures_executor;
extern crate futures_io;
extern crate futures_sink;
extern crate futures_util;

pub use futures_core::future::{Future, IntoFuture};
pub use futures_util::future::FutureExt;
pub use futures_core::stream::Stream;
pub use futures_util::stream::StreamExt;
pub use futures_sink::Sink;
pub use futures_util::sink::SinkExt;

// Macros redefined here because macro re-exports are unstable.

/// A macro for extracting the successful type of a `Poll<T, E>`.
///
/// This macro bakes in propagation of both errors and `Pending` signals by
/// returning early.
#[macro_export]
macro_rules! try_ready {
    ($e:expr) => (match $e {
        Ok($crate::prelude::Async::Ready(t)) => t,
        Ok($crate::prelude::Async::Pending) => return Ok($crate::prelude::Async::Pending),
        Err(e) => return Err(From::from(e)),
    })
}

/// A macro to create a `static` of type `LocalKey`
///
/// This macro is intentionally similar to the `thread_local!`, and creates a
/// `static` which has a `get_mut` method to access the data on a task.
///
/// The data associated with each task local is per-task, so different tasks
/// will contain different values.
#[macro_export]
macro_rules! task_local {
    (static $NAME:ident: $t:ty = $e:expr) => (
        static $NAME: $crate::task::LocalKey<$t> = {
            fn __init() -> $t { $e }
            fn __key() -> ::std::any::TypeId {
                struct __A;
                ::std::any::TypeId::of::<__A>()
            }
            $crate::task::LocalKey {
                __init: __init,
                __key: __key,
            }
        };
    )
}

pub use futures_core::{Async, Poll};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communciation.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](::channel::oneshot), a way of sending a single value from
    //! one task to another.
    //!
    //! - [mpsc](::channel::mpsc), a multi-producer, single-consumer channel for
    //! sending values between tasks, analogous to the similarly-named structure
    //! in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an *executor*, which is
    //! capable of "spawning" futures as *tasks*. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](::executor::ThreadPool). A small set of worker threads can handle
    //! a very large set of spawned tasks (which are much lighter weight than
    //! threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](::executor::ThreadPool::run) an initial task on it, which can
    //! then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app: Box<Future<Item = (), Error = ()>> = Box::new(lazy(|| Ok(())));
    //!
    //! // assumping `my_app: Future`
    //! ThreadPool::new().run(my_app);
    //! ```
    //!
    //! The call to [`run`](::executor::ThreadPool::run) will block the current
    //! thread until the future defined by `my_app` completes, and will return
    //! the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! There are two ways to spawn a task:
    //!
    //! - Spawn onto a "default" execuctor by calling the top-level
    //! [`spawn`](::executor::spawn) function.
    //!
    //! - Spawn onto a specific executor by calling its
    //! [`spawn`](::executor::Executor::spawn) method directly.
    //!
    //! Every task always has an associated default executor, which is usually
    //! the executor on which the task is running.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](::executor::LocalPool) executor. Aside from cutting down
    //! on synchronization costs, this executor also makes it possible to
    //! execute non-`Send` tasks, via
    //! [`spawn_local`](::executor::LocalExecutor::spawn_local). The `LocalPool`
    //! is best suited for running I/O-bound tasks that do relatively little
    //! work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](::executor::block_on), for simply running a future to
    //! completion on the current thread. However, any tasks spawned by the
    //! future will *also* be run on the current thread (via `LocalPool`), and
    //! will be dropped when the primary future completes.
    // TODO: add docs (or link to apr) for implementing an executor

    pub use futures_executor::{
        Enter, EnterError, LocalExecutor, LocalPool, Spawn, SpawnWithHandle, ThreadPool,
        ThreadPoolBuilder, block_on, enter, spawn, spawn_with_handle
    };
    pub use futures_core::executor::{SpawnError, Executor};
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](::Future).
    //!
    //! - The [`FutureExt`](::future::FutureExt) trait, which provides adapters
    //! for chaining and composing futures.
    //!
    //! - Top-level future contructors like [`lazy`](::future::lazy) which
    //! creates a future from a closure that defines its return value, and
    //! [`result`](::future::result), which constructs a future with an
    //! immediate defined value.

    pub use futures_core::future::{
        Result, Future, FutureFrom, IntoFuture, err, ok, result
    };
    pub use futures_util::future::{
        AndThen, Empty, Flatten, FlattenStream, FromErr, Fuse,
        Inspect, IntoStream, Join, Join3, Join4, Join5, Lazy, LoopFn,
        Map, MapErr, OrElse, PollFn, Select, Then, Either, Loop, FutureExt, empty,
        lazy, loop_fn, poll_fn
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        CatchUnwind, JoinAll, SelectAll, SelectOk, Shared, SharedError, SharedItem,
        join_all, select_all, select_ok
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](::io::AsyncRead) and
    //! [`AsyncWrite`](::io::AsyncWrite), which mirror the `Read` and `Write`
    //! traits of the standard library. However, these traits integrate with the
    //! asynchronous task system, so that if an I/O object isn't ready for
    //! reading (or writing), the thread is not blocked, and instead the current
    //! task is queued to be woken when I/O is ready.
    //!
    // TODO: document utility functions once the re-org is done

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        codec, io, AsyncReadExt, AsyncWriteExt
    };
}

#[cfg(feature = "std")]
pub mod never {
    //! This module contains the `Never` type.
    //!
    //! Values of this type can never be created and will never exist.
    pub use futures_core::never::*;
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the standard
    //! library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use futures_core::{
        Future,
        IntoFuture,
        Stream,
        Async,
        Poll,
        task,
    };

    pub use futures_sink::Sink;

    pub use futures_util::{
        FutureExt,
        StreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncRead,
        AsyncWrite,
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](::Sink), which allows you to asynchronously write data.
    //!
    //! - The [`SinkExt`](::sink::SinkExt) trait, which provides adapters
    //! for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Fanout, Flush, Send, SendAll, SinkFromErr, SinkMapErr, With,
        WithFlatMap, SinkExt, close, flush,
    };

    #[cfg(feature = "std")]
    pub use futures_sink::BoxSink;

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](::Stream), for objects that can asynchronously
    //! produce a sequence of values.
    //!
    //! - The [`StreamExt`](::future::StreamExt) trait, which provides adapters
    //! for chaining and composing streams.
    //!
    //! - Top-level stream contructors like [`iter_ok`](::stream::iter_ok) which
    //! creates a stream from an iterator, and
    //! [`futures_unordered`](::stream::futures_unordered()), which constructs a
    //! stream from a collection of futures.

    pub use futures_core::stream::Stream;

    pub use futures_util::stream::{
        AndThen, Chain, Concat, Empty, Filter, FilterMap, Flatten, Fold,
        ForEach, Forward, FromErr, Fuse, Inspect, InspectErr, IterOk,
        IterResult, Map, MapErr, Once, OrElse, Peekable, PollFn, Repeat, Select,
        Skip, SkipWhile, StreamFuture, Take, TakeWhile, Then, Unfold, Zip,
        StreamExt, empty, iter_ok, iter_result, once, poll_fn, repeat, unfold,
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_unordered, BufferUnordered, Buffered, CatchUnwind, Chunks, Collect,
        FuturesUnordered, FuturesOrdered, ReuniteError, SelectAll, SplitSink, SplitStream,
        futures_ordered,
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Context`](::task::Context), which provides contextual data present
    //! for every task, including a handle for waking up the task.
    //!
    //! - [`Waker`](::task::Waker), a handle for waking up a task.
    //!
    //! - [`LocalKey`](::task::LocalKey), a key for task-local data; you should
    //! use the [`task_local` macro](../macro.task_local.html) to set up such keys.
    //!
    //! Tasks themselves are generally created by spawning a future onto [an
    //! executor](::executor). However, you can manually construct a task by
    //! creating your own `Context` instance, and polling a future with it.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        AtomicWaker, Context, LocalMap, Waker, UnsafeWake, Wake
    };

    #[cfg(feature = "std")]
    pub use futures_core::task::LocalKey;
}
<commit_msg>More review fixes<commit_after>//! Abstractions for asynchronous programming
//!
//! This crate provides a number of core abstractions for writing asynchronous code:
//!
//! - [Futures](::Future) (sometimes called promises), which represent a single
//! asychronous computation that may result in a final value or an error.
//!
//! - [Streams](::Stream), which represent a series of values or errors produced asynchronously.
//!
//! - [Sinks](::Sink), which support asynchronous writing of data.
//!
//! - [Executors](::executor), which are responsible for running asynchronous tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](::io) and
//! [cross-task communication](::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.
//!
//! **The best way to learn about this crate is through the [Asynchronous
//! Programming in Rust](https://aturon.github.io/apr/) book**, which provides a
//! comprehensive introduction. The docs within this crate, by contrast, are
//! intended primarily as a reference.

#![no_std]
#![doc(html_root_url = "https://docs.rs/futures/0.2")]

extern crate futures_core;
extern crate futures_channel;
extern crate futures_executor;
extern crate futures_io;
extern crate futures_sink;
extern crate futures_util;

pub use futures_core::future::{Future, IntoFuture};
pub use futures_util::future::FutureExt;
pub use futures_core::stream::Stream;
pub use futures_util::stream::StreamExt;
pub use futures_sink::Sink;
pub use futures_util::sink::SinkExt;

// Macros redefined here because macro re-exports are unstable.

/// A macro for extracting the successful type of a `Poll<T, E>`.
///
/// This macro bakes in propagation of both errors and `Pending` signals by
/// returning early.
#[macro_export]
macro_rules! try_ready {
    ($e:expr) => (match $e {
        Ok($crate::prelude::Async::Ready(t)) => t,
        Ok($crate::prelude::Async::Pending) => return Ok($crate::prelude::Async::Pending),
        Err(e) => return Err(From::from(e)),
    })
}

/// A macro to create a `static` of type `LocalKey`
///
/// This macro is intentionally similar to the `thread_local!`, and creates a
/// `static` which has a `get_mut` method to access the data on a task.
///
/// The data associated with each task local is per-task, so different tasks
/// will contain different values.
#[macro_export]
macro_rules! task_local {
    (static $NAME:ident: $t:ty = $e:expr) => (
        static $NAME: $crate::task::LocalKey<$t> = {
            fn __init() -> $t { $e }
            fn __key() -> ::std::any::TypeId {
                struct __A;
                ::std::any::TypeId::of::<__A>()
            }
            $crate::task::LocalKey {
                __init: __init,
                __key: __key,
            }
        };
    )
}

pub use futures_core::{Async, Poll};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communciation.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](::channel::oneshot), a way of sending a single value from
    //! one task to another.
    //!
    //! - [mpsc](::channel::mpsc), a multi-producer, single-consumer channel for
    //! sending values between tasks, analogous to the similarly-named structure
    //! in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](::executor::ThreadPool). A small set of worker threads can handle
    //! a very large set of spawned tasks (which are much lighter weight than
    //! threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](::executor::ThreadPool::run) an initial task on it, which can
    //! then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app: Box<Future<Item = (), Error = ()>> = Box::new(lazy(|| Ok(())));
    //!
    //! // assumping `my_app: Future`
    //! ThreadPool::new().run(my_app);
    //! ```
    //!
    //! The call to [`run`](::executor::ThreadPool::run) will block the current
    //! thread until the future defined by `my_app` completes, and will return
    //! the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! There are two ways to spawn a task:
    //!
    //! - Spawn onto a "default" execuctor by calling the top-level
    //! [`spawn`](::executor::spawn) function or [pulling the executor from the
    //! task context](::task::Context::executor).
    //!
    //! - Spawn onto a specific executor by calling its
    //! [`spawn`](::executor::Executor::spawn) method directly.
    //!
    //! Every task always has an associated default executor, which is usually
    //! the executor on which the task is running.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](::executor::LocalPool) executor. Aside from cutting down
    //! on synchronization costs, this executor also makes it possible to
    //! execute non-`Send` tasks, via
    //! [`spawn_local`](::executor::LocalExecutor::spawn_local). The `LocalPool`
    //! is best suited for running I/O-bound tasks that do relatively little
    //! work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](::executor::block_on), for simply running a future to
    //! completion on the current thread. However, any tasks spawned by the
    //! future will *also* be run on the current thread (via `LocalPool`), and
    //! will be dropped when the primary future completes.
    // TODO: add docs (or link to apr) for implementing an executor

    pub use futures_executor::{
        Enter, EnterError, LocalExecutor, LocalPool, Spawn, SpawnWithHandle, ThreadPool,
        ThreadPoolBuilder, block_on, enter, spawn, spawn_with_handle
    };
    pub use futures_core::executor::{SpawnError, Executor};
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](::Future).
    //!
    //! - The [`FutureExt`](::future::FutureExt) trait, which provides adapters
    //! for chaining and composing futures.
    //!
    //! - Top-level future combinators like [`lazy`](::future::lazy) which
    //! creates a future from a closure that defines its return value, and
    //! [`result`](::future::result), which constructs a future with an
    //! immediate defined value.

    pub use futures_core::future::{
        Result, Future, FutureFrom, IntoFuture, err, ok, result
    };
    pub use futures_util::future::{
        AndThen, Empty, Flatten, FlattenStream, ErrInto, Fuse,
        Inspect, IntoStream, Join, Join3, Join4, Join5, Lazy, LoopFn,
        Map, MapErr, OrElse, PollFn, Select, Then, Either, Loop, FutureExt, empty,
        lazy, loop_fn, poll_fn
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        CatchUnwind, JoinAll, SelectAll, SelectOk, Shared, SharedError, SharedItem,
        join_all, select_all, select_ok
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](::io::AsyncRead) and
    //! [`AsyncWrite`](::io::AsyncWrite), which mirror the `Read` and `Write`
    //! traits of the standard library. However, these traits integrate with the
    //! asynchronous task system, so that if an I/O object isn't ready for
    //! reading (or writing), the thread is not blocked, and instead the current
    //! task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](::io::AsyncWriteExt) extension traits offer a variety
    //! of useful combinators for operating with asynchronous I/O objects,
    //! including ways to work with them using futures, streams and sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        codec, AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

#[cfg(feature = "std")]
pub mod never {
    //! This module contains the `Never` type.
    //!
    //! Values of this type can never be created and will never exist.
    pub use futures_core::never::*;
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the standard
    //! library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use futures_core::{
        Future,
        IntoFuture,
        Stream,
        Async,
        Poll,
        task,
    };

    pub use futures_sink::Sink;

    pub use futures_util::{
        FutureExt,
        StreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncRead,
        AsyncWrite,
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](::Sink), which allows you to asynchronously write data.
    //!
    //! - The [`SinkExt`](::sink::SinkExt) trait, which provides adapters
    //! for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Fanout, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        WithFlatMap, SinkExt, close, flush,
    };

    #[cfg(feature = "std")]
    pub use futures_sink::BoxSink;

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](::Stream), for objects that can asynchronously
    //! produce a sequence of values.
    //!
    //! - The [`StreamExt`](::future::StreamExt) trait, which provides adapters
    //! for chaining and composing streams.
    //!
    //! - Top-level stream contructors like [`iter_ok`](::stream::iter_ok) which
    //! creates a stream from an iterator, and
    //! [`futures_unordered`](::stream::futures_unordered()), which constructs a
    //! stream from a collection of futures.

    pub use futures_core::stream::Stream;

    pub use futures_util::stream::{
        AndThen, Chain, Concat, Empty, Filter, FilterMap, Flatten, Fold,
        ForEach, Forward, ErrInto, Fuse, Inspect, InspectErr, IterOk,
        IterResult, Map, MapErr, Once, OrElse, Peekable, PollFn, Repeat, Select,
        Skip, SkipWhile, StreamFuture, Take, TakeWhile, Then, Unfold, Zip,
        StreamExt, empty, iter_ok, iter_result, once, poll_fn, repeat, unfold,
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_unordered, BufferUnordered, Buffered, CatchUnwind, Chunks, Collect,
        FuturesUnordered, FuturesOrdered, ReuniteError, SelectAll, SplitSink, SplitStream,
        futures_ordered,
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Context`](::task::Context), which provides contextual data present
    //! for every task, including a handle for waking up the task.
    //!
    //! - [`Waker`](::task::Waker), a handle for waking up a task.
    //!
    //! - [`LocalKey`](::task::LocalKey), a key for task-local data; you should
    //! use the [`task_local` macro](../macro.task_local.html) to set up such keys.
    //!
    //! Tasks themselves are generally created by spawning a future onto [an
    //! executor](::executor). However, you can manually construct a task by
    //! creating your own `Context` instance, and polling a future with it.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        AtomicWaker, Context, LocalMap, Waker, UnsafeWake, Wake
    };

    #[cfg(feature = "std")]
    pub use futures_core::task::LocalKey;
}
<|endoftext|>


<commit_before>use Parameter;
use agents::ControlAgent;
use agents::memory::Trace;
use domains::Transition;
use fa::{QFunction, Projection};
use geometry::{Space, ActionSpace};
use policies::{Policy, Greedy};
use std::collections::VecDeque;
use std::marker::PhantomData;
use utils::dot;

/// Watkins' classical off policy temporal difference control algorithm.
///
/// C. J. C. H. Watkins and P. Dayan, “Q-learning,” Mach. Learn., vol. 8, no. 3–4, pp. 279–292,
/// 1992.
pub struct QLearning<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> QLearning<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2>(q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        QLearning {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for QLearning<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let qs = self.q_func.evaluate(s);
        let nqs = self.q_func.evaluate(ns);

        let a = t.action;
        let na = Greedy.sample(nqs.as_slice());

        let td_error = t.reward + self.gamma*nqs[na] - qs[a];

        self.q_func.update_action(s, a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

pub struct QLambda<S: Space, Q: QFunction<S> + Projection<S>, P: Policy> {
    trace: Trace,

    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> QLambda<S, Q, P>
    where Q: QFunction<S> + Projection<S>,
          P: Policy
{
    pub fn new<T1, T2>(trace: Trace, q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        QLambda {
            trace: trace,

            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for QLambda<S, Q, P>
    where Q: QFunction<S> + Projection<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let phi_s = self.q_func.project(t.from.state());
        let nqs = self.q_func.evaluate_phi(&self.q_func.project(t.to.state()));

        let a = t.action;
        let na = Greedy.sample(nqs.as_slice());

        let td_error = t.reward + self.gamma*nqs[na] - self.q_func.evaluate_action_phi(&phi_s, a);

        self.trace.decay(self.gamma.value());
        self.trace.update(&phi_s);
        self.q_func.update_action_phi(self.trace.get(), a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

/// Classical on policy temporal difference control algorithm.
pub struct SARSA<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> SARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2>(q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        SARSA {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for SARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let qs = self.q_func.evaluate(s);
        let nqs = self.q_func.evaluate(ns);

        let a = t.action;
        let na = self.policy.sample(nqs.as_slice());

        let td_error = t.reward + self.gamma*nqs[na] - qs[a];

        self.q_func.update_action(s, a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

/// Expected SARSA.
pub struct ExpectedSARSA<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> ExpectedSARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2>(q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        ExpectedSARSA {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for ExpectedSARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let qs = self.q_func.evaluate(s);
        let nqs = self.q_func.evaluate(ns);

        let a = t.action;

        let exp_nqs = dot(&nqs, &self.policy.probabilities(nqs.as_slice()));
        let td_error = t.reward + self.gamma*exp_nqs - qs[a];

        self.q_func.update_action(s, a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

/// General multi-step temporal-difference learning algorithm (off-policy).
///
/// The sigma parameter varies the degree of sampling, yielding classical
/// learning algorithms as special cases:
///
/// * `0` - `ExpectedSARSA` | `TreeBackup`
/// * `1` - `SARSA`
///
/// De Asis, Kristopher, et al. "Multi-step Reinforcement Learning: A Unifying
/// Algorithm." arXiv preprint arXiv:1703.01327 (2017).
pub struct QSigma<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,
    pub sigma: Parameter,

    pub n_steps: usize,

    backup: VecDeque<BackupEntry<S>>,
}

impl<S: Space, Q, P> QSigma<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2, T3>(q_func: Q,
                           policy: P,
                           alpha: T1,
                           gamma: T2,
                           sigma: T3,
                           n_steps: usize)
                           -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>,
              T3: Into<Parameter>
    {
        QSigma {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),
            sigma: sigma.into(),

            n_steps: n_steps,

            backup: VecDeque::new(),
        }
    }

    fn consume_backup(&mut self) {
        let td_error = (1..self.n_steps).fold(self.backup[0].delta, |acc, k| {
            // Calculate the cumulative discount factor:
            let gamma = self.gamma.value();
            let df = (1..k).fold(1.0, |acc, i| {
                let b = &self.backup[i];

                acc*gamma*((1.0 - b.sigma)*b.pi + b.sigma)
            });

            acc + self.backup[k].delta*df
        });

        let isr = (1..self.n_steps).fold(1.0, |acc, k| {
            let b = &self.backup[k];

            acc*(b.sigma*b.mu / b.pi + 1.0 - b.sigma)
        });

        self.q_func.update_action(&self.backup[0].s1,
                                  self.backup[0].a1,
                                  self.alpha*isr*td_error);

        self.backup.pop_front();
    }
}

struct BackupEntry<S: Space> {
    pub s1: S::Repr,
    pub a1: usize,
    pub s2: S::Repr,
    pub a2: usize,

    pub q1: f64,
    pub q2: f64,
    pub delta: f64,

    pub sigma: f64,
    pub pi: f64,
    pub mu: f64,
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for QSigma<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let q = self.q_func.evaluate_action(s, t.action);
        let nqs = self.q_func.evaluate(ns);

        let npi = self.policy.probabilities(nqs.as_slice());
        let exp_nqs = dot(&nqs, &npi);

        let na = self.policy.sample(nqs.as_slice());
        let nq = nqs[na];

        let sigma = {
            self.sigma = self.sigma.step();
            self.sigma.value()
        };
        let td_error = t.reward + self.gamma*(sigma*nq + (1.0 - sigma)*exp_nqs) - q;

        // Update backup sequence:
        self.backup.push_back(BackupEntry {
            s1: s.clone(),
            a1: t.action,
            s2: ns.clone(),
            a2: na,

            q1: q,
            q2: nq,
            delta: td_error,

            sigma: sigma,
            pi: npi[na],
            mu: Greedy.probabilities(&nqs)[na],
        });

        // Learn of latest backup sequence if we have `n_steps` entries:
        if self.backup.len() >= self.n_steps {
            self.consume_backup()
        }
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        // TODO: Handle terminal update according to Sutton's pseudocode.
        //       It's likely that this will require a change to the interface
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

// TODO:
// PQ(lambda) - http://proceedings.mlr.press/v32/sutton14.pdf
<commit_msg>Add SARSALambda<commit_after>use Parameter;
use agents::ControlAgent;
use agents::memory::Trace;
use domains::Transition;
use fa::{QFunction, Projection};
use geometry::{Space, ActionSpace};
use policies::{Policy, Greedy};
use std::collections::VecDeque;
use std::marker::PhantomData;
use utils::dot;

/// Watkins' classical off policy temporal difference control algorithm.
///
/// C. J. C. H. Watkins and P. Dayan, “Q-learning,” Mach. Learn., vol. 8, no. 3–4, pp. 279–292,
/// 1992.
pub struct QLearning<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> QLearning<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2>(q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        QLearning {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for QLearning<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let qs = self.q_func.evaluate(s);
        let nqs = self.q_func.evaluate(ns);

        let a = t.action;
        let na = Greedy.sample(nqs.as_slice());

        let td_error = t.reward + self.gamma*nqs[na] - qs[a];

        self.q_func.update_action(s, a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

pub struct QLambda<S: Space, Q: QFunction<S> + Projection<S>, P: Policy> {
    trace: Trace,

    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> QLambda<S, Q, P>
    where Q: QFunction<S> + Projection<S>,
          P: Policy
{
    pub fn new<T1, T2>(trace: Trace, q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        QLambda {
            trace: trace,

            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for QLambda<S, Q, P>
    where Q: QFunction<S> + Projection<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let phi_s = self.q_func.project(t.from.state());
        let nqs = self.q_func.evaluate_phi(&self.q_func.project(t.to.state()));

        let a = t.action;
        let na = Greedy.sample(nqs.as_slice());

        let td_error = t.reward + self.gamma*nqs[na] - self.q_func.evaluate_action_phi(&phi_s, a);

        self.trace.decay(self.gamma.value());
        self.trace.update(&phi_s);
        self.q_func.update_action_phi(self.trace.get(), a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

/// Classical on policy temporal difference control algorithm.
pub struct SARSA<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> SARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2>(q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        SARSA {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for SARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let qs = self.q_func.evaluate(s);
        let nqs = self.q_func.evaluate(ns);

        let a = t.action;
        let na = self.policy.sample(nqs.as_slice());

        let td_error = t.reward + self.gamma*nqs[na] - qs[a];

        self.q_func.update_action(s, a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

pub struct SARSALambda<S: Space, Q: QFunction<S> + Projection<S>, P: Policy> {
    trace: Trace,

    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> SARSALambda<S, Q, P>
    where Q: QFunction<S> + Projection<S>,
          P: Policy
{
    pub fn new<T1, T2>(trace: Trace, q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        SARSALambda {
            trace: trace,

            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for SARSALambda<S, Q, P>
    where Q: QFunction<S> + Projection<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let phi_s = self.q_func.project(t.from.state());
        let nqs = self.q_func.evaluate_phi(&self.q_func.project(t.to.state()));

        let a = t.action;
        let na = self.policy.sample(nqs.as_slice());

        let td_error = t.reward + self.gamma*nqs[na] - self.q_func.evaluate_action_phi(&phi_s, a);

        self.trace.decay(self.gamma.value());
        self.trace.update(&phi_s);
        self.q_func.update_action_phi(self.trace.get(), a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

/// Expected SARSA.
pub struct ExpectedSARSA<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, Q, P> ExpectedSARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2>(q_func: Q, policy: P, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        ExpectedSARSA {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for ExpectedSARSA<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let qs = self.q_func.evaluate(s);
        let nqs = self.q_func.evaluate(ns);

        let a = t.action;

        let exp_nqs = dot(&nqs, &self.policy.probabilities(nqs.as_slice()));
        let td_error = t.reward + self.gamma*exp_nqs - qs[a];

        self.q_func.update_action(s, a, self.alpha*td_error);
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

/// General multi-step temporal-difference learning algorithm (off-policy).
///
/// The sigma parameter varies the degree of sampling, yielding classical
/// learning algorithms as special cases:
///
/// * `0` - `ExpectedSARSA` | `TreeBackup`
/// * `1` - `SARSA`
///
/// De Asis, Kristopher, et al. "Multi-step Reinforcement Learning: A Unifying
/// Algorithm." arXiv preprint arXiv:1703.01327 (2017).
pub struct QSigma<S: Space, Q: QFunction<S>, P: Policy> {
    pub q_func: Q,
    pub policy: P,

    pub alpha: Parameter,
    pub gamma: Parameter,
    pub sigma: Parameter,

    pub n_steps: usize,

    backup: VecDeque<BackupEntry<S>>,
}

impl<S: Space, Q, P> QSigma<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    pub fn new<T1, T2, T3>(q_func: Q,
                           policy: P,
                           alpha: T1,
                           gamma: T2,
                           sigma: T3,
                           n_steps: usize)
                           -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>,
              T3: Into<Parameter>
    {
        QSigma {
            q_func: q_func,
            policy: policy,

            alpha: alpha.into(),
            gamma: gamma.into(),
            sigma: sigma.into(),

            n_steps: n_steps,

            backup: VecDeque::new(),
        }
    }

    fn consume_backup(&mut self) {
        let td_error = (1..self.n_steps).fold(self.backup[0].delta, |acc, k| {
            // Calculate the cumulative discount factor:
            let gamma = self.gamma.value();
            let df = (1..k).fold(1.0, |acc, i| {
                let b = &self.backup[i];

                acc*gamma*((1.0 - b.sigma)*b.pi + b.sigma)
            });

            acc + self.backup[k].delta*df
        });

        let isr = (1..self.n_steps).fold(1.0, |acc, k| {
            let b = &self.backup[k];

            acc*(b.sigma*b.mu / b.pi + 1.0 - b.sigma)
        });

        self.q_func.update_action(&self.backup[0].s1,
                                  self.backup[0].a1,
                                  self.alpha*isr*td_error);

        self.backup.pop_front();
    }
}

struct BackupEntry<S: Space> {
    pub s1: S::Repr,
    pub a1: usize,
    pub s2: S::Repr,
    pub a2: usize,

    pub q1: f64,
    pub q2: f64,
    pub delta: f64,

    pub sigma: f64,
    pub pi: f64,
    pub mu: f64,
}

impl<S: Space, Q, P> ControlAgent<S, ActionSpace> for QSigma<S, Q, P>
    where Q: QFunction<S>,
          P: Policy
{
    fn pi(&mut self, s: &S::Repr) -> usize {
        self.policy.sample(self.q_func.evaluate(s).as_slice())
    }

    fn evaluate_policy<T: Policy>(&self, p: &mut T, s: &S::Repr) -> usize {
        p.sample(self.q_func.evaluate(s).as_slice())
    }

    fn handle_transition(&mut self, t: &Transition<S, ActionSpace>) {
        let (s, ns) = (t.from.state(), t.to.state());

        let q = self.q_func.evaluate_action(s, t.action);
        let nqs = self.q_func.evaluate(ns);

        let npi = self.policy.probabilities(nqs.as_slice());
        let exp_nqs = dot(&nqs, &npi);

        let na = self.policy.sample(nqs.as_slice());
        let nq = nqs[na];

        let sigma = {
            self.sigma = self.sigma.step();
            self.sigma.value()
        };
        let td_error = t.reward + self.gamma*(sigma*nq + (1.0 - sigma)*exp_nqs) - q;

        // Update backup sequence:
        self.backup.push_back(BackupEntry {
            s1: s.clone(),
            a1: t.action,
            s2: ns.clone(),
            a2: na,

            q1: q,
            q2: nq,
            delta: td_error,

            sigma: sigma,
            pi: npi[na],
            mu: Greedy.probabilities(&nqs)[na],
        });

        // Learn of latest backup sequence if we have `n_steps` entries:
        if self.backup.len() >= self.n_steps {
            self.consume_backup()
        }
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        // TODO: Handle terminal update according to Sutton's pseudocode.
        //       It's likely that this will require a change to the interface
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();

        self.policy.handle_terminal();
    }
}

// TODO:
// PQ(lambda) - http://proceedings.mlr.press/v32/sutton14.pdf
<|endoftext|>


<commit_before>use ffi::*;
use allegro::ffi::*;
use allegro::{Color, DrawTarget};

use std::cast;
use std::libc::*;
use std::mem;

pub enum FontAlignment
{
	AlignLeft,
	AlignCentre,
	AlignRight
}

pub trait FontDrawing
{
	fn draw_text(&self, font: &Font, color: Color, x: f32, y: f32, align: FontAlignment, text: &str);
}

impl<T: DrawTarget> FontDrawing for T
{
	fn draw_text(&self, font: &Font, color: Color, x: f32, y: f32, align: FontAlignment, text: &str)
	{
		unsafe
		{
			if al_get_target_bitmap() != self.get_target_bitmap()
			{
				al_set_target_bitmap(self.get_target_bitmap())
			}

			let mut info: ALLEGRO_USTR_INFO = mem::uninit();
			let ustr = al_ref_buffer(&mut info, text.as_ptr() as *i8, text.len() as c_int);

			let flags = match align
			{
				AlignLeft => ALLEGRO_ALIGN_LEFT,
				AlignRight => ALLEGRO_ALIGN_RIGHT,
				AlignCentre => ALLEGRO_ALIGN_CENTRE,
			};

			al_draw_ustr(cast::transmute(font.get_font()), *color, x as c_float, y as c_float, flags, ustr);
		}
	}
}

pub struct Font
{
	priv allegro_font: *mut ALLEGRO_FONT
}

impl Font
{
	pub fn get_font(&self) -> *mut ALLEGRO_FONT
	{
		self.allegro_font
	}

	pub fn get_text_width(&self, text: &str) -> i32
	{
		unsafe
		{
			let mut info: ALLEGRO_USTR_INFO = mem::uninit();
			let ustr = al_ref_buffer(&mut info, text.as_ptr() as *i8, text.len() as c_int);
			al_get_ustr_width(self.get_font() as *_, ustr) as i32
		}
	}

	pub fn get_line_height(&self) -> i32
	{
		unsafe
		{
			al_get_font_line_height(self.get_font() as *_) as i32
		}
	}

	pub fn get_ascent(&self) -> i32
	{
		unsafe
		{
			al_get_font_ascent(self.get_font() as *_) as i32
		}
	}

	pub fn get_descent(&self) -> i32
	{
		unsafe
		{
			al_get_font_descent(self.get_font() as *_) as i32
		}
	}

	pub fn get_text_dimensions(&self, text: &str) -> (i32, i32, i32, i32)
	{
		unsafe
		{
			let (mut x, mut y, mut w, mut h) = mem::uninit::<(c_int, c_int, c_int, c_int)>();
			let mut info: ALLEGRO_USTR_INFO = mem::uninit();
			let ustr = al_ref_buffer(&mut info, text.as_ptr() as *i8, text.len() as c_int);
			al_get_ustr_dimensions(self.get_font() as *_, ustr, &mut x, &mut y, &mut w, &mut h);
			(x as i32, y as i32, w as i32, h as i32)
		}
	}
}

impl Drop for Font
{
	fn drop(&mut self)
	{
		unsafe
		{
			al_destroy_font(self.allegro_font);
		}
	}
}

impl ::addon::FontAddon
{
	pub fn create_builtin_font(&self) -> Option
	{
		let ret = unsafe
		{
			al_create_builtin_font()
		};
		if ret.is_null()
		{
			None
		}
		else
		{
			Some(Font{ allegro_font: ret })
		}
	}
}
<commit_msg>This looks a bit better<commit_after>use ffi::*;
use allegro::ffi::*;
use allegro::{Color, DrawTarget};

use std::cast;
use std::libc::*;
use std::mem;

pub enum FontAlignment
{
	AlignLeft,
	AlignCentre,
	AlignRight
}

pub trait FontDrawing
{
	fn draw_text(&self, font: &Font, color: Color, x: f32, y: f32, align: FontAlignment, text: &str);
}

impl<T: DrawTarget> FontDrawing for T
{
	fn draw_text(&self, font: &Font, color: Color, x: f32, y: f32, align: FontAlignment, text: &str)
	{
		unsafe
		{
			if al_get_target_bitmap() != self.get_target_bitmap()
			{
				al_set_target_bitmap(self.get_target_bitmap())
			}

			let mut info: ALLEGRO_USTR_INFO = mem::uninit();
			let ustr = al_ref_buffer(&mut info, text.as_ptr() as *i8, text.len() as c_int);

			let flags = match align
			{
				AlignLeft => ALLEGRO_ALIGN_LEFT,
				AlignRight => ALLEGRO_ALIGN_RIGHT,
				AlignCentre => ALLEGRO_ALIGN_CENTRE,
			};

			al_draw_ustr(cast::transmute(font.get_font()), *color, x as c_float, y as c_float, flags, ustr);
		}
	}
}

pub struct Font
{
	priv allegro_font: *mut ALLEGRO_FONT
}

impl Font
{
	pub fn get_font(&self) -> *mut ALLEGRO_FONT
	{
		self.allegro_font
	}

	pub fn get_text_width(&self, text: &str) -> i32
	{
		unsafe
		{
			let mut info: ALLEGRO_USTR_INFO = mem::uninit();
			let ustr = al_ref_buffer(&mut info, text.as_ptr() as *i8, text.len() as c_int);
			al_get_ustr_width(self.get_font() as *_, ustr) as i32
		}
	}

	pub fn get_line_height(&self) -> i32
	{
		unsafe
		{
			al_get_font_line_height(self.get_font() as *_) as i32
		}
	}

	pub fn get_ascent(&self) -> i32
	{
		unsafe
		{
			al_get_font_ascent(self.get_font() as *_) as i32
		}
	}

	pub fn get_descent(&self) -> i32
	{
		unsafe
		{
			al_get_font_descent(self.get_font() as *_) as i32
		}
	}

	pub fn get_text_dimensions(&self, text: &str) -> (i32, i32, i32, i32)
	{
		unsafe
		{
			let (mut x, mut y, mut w, mut h): (c_int, c_int, c_int, c_int) = mem::uninit();
			let mut info: ALLEGRO_USTR_INFO = mem::uninit();
			let ustr = al_ref_buffer(&mut info, text.as_ptr() as *i8, text.len() as c_int);
			al_get_ustr_dimensions(self.get_font() as *_, ustr, &mut x, &mut y, &mut w, &mut h);
			(x as i32, y as i32, w as i32, h as i32)
		}
	}
}

impl Drop for Font
{
	fn drop(&mut self)
	{
		unsafe
		{
			al_destroy_font(self.allegro_font);
		}
	}
}

impl ::addon::FontAddon
{
	pub fn create_builtin_font(&self) -> Option
	{
		let ret = unsafe
		{
			al_create_builtin_font()
		};
		if ret.is_null()
		{
			None
		}
		else
		{
			Some(Font{ allegro_font: ret })
		}
	}
}
<|endoftext|>