<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::Downcast;
use interfaces::{CefBrowser, CefBrowserHost, CefClient, cef_browser_host_t, cef_client_t};
use types::{cef_mouse_button_type_t, cef_mouse_event, cef_rect_t, cef_key_event};
use types::cef_key_event_type_t::{KEYEVENT_CHAR, KEYEVENT_KEYDOWN, KEYEVENT_KEYUP, KEYEVENT_RAWKEYDOWN};
use browser::{self, ServoCefBrowserExtensions};

use compositing::windowing::{WindowEvent, MouseWindowEvent};
use geom::point::TypedPoint2D;
use geom::size::TypedSize2D;
use libc::{c_double, c_int};
use msg::constellation_msg::{self, KeyModifiers, KeyState};
use script_traits::MouseButton;
use std::cell::RefCell;

pub struct ServoCefBrowserHost {
    /// A reference to the browser.
    pub browser: RefCell<Option<CefBrowser>>,
    /// A reference to the client.
    pub client: CefClient,
}

full_cef_class_impl! {
    ServoCefBrowserHost : CefBrowserHost, cef_browser_host_t {
        fn get_client(&this,) -> *mut cef_client_t {{
            this.downcast().client.clone()
        }}

        fn was_resized(&this,) -> () {{
            let mut rect = cef_rect_t::zero();
            this.get_client()
                .get_render_handler()
                .get_backing_rect(this.downcast().browser.borrow().clone().unwrap(), &mut rect);
            let size = TypedSize2D(rect.width as u32, rect.height as u32);
            this.downcast().send_window_event(WindowEvent::Resize(size));
        }}

        fn close_browser(&this, _force: c_int [c_int],) -> () {{
            browser::close(this.downcast().browser.borrow_mut().take().unwrap());
        }}

        fn send_focus_event(&this, focus: c_int [c_int],) -> () {{
            let focus: c_int = focus;
            if focus != 0 {
                this.downcast().send_window_event(WindowEvent::Refresh);
            }
        }}

        fn send_key_event(&this, event: *const cef_key_event [&cef_key_event],) -> () {{
            // FIXME(pcwalton): So awful. But it's nearly midnight here and I have to get
            // Google working.
            let event: &cef_key_event = event;
            let key = match (*event).character as u8 {
                b'a' | b'A' => constellation_msg::Key::A,
                b'b' | b'B' => constellation_msg::Key::B,
                b'c' | b'C' => constellation_msg::Key::C,
                b'd' | b'D' => constellation_msg::Key::D,
                b'e' | b'E' => constellation_msg::Key::E,
                b'f' | b'F' => constellation_msg::Key::F,
                b'g' | b'G' => constellation_msg::Key::G,
                b'h' | b'H' => constellation_msg::Key::H,
                b'i' | b'I' => constellation_msg::Key::I,
                b'j' | b'J' => constellation_msg::Key::J,
                b'k' | b'K' => constellation_msg::Key::K,
                b'l' | b'L' => constellation_msg::Key::L,
                b'm' | b'M' => constellation_msg::Key::M,
                b'n' | b'N' => constellation_msg::Key::N,
                b'o' | b'O' => constellation_msg::Key::O,
                b'p' | b'P' => constellation_msg::Key::P,
                b'q' | b'Q' => constellation_msg::Key::Q,
                b'r' | b'R' => constellation_msg::Key::R,
                b's' | b'S' => constellation_msg::Key::S,
                b't' | b'T' => constellation_msg::Key::T,
                b'u' | b'U' => constellation_msg::Key::U,
                b'v' | b'V' => constellation_msg::Key::V,
                b'w' | b'W' => constellation_msg::Key::W,
                b'x' | b'X' => constellation_msg::Key::X,
                b'y' | b'Y' => constellation_msg::Key::Y,
                b'z' | b'Z' => constellation_msg::Key::Z,
                b'0' => constellation_msg::Key::Num0,
                b'1' => constellation_msg::Key::Num1,
                b'2' => constellation_msg::Key::Num2,
                b'3' => constellation_msg::Key::Num3,
                b'4' => constellation_msg::Key::Num4,
                b'5' => constellation_msg::Key::Num5,
                b'6' => constellation_msg::Key::Num6,
                b'7' => constellation_msg::Key::Num7,
                b'8' => constellation_msg::Key::Num8,
                b'9' => constellation_msg::Key::Num9,
                b'\n' | b'\r' => constellation_msg::Key::Enter,
                _ => constellation_msg::Key::Space,
            };
            let key_state = match (*event).t {
                KEYEVENT_RAWKEYDOWN => KeyState::Pressed,
                KEYEVENT_KEYDOWN | KEYEVENT_CHAR => KeyState::Repeated,
                KEYEVENT_KEYUP => KeyState::Released,
            };
            let key_modifiers = KeyModifiers::empty();  // TODO(pcwalton)
            this.downcast().send_window_event(WindowEvent::KeyEvent(key, key_state, key_modifiers))
        }}

        fn send_mouse_click_event(&this,
                                  event: *const cef_mouse_event [&cef_mouse_event],
                                  mouse_button_type: cef_mouse_button_type_t [cef_mouse_button_type_t],
                                  mouse_up: c_int [c_int],
                                  _click_count: c_int [c_int],)
                                  -> () {{
            let event: &cef_mouse_event = event;
            let mouse_button_type: cef_mouse_button_type_t = mouse_button_type;
            let mouse_up: c_int = mouse_up;
            let button_type = match mouse_button_type {
                cef_mouse_button_type_t::MBT_LEFT => MouseButton::Left,
                cef_mouse_button_type_t::MBT_MIDDLE => MouseButton::Middle,
                cef_mouse_button_type_t::MBT_RIGHT => MouseButton::Right,
            };
            let point = TypedPoint2D((*event).x as f32, (*event).y as f32);
            if mouse_up != 0 {
                this.downcast().send_window_event(WindowEvent::MouseWindowEventClass(
                    MouseWindowEvent::Click(button_type, point)))
            } else {
                this.downcast().send_window_event(WindowEvent::MouseWindowEventClass(
                    MouseWindowEvent::MouseUp(button_type, point)))
            }
        }}

        fn send_mouse_move_event(&this, event: *const cef_mouse_event [&cef_mouse_event],
                                 _mouse_exited: c_int [c_int],)
                                 -> () {{
            let event: &cef_mouse_event = event;
            let point = TypedPoint2D((*event).x as f32, (*event).y as f32);
            this.downcast().send_window_event(WindowEvent::MouseWindowMoveEventClass(point))
        }}

        fn send_mouse_wheel_event(&this,
                                  event: *const cef_mouse_event [&cef_mouse_event],
                                  delta_x: c_int [c_int],
                                  delta_y: c_int [c_int],)
                                  -> () {{
            let event: &cef_mouse_event = event;
            let delta_x: c_int = delta_x;
            let delta_y: c_int = delta_y;
            let delta = TypedPoint2D(delta_x as f32, delta_y as f32);
            let origin = TypedPoint2D((*event).x as i32, (*event).y as i32);
            this.downcast().send_window_event(WindowEvent::Scroll(delta, origin))
        }}

        fn get_zoom_level(&this,) -> c_double {{
            this.downcast().pinch_zoom_level() as c_double
        }}

        fn set_zoom_level(&this, new_zoom_level: c_double [c_double],) -> () {{
            let new_zoom_level: c_double = new_zoom_level;
            let old_zoom_level = this.get_zoom_level();
            this.downcast().send_window_event(WindowEvent::PinchZoom((new_zoom_level / old_zoom_level) as f32))
        }}

        fn initialize_compositing(&this,) -> () {{
            this.downcast().send_window_event(WindowEvent::InitializeCompositing);
        }}
    }
}

impl ServoCefBrowserHost {
    pub fn new(client: CefClient) -> ServoCefBrowserHost {
        ServoCefBrowserHost {
            browser: RefCell::new(None),
            client: client,
        }
    }

    fn send_window_event(&self, event: WindowEvent) {
        self.browser.borrow_mut().as_mut().unwrap().send_window_event(event);
    }

    fn pinch_zoom_level(&self) -> f32 {
        self.browser.borrow_mut().as_mut().unwrap().pinch_zoom_level()
    }
}

pub trait ServoCefBrowserHostExtensions {
    fn set_browser(&self, browser: CefBrowser);
}

impl ServoCefBrowserHostExtensions for CefBrowserHost {
    fn set_browser(&self, browser: CefBrowser) {
        *self.downcast().browser.borrow_mut() = Some(browser)
    }
}

<commit_msg>implement cef_browser_host_t::get_browser() method<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::Downcast;
use interfaces::{CefBrowser, CefBrowserHost, CefClient, cef_browser_t, cef_browser_host_t, cef_client_t};
use types::{cef_mouse_button_type_t, cef_mouse_event, cef_rect_t, cef_key_event};
use types::cef_key_event_type_t::{KEYEVENT_CHAR, KEYEVENT_KEYDOWN, KEYEVENT_KEYUP, KEYEVENT_RAWKEYDOWN};
use browser::{self, ServoCefBrowserExtensions};

use compositing::windowing::{WindowEvent, MouseWindowEvent};
use geom::point::TypedPoint2D;
use geom::size::TypedSize2D;
use libc::{c_double, c_int};
use msg::constellation_msg::{self, KeyModifiers, KeyState};
use script_traits::MouseButton;
use std::cell::RefCell;

pub struct ServoCefBrowserHost {
    /// A reference to the browser.
    pub browser: RefCell<Option<CefBrowser>>,
    /// A reference to the client.
    pub client: CefClient,
}

full_cef_class_impl! {
    ServoCefBrowserHost : CefBrowserHost, cef_browser_host_t {
        fn get_client(&this,) -> *mut cef_client_t {{
            this.downcast().client.clone()
        }}
        fn get_browser(&this,) -> *mut cef_browser_t {{
            let browser = this.downcast().browser.borrow_mut();
            browser.clone().unwrap()
        }}

        fn was_resized(&this,) -> () {{
            let mut rect = cef_rect_t::zero();
            this.get_client()
                .get_render_handler()
                .get_backing_rect(this.downcast().browser.borrow().clone().unwrap(), &mut rect);
            let size = TypedSize2D(rect.width as u32, rect.height as u32);
            this.downcast().send_window_event(WindowEvent::Resize(size));
        }}

        fn close_browser(&this, _force: c_int [c_int],) -> () {{
            browser::close(this.downcast().browser.borrow_mut().take().unwrap());
        }}

        fn send_focus_event(&this, focus: c_int [c_int],) -> () {{
            let focus: c_int = focus;
            if focus != 0 {
                this.downcast().send_window_event(WindowEvent::Refresh);
            }
        }}

        fn send_key_event(&this, event: *const cef_key_event [&cef_key_event],) -> () {{
            // FIXME(pcwalton): So awful. But it's nearly midnight here and I have to get
            // Google working.
            let event: &cef_key_event = event;
            let key = match (*event).character as u8 {
                b'a' | b'A' => constellation_msg::Key::A,
                b'b' | b'B' => constellation_msg::Key::B,
                b'c' | b'C' => constellation_msg::Key::C,
                b'd' | b'D' => constellation_msg::Key::D,
                b'e' | b'E' => constellation_msg::Key::E,
                b'f' | b'F' => constellation_msg::Key::F,
                b'g' | b'G' => constellation_msg::Key::G,
                b'h' | b'H' => constellation_msg::Key::H,
                b'i' | b'I' => constellation_msg::Key::I,
                b'j' | b'J' => constellation_msg::Key::J,
                b'k' | b'K' => constellation_msg::Key::K,
                b'l' | b'L' => constellation_msg::Key::L,
                b'm' | b'M' => constellation_msg::Key::M,
                b'n' | b'N' => constellation_msg::Key::N,
                b'o' | b'O' => constellation_msg::Key::O,
                b'p' | b'P' => constellation_msg::Key::P,
                b'q' | b'Q' => constellation_msg::Key::Q,
                b'r' | b'R' => constellation_msg::Key::R,
                b's' | b'S' => constellation_msg::Key::S,
                b't' | b'T' => constellation_msg::Key::T,
                b'u' | b'U' => constellation_msg::Key::U,
                b'v' | b'V' => constellation_msg::Key::V,
                b'w' | b'W' => constellation_msg::Key::W,
                b'x' | b'X' => constellation_msg::Key::X,
                b'y' | b'Y' => constellation_msg::Key::Y,
                b'z' | b'Z' => constellation_msg::Key::Z,
                b'0' => constellation_msg::Key::Num0,
                b'1' => constellation_msg::Key::Num1,
                b'2' => constellation_msg::Key::Num2,
                b'3' => constellation_msg::Key::Num3,
                b'4' => constellation_msg::Key::Num4,
                b'5' => constellation_msg::Key::Num5,
                b'6' => constellation_msg::Key::Num6,
                b'7' => constellation_msg::Key::Num7,
                b'8' => constellation_msg::Key::Num8,
                b'9' => constellation_msg::Key::Num9,
                b'\n' | b'\r' => constellation_msg::Key::Enter,
                _ => constellation_msg::Key::Space,
            };
            let key_state = match (*event).t {
                KEYEVENT_RAWKEYDOWN => KeyState::Pressed,
                KEYEVENT_KEYDOWN | KEYEVENT_CHAR => KeyState::Repeated,
                KEYEVENT_KEYUP => KeyState::Released,
            };
            let key_modifiers = KeyModifiers::empty();  // TODO(pcwalton)
            this.downcast().send_window_event(WindowEvent::KeyEvent(key, key_state, key_modifiers))
        }}

        fn send_mouse_click_event(&this,
                                  event: *const cef_mouse_event [&cef_mouse_event],
                                  mouse_button_type: cef_mouse_button_type_t [cef_mouse_button_type_t],
                                  mouse_up: c_int [c_int],
                                  _click_count: c_int [c_int],)
                                  -> () {{
            let event: &cef_mouse_event = event;
            let mouse_button_type: cef_mouse_button_type_t = mouse_button_type;
            let mouse_up: c_int = mouse_up;
            let button_type = match mouse_button_type {
                cef_mouse_button_type_t::MBT_LEFT => MouseButton::Left,
                cef_mouse_button_type_t::MBT_MIDDLE => MouseButton::Middle,
                cef_mouse_button_type_t::MBT_RIGHT => MouseButton::Right,
            };
            let point = TypedPoint2D((*event).x as f32, (*event).y as f32);
            if mouse_up != 0 {
                this.downcast().send_window_event(WindowEvent::MouseWindowEventClass(
                    MouseWindowEvent::Click(button_type, point)))
            } else {
                this.downcast().send_window_event(WindowEvent::MouseWindowEventClass(
                    MouseWindowEvent::MouseUp(button_type, point)))
            }
        }}

        fn send_mouse_move_event(&this, event: *const cef_mouse_event [&cef_mouse_event],
                                 _mouse_exited: c_int [c_int],)
                                 -> () {{
            let event: &cef_mouse_event = event;
            let point = TypedPoint2D((*event).x as f32, (*event).y as f32);
            this.downcast().send_window_event(WindowEvent::MouseWindowMoveEventClass(point))
        }}

        fn send_mouse_wheel_event(&this,
                                  event: *const cef_mouse_event [&cef_mouse_event],
                                  delta_x: c_int [c_int],
                                  delta_y: c_int [c_int],)
                                  -> () {{
            let event: &cef_mouse_event = event;
            let delta_x: c_int = delta_x;
            let delta_y: c_int = delta_y;
            let delta = TypedPoint2D(delta_x as f32, delta_y as f32);
            let origin = TypedPoint2D((*event).x as i32, (*event).y as i32);
            this.downcast().send_window_event(WindowEvent::Scroll(delta, origin))
        }}

        fn get_zoom_level(&this,) -> c_double {{
            this.downcast().pinch_zoom_level() as c_double
        }}

        fn set_zoom_level(&this, new_zoom_level: c_double [c_double],) -> () {{
            let new_zoom_level: c_double = new_zoom_level;
            let old_zoom_level = this.get_zoom_level();
            this.downcast().send_window_event(WindowEvent::PinchZoom((new_zoom_level / old_zoom_level) as f32))
        }}

        fn initialize_compositing(&this,) -> () {{
            this.downcast().send_window_event(WindowEvent::InitializeCompositing);
        }}
    }
}

impl ServoCefBrowserHost {
    pub fn new(client: CefClient) -> ServoCefBrowserHost {
        ServoCefBrowserHost {
            browser: RefCell::new(None),
            client: client,
        }
    }

    fn send_window_event(&self, event: WindowEvent) {
        self.browser.borrow_mut().as_mut().unwrap().send_window_event(event);
    }

    fn pinch_zoom_level(&self) -> f32 {
        self.browser.borrow_mut().as_mut().unwrap().pinch_zoom_level()
    }
}

pub trait ServoCefBrowserHostExtensions {
    fn set_browser(&self, browser: CefBrowser);
}

impl ServoCefBrowserHostExtensions for CefBrowserHost {
    fn set_browser(&self, browser: CefBrowser) {
        *self.downcast().browser.borrow_mut() = Some(browser)
    }
}

<|endoftext|>


<commit_before>use core::mem::transmute;
use core::ptr::{set_memory, copy_memory, offset};
use core::i32::ctlz32;
use core::fail::out_of_memory;

use kernel::ptr::mut_offset;

#[repr(u8)]
enum Node {
    UNUSED = 0,
    USED = 1,
    SPLIT = 2,
    FULL = 3
}

pub trait Allocator {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint);

    fn zero_alloc(&mut self, s: uint) -> (*mut u8, uint) {
        let (ptr, size) = self.alloc(s);
        unsafe { set_memory(ptr, 0, size); }
        (ptr, size)
    }

    fn realloc(&mut self, src: *mut u8, size: uint) -> (*mut u8, uint) {
        self.free(src);
        let (ptr, sz) = self.alloc(size);
        unsafe { copy_memory(ptr, src as *u8, sz); }
        (ptr, sz)
    }

    fn free(&mut self, ptr: *mut u8);
}

trait BitvTrait {
    fn get(&self, i: uint) -> Node;
    fn set(&self, i: uint, x: Node);
    fn to_bytes(&self) -> *mut u8;
    fn size(&self) -> uint;
}

static BITV_SIZE: uint = 0x10_000;
pub type BitvStorage = *mut [u32, ..BITV_SIZE / 4];

// vector of 2-bit
pub struct Bitv {
    storage: BitvStorage
}

impl BitvTrait for Bitv {
    #[inline]
    fn get(&self, i: uint) -> Node {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe { transmute(((*self.storage)[w] as uint >> b) as u8 & 3) }
    }

    #[inline]
    fn set(&self, i: uint, x: Node) {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe { (*self.storage)[w] = (((*self.storage)[w] & !(3 << b)) | (x as u32 << b)); }
    }

    #[inline]
    fn to_bytes(&self) -> *mut u8 {
        self.storage as *mut u8
    }

    #[inline]
    fn size(&self) -> uint {
        BITV_SIZE
    }
}

pub struct BuddyAlloc {
    order: uint,
    tree: Bitv
}

pub struct Alloc {
    parent: BuddyAlloc,
    base: *mut u8,
    el_size: uint
}

impl BuddyAlloc {
    pub fn new(order: uint, storage: Bitv) -> BuddyAlloc {
        unsafe { set_memory(storage.to_bytes(), 0, storage.size()); }

        BuddyAlloc { order: order, tree: storage }
    }

    #[inline]
    fn offset(&self, index: uint, level: uint) -> uint {
        /* unsafe { - unnecessary */
            (index + 1 - (1 << (self.order - level))) << level
        /* } */
    }

    fn alloc(&mut self, mut size: uint) -> (uint, uint) {
        if size == 0 {
            size = 1;
        }
        // smallest power of 2 >= size
        let lg2_size = 32 - unsafe { ctlz32(size as i32 - 1) } as uint;

        let mut index = 0; // points to current tree node
        let mut level = self.order; // current height

        loop {
            match (self.tree.get(index), level == lg2_size) {
                (UNUSED, true) => {
                    // Found appropriate unused node
                    self.tree.set(index, USED); // use

                    let mut parent = index;
                    loop {
                        let buddy = parent - 1 + (parent & 1) * 2;
                        match self.tree.get(buddy) {
                            USED | FULL if parent > 0 => {
                                parent = (parent + 1) / 2 - 1;
                                self.tree.set(parent, FULL);
                            }
                            _ => break
                        }
                    }
                    return (
                        self.offset(index, level),
                        1 << lg2_size
                    );
                }
                (UNUSED, false) => {
                    // This large node is unused, split it!
                    self.tree.set(index, SPLIT);
                    self.tree.set(index*2 + 1, UNUSED);
                    self.tree.set(index*2 + 2, UNUSED);
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                (SPLIT, false) => {
                    // Traverse children
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                _ => loop {
                    // Go either right or back up
                    if index & 1 == 1 {
                        // right sibling
                        index += 1;
                        break;
                    }

                    // go up by one level
                    level += 1;

                    if index == 0 {
                        // out of memory -- back at tree's root after traversal
			out_of_memory();
                        return (0, 0);
                    }

                    index = (index + 1) / 2 - 1; // parent
                }
            }
        }
    }

    fn free(&mut self, offset: uint) {
        let mut length = 1 << self.order;
        let mut left = 0;
        let mut index = 0;

        // Problem 8: fix bug to reallocate two adjacent blocks correctly (when they're both free)
        // Allocator needs to remove the children in the tree and point to the parent (combine the two blocks into one)
        // Looks like this tree is being stored in an array/vector
        loop {
            match self.tree.get(index) {
                UNUSED => return,                       // block is free, don't do anything
                USED => self.tree.set(index, UNUSED),   // block is being used, free it
                _ => {
                    length /= 2;
                    if offset < left + length {
                        index = index * 2 + 1; // left child
                    }
                    else {
                        left += length;
                        index = index * 2 + 2; // right child
                    }
                }
            }
        }
    }
}

impl Allocator for Alloc {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint) {
        let (offset, size) = self.parent.alloc(size);
        unsafe {
            return (
                mut_offset(self.base, (offset << self.el_size) as int),
                size << self.el_size
            )
        }
    }

    fn free(&mut self, ptr: *mut u8) {
        let length = 1 << self.parent.order << self.el_size;

        unsafe {
            if ptr < self.base || ptr >= mut_offset(self.base, length) {
                return;
            }
        }

        let offset = (ptr as uint - self.base as uint) >> self.el_size;
        self.parent.free(offset);
    }
}
<commit_msg>Fixed buddy block bug. I think.<commit_after>use core::mem::transmute;
use core::ptr::{set_memory, copy_memory, offset};
use core::i32::ctlz32;
use core::fail::out_of_memory;

use kernel::ptr::mut_offset;

#[repr(u8)]
enum Node {
    UNUSED = 0,
    USED = 1,
    SPLIT = 2,
    FULL = 3
}

pub trait Allocator {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint);

    fn zero_alloc(&mut self, s: uint) -> (*mut u8, uint) {
        let (ptr, size) = self.alloc(s);
        unsafe { set_memory(ptr, 0, size); }
        (ptr, size)
    }

    fn realloc(&mut self, src: *mut u8, size: uint) -> (*mut u8, uint) {
        self.free(src);
        let (ptr, sz) = self.alloc(size);
        unsafe { copy_memory(ptr, src as *u8, sz); }
        (ptr, sz)
    }

    fn free(&mut self, ptr: *mut u8);
}

trait BitvTrait {
    fn get(&self, i: uint) -> Node;
    fn set(&self, i: uint, x: Node);
    fn to_bytes(&self) -> *mut u8;
    fn size(&self) -> uint;
}

static BITV_SIZE: uint = 0x10_000;
pub type BitvStorage = *mut [u32, ..BITV_SIZE / 4];

// vector of 2-bit
pub struct Bitv {
    storage: BitvStorage
}

impl BitvTrait for Bitv {
    #[inline]
    fn get(&self, i: uint) -> Node {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe { transmute(((*self.storage)[w] as uint >> b) as u8 & 3) }
    }

    #[inline]
    fn set(&self, i: uint, x: Node) {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe { (*self.storage)[w] = (((*self.storage)[w] & !(3 << b)) | (x as u32 << b)); }
    }

    #[inline]
    fn to_bytes(&self) -> *mut u8 {
        self.storage as *mut u8
    }

    #[inline]
    fn size(&self) -> uint {
        BITV_SIZE
    }
}

pub struct BuddyAlloc {
    order: uint,
    tree: Bitv
}

pub struct Alloc {
    parent: BuddyAlloc,
    base: *mut u8,
    el_size: uint
}

impl BuddyAlloc {
    pub fn new(order: uint, storage: Bitv) -> BuddyAlloc {
        unsafe { set_memory(storage.to_bytes(), 0, storage.size()); }

        BuddyAlloc { order: order, tree: storage }
    }

    #[inline]
    fn offset(&self, index: uint, level: uint) -> uint {
        /* unsafe { - unnecessary */
            (index + 1 - (1 << (self.order - level))) << level
        /* } */
    }

    fn alloc(&mut self, mut size: uint) -> (uint, uint) {
        if size == 0 {
            size = 1;
        }
        // smallest power of 2 >= size
        let lg2_size = 32 - unsafe { ctlz32(size as i32 - 1) } as uint;

        let mut index = 0; // points to current tree node
        let mut level = self.order; // current height

        loop {
            match (self.tree.get(index), level == lg2_size) {
                (UNUSED, true) => {
                    // Found appropriate unused node
                    self.tree.set(index, USED); // use

                    let mut parent = index;
                    loop {
                        let buddy = parent - 1 + (parent & 1) * 2;
                        match self.tree.get(buddy) {
                            USED | FULL if parent > 0 => {
                                parent = (parent + 1) / 2 - 1;
                                self.tree.set(parent, FULL);
                            }
                            _ => break
                        }
                    }
                    return (
                        self.offset(index, level),
                        1 << lg2_size
                    );
                }
                (UNUSED, false) => {
                    // This large node is unused, split it!
                    self.tree.set(index, SPLIT);
                    self.tree.set(index*2 + 1, UNUSED);
                    self.tree.set(index*2 + 2, UNUSED);
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                (SPLIT, false) => {
                    // Traverse children
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                _ => loop {
                    // Go either right or back up
                    if index & 1 == 1 {
                        // right sibling
                        index += 1;
                        break;
                    }

                    // go up by one level
                    level += 1;

                    if index == 0 {
                        // out of memory -- back at tree's root after traversal
			out_of_memory();
                        return (0, 0);
                    }

                    index = (index + 1) / 2 - 1; // parent
                }
            }
        }
    }

    fn free(&mut self, offset: uint) {
        let mut length = 1 << self.order;
        let mut left = 0;
        let mut index = 0;

        // Problem 8: fix bug to reallocate two adjacent blocks correctly (when they're both free)
        loop {
            match self.tree.get(index) {
                UNUSED => return,                       // block is free, don't do anything
                USED => {
                    /******** Added code ********/
                    // Left child at 2*index + 1
                    // Right child at 2*index + 2
                    // Parent at floor((index-1)/2)

                    loop{
                        if index == 0 {
                            self.tree.set(0,UNUSED);
                            return;
                        }
                        // Find sibling and check if also UNUSED
                        let buddy = index-1 + (index & 1)*2;
                        match self.tree.get(buddy){
                            UNUSED => {},
                            _ => {
                                self.tree.set(index,UNUSED);
                                loop{
                                    let parent = (index+1)/2 -1;
                                    match self.tree.get(parent){
                                        FULL if index > 0 => {
                                            self.tree.set(parent,SPLIT);
                                        },
                                        _ => return
                                    }
                                    index = parent;
                                }
                            }
                        }
                        index = (index+1)/ 2-1;
                    }

                },
                _ => {
                    length /= 2;
                    if offset < left + length {
                        index = index * 2 + 1; // left child
                    }
                    else {
                        left += length;
                        index = index * 2 + 2; // right child
                    }
                }
            }
        }
    }
}

impl Allocator for Alloc {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint) {
        let (offset, size) = self.parent.alloc(size);
        unsafe {
            return (
                mut_offset(self.base, (offset << self.el_size) as int),
                size << self.el_size
            )
        }
    }

    fn free(&mut self, ptr: *mut u8) {
        let length = 1 << self.parent.order << self.el_size;

        unsafe {
            if ptr < self.base || ptr >= mut_offset(self.base, length) {
                return;
            }
        }

        let offset = (ptr as uint - self.base as uint) >> self.el_size;
        self.parent.free(offset);
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
//    https://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.

mod analysis;
mod api;
mod codegen_cpp;
mod codegen_rs;
#[cfg(test)]
mod conversion_tests;
mod convert_error;
mod error_reporter;
mod parse;
mod utilities;

use analysis::fun::FnAnalyzer;
use autocxx_parser::TypeConfig;
pub(crate) use codegen_cpp::CppCodeGenerator;
pub(crate) use convert_error::ConvertError;
use itertools::Itertools;
use syn::{Item, ItemMod};

use crate::{CppFilePair, UnsafePolicy};

use self::{
    analysis::{
        abstract_types::mark_types_abstract, gc::filter_apis_by_following_edges_from_allowlist,
        pod::analyze_pod_apis, remove_ignored::filter_apis_by_ignored_dependents,
    },
    api::{Api, ApiAnalysis},
    codegen_rs::RsCodeGenerator,
    parse::{type_converter::TypeConverter, ParseBindgen},
};

const LOG_APIS: bool = true;

/// Converts the bindings generated by bindgen into a form suitable
/// for use with `cxx`.
/// In fact, most of the actual operation happens within an
/// individual `BridgeConversion`.
///
/// # Flexibility in handling bindgen output
///
/// autocxx is inevitably tied to the details of the bindgen output;
/// e.g. the creation of a 'root' mod when namespaces are enabled.
/// At the moment this crate takes the view that it's OK to panic
/// if the bindgen output is not as expected. It may be in future that
/// we need to be a bit more graceful, but for now, that's OK.
pub(crate) struct BridgeConverter<'a> {
    include_list: &'a [String],
    type_config: &'a TypeConfig,
}

/// C++ and Rust code generation output.
pub(crate) struct CodegenResults {
    pub(crate) rs: Vec<Item>,
    pub(crate) cpp: Option<CppFilePair>,
}

impl<'a> BridgeConverter<'a> {
    pub fn new(include_list: &'a [String], type_config: &'a TypeConfig) -> Self {
        Self {
            include_list,
            type_config,
        }
    }

    fn dump_apis<T: ApiAnalysis>(label: &str, apis: &[Api<T>]) {
        if LOG_APIS {
            log::info!(
                "APIs after {}:\n{}",
                label,
                apis.iter().map(|api| { format!("  {:?}", api) }).join("\n")
            )
        }
    }

    /// Convert a TokenStream of bindgen-generated bindings to a form
    /// suitable for cxx.
    ///
    /// This is really the heart of autocxx. It parses the output of `bindgen`
    /// (although really by "parse" we mean to interpret the structures already built
    /// up by the `syn` crate).
    pub(crate) fn convert(
        &self,
        mut bindgen_mod: ItemMod,
        unsafe_policy: UnsafePolicy,
        inclusions: String,
    ) -> Result<CodegenResults, ConvertError> {
        match &mut bindgen_mod.content {
            None => Err(ConvertError::NoContent),
            Some((_, items)) => {
                // Parse the bindgen mod.
                let items_to_process = items.drain(..).collect();
                let parser = ParseBindgen::new(&self.type_config);
                let apis = parser.parse_items(items_to_process)?;
                Self::dump_apis("parsing", &apis);
                // Inside parse_results, we now have a list of APIs and a few other things
                // e.g. type relationships. The latter are stored in here...
                let mut type_converter = TypeConverter::new(self.type_config, &apis);
                // The code above will have contributed lots of `Api`s to self.apis.
                // Now analyze which of them can be POD (i.e. trivial, movable, pass-by-value
                // versus which need to be opaque).
                // Specifically, let's confirm that the items requested by the user to be
                // POD really are POD, and duly mark any dependent types.
                // This returns a new list of `Api`s, which will be parameterized with
                // the analysis results. It also returns an object which can be used
                // by subsequent phases to work out which objects are POD.
                let analyzed_apis = analyze_pod_apis(apis, &self.type_config, &mut type_converter)?;
                // Next, figure out how we materialize different functions.
                // Some will be simple entries in the cxx::bridge module; others will
                // require C++ wrapper functions. This is probably the most complex
                // part of `autocxx`. Again, this returns a new set of `Api`s, but
                // parameterized by a richer set of metadata.
                let mut analyzed_apis = FnAnalyzer::analyze_functions(
                    analyzed_apis,
                    unsafe_policy,
                    &mut type_converter,
                    self.type_config,
                );
                // If any of those functions turned out to be pure virtual, don't attempt
                // to generate UniquePtr implementations for the type, since it can't
                // be instantiated.
                mark_types_abstract(&mut analyzed_apis);
                Self::dump_apis("main analyses", &analyzed_apis);
                // During parsing or subsequent processing we might have encountered
                // items which we couldn't process due to as-yet-unsupported features.
                // There might be other items depending on such things. Let's remove them
                // too.
                let analyzed_apis = filter_apis_by_ignored_dependents(analyzed_apis);
                Self::dump_apis("removing ignored dependents", &analyzed_apis);
                // We now garbage collect the ones we don't need...
                let mut analyzed_apis =
                    filter_apis_by_following_edges_from_allowlist(analyzed_apis, &self.type_config);
                // Determine what variably-sized C types (e.g. int) we need to include
                analysis::ctypes::append_ctype_information(&mut analyzed_apis);
                Self::dump_apis("GC", &analyzed_apis);
                // And finally pass them to the code gen phases, which outputs
                // code suitable for cxx to consume.
                let cpp = CppCodeGenerator::generate_cpp_code(inclusions, &analyzed_apis)?;
                let rs = RsCodeGenerator::generate_rs_code(
                    analyzed_apis,
                    self.include_list,
                    bindgen_mod,
                );
                Ok(CodegenResults { rs, cpp })
            }
        }
    }
}
<commit_msg>Further step to localizing TypeConverter.<commit_after>// Copyright 2020 Google LLC
//
// 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
//
//    https://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.

mod analysis;
mod api;
mod codegen_cpp;
mod codegen_rs;
#[cfg(test)]
mod conversion_tests;
mod convert_error;
mod error_reporter;
mod parse;
mod utilities;

use analysis::fun::FnAnalyzer;
use autocxx_parser::TypeConfig;
pub(crate) use codegen_cpp::CppCodeGenerator;
pub(crate) use convert_error::ConvertError;
use itertools::Itertools;
use syn::{Item, ItemMod};

use crate::{CppFilePair, UnsafePolicy};

use self::{
    analysis::{
        abstract_types::mark_types_abstract, gc::filter_apis_by_following_edges_from_allowlist,
        pod::analyze_pod_apis, remove_ignored::filter_apis_by_ignored_dependents,
    },
    api::{Api, ApiAnalysis},
    codegen_rs::RsCodeGenerator,
    parse::{type_converter::TypeConverter, ParseBindgen},
};

const LOG_APIS: bool = true;

/// Converts the bindings generated by bindgen into a form suitable
/// for use with `cxx`.
/// In fact, most of the actual operation happens within an
/// individual `BridgeConversion`.
///
/// # Flexibility in handling bindgen output
///
/// autocxx is inevitably tied to the details of the bindgen output;
/// e.g. the creation of a 'root' mod when namespaces are enabled.
/// At the moment this crate takes the view that it's OK to panic
/// if the bindgen output is not as expected. It may be in future that
/// we need to be a bit more graceful, but for now, that's OK.
pub(crate) struct BridgeConverter<'a> {
    include_list: &'a [String],
    type_config: &'a TypeConfig,
}

/// C++ and Rust code generation output.
pub(crate) struct CodegenResults {
    pub(crate) rs: Vec<Item>,
    pub(crate) cpp: Option<CppFilePair>,
}

impl<'a> BridgeConverter<'a> {
    pub fn new(include_list: &'a [String], type_config: &'a TypeConfig) -> Self {
        Self {
            include_list,
            type_config,
        }
    }

    fn dump_apis<T: ApiAnalysis>(label: &str, apis: &[Api<T>]) {
        if LOG_APIS {
            log::info!(
                "APIs after {}:\n{}",
                label,
                apis.iter().map(|api| { format!("  {:?}", api) }).join("\n")
            )
        }
    }

    /// Convert a TokenStream of bindgen-generated bindings to a form
    /// suitable for cxx.
    ///
    /// This is really the heart of autocxx. It parses the output of `bindgen`
    /// (although really by "parse" we mean to interpret the structures already built
    /// up by the `syn` crate).
    pub(crate) fn convert(
        &self,
        mut bindgen_mod: ItemMod,
        unsafe_policy: UnsafePolicy,
        inclusions: String,
    ) -> Result<CodegenResults, ConvertError> {
        match &mut bindgen_mod.content {
            None => Err(ConvertError::NoContent),
            Some((_, items)) => {
                // Parse the bindgen mod.
                let items_to_process = items.drain(..).collect();
                let parser = ParseBindgen::new(&self.type_config);
                let apis = parser.parse_items(items_to_process)?;
                Self::dump_apis("parsing", &apis);
                // Inside parse_results, we now have a list of APIs and a few other things
                // e.g. type relationships. The latter are stored in here...
                let mut type_converter = TypeConverter::new(self.type_config, &apis);
                // The code above will have contributed lots of `Api`s to self.apis.
                // Now analyze which of them can be POD (i.e. trivial, movable, pass-by-value
                // versus which need to be opaque).
                // Specifically, let's confirm that the items requested by the user to be
                // POD really are POD, and duly mark any dependent types.
                // This returns a new list of `Api`s, which will be parameterized with
                // the analysis results. It also returns an object which can be used
                // by subsequent phases to work out which objects are POD.
                let analyzed_apis = analyze_pod_apis(apis, &self.type_config, &mut type_converter)?;
                // Next, figure out how we materialize different functions.
                // Some will be simple entries in the cxx::bridge module; others will
                // require C++ wrapper functions. This is probably the most complex
                // part of `autocxx`. Again, this returns a new set of `Api`s, but
                // parameterized by a richer set of metadata.
                let mut type_converter = TypeConverter::new(self.type_config, &analyzed_apis);
                let mut analyzed_apis = FnAnalyzer::analyze_functions(
                    analyzed_apis,
                    unsafe_policy,
                    &mut type_converter,
                    self.type_config,
                );
                // If any of those functions turned out to be pure virtual, don't attempt
                // to generate UniquePtr implementations for the type, since it can't
                // be instantiated.
                mark_types_abstract(&mut analyzed_apis);
                Self::dump_apis("main analyses", &analyzed_apis);
                // During parsing or subsequent processing we might have encountered
                // items which we couldn't process due to as-yet-unsupported features.
                // There might be other items depending on such things. Let's remove them
                // too.
                let analyzed_apis = filter_apis_by_ignored_dependents(analyzed_apis);
                Self::dump_apis("removing ignored dependents", &analyzed_apis);
                // We now garbage collect the ones we don't need...
                let mut analyzed_apis =
                    filter_apis_by_following_edges_from_allowlist(analyzed_apis, &self.type_config);
                // Determine what variably-sized C types (e.g. int) we need to include
                analysis::ctypes::append_ctype_information(&mut analyzed_apis);
                Self::dump_apis("GC", &analyzed_apis);
                // And finally pass them to the code gen phases, which outputs
                // code suitable for cxx to consume.
                let cpp = CppCodeGenerator::generate_cpp_code(inclusions, &analyzed_apis)?;
                let rs = RsCodeGenerator::generate_rs_code(
                    analyzed_apis,
                    self.include_list,
                    bindgen_mod,
                );
                Ok(CodegenResults { rs, cpp })
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! # extern crate futures;
//! # extern crate futures_executor;
//! use futures::prelude::*;
//! use futures::future;
//! use futures_executor::block_on;
//!
//! # fn main() {
//! let future = future::ready(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *block_on(shared1));
//! assert_eq!(6, *block_on(shared2));
//! # }
//! ```

use slab::Slab;

use std::fmt;
use std::cell::UnsafeCell;
use std::marker::Unpin;
use std::mem::{self, PinMut};
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::task::local_waker_from_nonlocal;

use futures_core::{Future, Poll};
use futures_core::task::{self, Wake, Waker};

/// A future that is cloneable and can be polled in multiple threads.
/// Use `Future::shared()` method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    inner: Arc<Inner<F>>,
    waker_key: usize,
}

struct Inner<F: Future> {
    future_or_output: UnsafeCell<FutureOrOutput<F>>,
    notifier: Arc<Notifier>,
}

struct Notifier {
    state: AtomicUsize,
    wakers: Mutex<Slab<Option<Waker>>>,
}

// The future itself is polled behind the `Arc`, so it won't be moved
// when `Shared` is moved.
impl<F: Future> Unpin for Shared<F> {}

impl<F: Future> fmt::Debug for Shared<F> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waker_key", &self.waker_key)
            .finish()
    }
}

impl<F: Future> fmt::Debug for Inner<F> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner")
            .finish()
    }
}

enum FutureOrOutput<F: Future> {
    Future(F),
    Output(Arc<F::Output>),
}

unsafe impl<F> Send for Inner<F>
where
    F: Future + Send,
    F::Output: Send + Sync,
{}

unsafe impl<F> Sync for Inner<F>
where
    F: Future + Send,
    F::Output: Send + Sync,
{}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

const NULL_WAKER_KEY: usize = usize::max_value();

pub fn new<F: Future>(future: F) -> Shared<F> {
    Shared {
        inner: Arc::new(Inner {
            future_or_output: UnsafeCell::new(FutureOrOutput::Future(future)),
            notifier: Arc::new(Notifier {
                state: AtomicUsize::new(IDLE),
                wakers: Mutex::new(Slab::new()),
            }),
        }),
        waker_key: NULL_WAKER_KEY,
    }
}

impl<F> Shared<F> where F: Future {
    /// If any clone of this `Shared` has completed execution, returns its result immediately
    /// without blocking. Otherwise, returns None without triggering the work represented by
    /// this `Shared`.
    pub fn peek(&self) -> Option<Arc<F::Output>> {
        match self.inner.notifier.state.load(SeqCst) {
            COMPLETE => {
                Some(unsafe { self.clone_output() })
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => None,
        }
    }

    /// Registers the current task to receive a wakeup when `Inner` is awoken.
    fn set_waker(&mut self, cx: &mut task::Context) {
        let mut wakers = self.inner.notifier.wakers.lock().unwrap();
        if self.waker_key == NULL_WAKER_KEY {
            self.waker_key = wakers.insert(Some(cx.waker().clone()));
        } else {
            let waker_slot = &mut wakers[self.waker_key];
            let needs_replacement = if let Some(old_waker) = waker_slot {
                // If there's still an unwoken waker in the slot, only replace
                // if the current one wouldn't wake the same task.
                !old_waker.will_wake(cx.waker())
            } else {
                true
            };
            if needs_replacement {
                *waker_slot = Some(cx.waker().clone());
            }
        }
        debug_assert!(self.waker_key != NULL_WAKER_KEY);
    }

    /// Safety: callers must first ensure that `self.inner.state`
    /// is `COMPLETE`
    unsafe fn clone_output(&self) -> Arc<F::Output> {
        if let FutureOrOutput::Output(item) = &*self.inner.future_or_output.get() {
            item.clone()
        } else {
            unreachable!()
        }
    }
}

impl<F: Future> Future for Shared<F> {
    type Output = Arc<F::Output>;

    fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
        let this = &mut *self;

        this.set_waker(cx);

        match this.inner.notifier.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that our task handle is currently registered

                return Poll::Pending
            }
            COMPLETE => {
                return unsafe { Poll::Ready(this.clone_output()) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        let waker = local_waker_from_nonlocal(this.inner.notifier.clone());
        let mut cx = cx.with_waker(&waker);

        loop {
            struct Reset<'a>(&'a AtomicUsize);

            impl<'a> Drop for Reset<'a> {
                fn drop(&mut self) {
                    use std::thread;

                    if thread::panicking() {
                        self.0.store(POISONED, SeqCst);
                    }
                }
            }

            let _reset = Reset(&this.inner.notifier.state);

            // Poll the future
            let res = unsafe {
                if let FutureOrOutput::Future(future) = &mut *this.inner.future_or_output.get() {
                    PinMut::new_unchecked(future).poll(&mut cx)
                } else {
                    unreachable!()
                }
            };
            match res {
                Poll::Pending => {
                    // Not ready, try to release the handle
                    match this.inner.notifier.state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Poll::Pending;
                        }
                        REPOLL => {
                            // Gotta poll again!
                            let prev = this.inner.notifier.state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }
                }
                Poll::Ready(output) => {
                    let output = Arc::new(output);
                    unsafe {
                        *this.inner.future_or_output.get() =
                            FutureOrOutput::Output(output.clone());
                    }
                    // Complete the future
                    this.inner.notifier.state.store(COMPLETE, SeqCst);
                    Wake::wake(&this.inner.notifier);
                    return Poll::Ready(output);
                }
            }
        }
    }
}

impl<F> Clone for Shared<F> where F: Future {
    fn clone(&self) -> Self {
        Shared {
            inner: self.inner.clone(),
            waker_key: NULL_WAKER_KEY,
        }
    }
}

impl<F> Drop for Shared<F> where F: Future {
    fn drop(&mut self) {
        if self.waker_key != NULL_WAKER_KEY {
            if let Ok(mut wakers) = self.inner.notifier.wakers.lock() {
                mem::replace(&mut *wakers, Slab::new());
            }
        }
    }
}

impl Wake for Notifier {
    fn wake(arc_self: &Arc<Self>) {
        arc_self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let wakers = &mut *arc_self.wakers.lock().unwrap();
        for (_key, opt_waker) in wakers {
            if let Some(waker) = opt_waker.take() {
                waker.wake();
            }
        }
    }
}
<commit_msg>Only remove current waker in Shared Drop impl<commit_after>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! # extern crate futures;
//! # extern crate futures_executor;
//! use futures::prelude::*;
//! use futures::future;
//! use futures_executor::block_on;
//!
//! # fn main() {
//! let future = future::ready(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *block_on(shared1));
//! assert_eq!(6, *block_on(shared2));
//! # }
//! ```

use slab::Slab;

use std::fmt;
use std::cell::UnsafeCell;
use std::marker::Unpin;
use std::mem::PinMut;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::task::local_waker_from_nonlocal;

use futures_core::{Future, Poll};
use futures_core::task::{self, Wake, Waker};

/// A future that is cloneable and can be polled in multiple threads.
/// Use `Future::shared()` method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    inner: Arc<Inner<F>>,
    waker_key: usize,
}

struct Inner<F: Future> {
    future_or_output: UnsafeCell<FutureOrOutput<F>>,
    notifier: Arc<Notifier>,
}

struct Notifier {
    state: AtomicUsize,
    wakers: Mutex<Slab<Option<Waker>>>,
}

// The future itself is polled behind the `Arc`, so it won't be moved
// when `Shared` is moved.
impl<F: Future> Unpin for Shared<F> {}

impl<F: Future> fmt::Debug for Shared<F> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waker_key", &self.waker_key)
            .finish()
    }
}

impl<F: Future> fmt::Debug for Inner<F> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner")
            .finish()
    }
}

enum FutureOrOutput<F: Future> {
    Future(F),
    Output(Arc<F::Output>),
}

unsafe impl<F> Send for Inner<F>
where
    F: Future + Send,
    F::Output: Send + Sync,
{}

unsafe impl<F> Sync for Inner<F>
where
    F: Future + Send,
    F::Output: Send + Sync,
{}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

const NULL_WAKER_KEY: usize = usize::max_value();

pub fn new<F: Future>(future: F) -> Shared<F> {
    Shared {
        inner: Arc::new(Inner {
            future_or_output: UnsafeCell::new(FutureOrOutput::Future(future)),
            notifier: Arc::new(Notifier {
                state: AtomicUsize::new(IDLE),
                wakers: Mutex::new(Slab::new()),
            }),
        }),
        waker_key: NULL_WAKER_KEY,
    }
}

impl<F> Shared<F> where F: Future {
    /// If any clone of this `Shared` has completed execution, returns its result immediately
    /// without blocking. Otherwise, returns None without triggering the work represented by
    /// this `Shared`.
    pub fn peek(&self) -> Option<Arc<F::Output>> {
        match self.inner.notifier.state.load(SeqCst) {
            COMPLETE => {
                Some(unsafe { self.clone_output() })
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => None,
        }
    }

    /// Registers the current task to receive a wakeup when `Inner` is awoken.
    fn set_waker(&mut self, cx: &mut task::Context) {
        let mut wakers = self.inner.notifier.wakers.lock().unwrap();
        if self.waker_key == NULL_WAKER_KEY {
            self.waker_key = wakers.insert(Some(cx.waker().clone()));
        } else {
            let waker_slot = &mut wakers[self.waker_key];
            let needs_replacement = if let Some(old_waker) = waker_slot {
                // If there's still an unwoken waker in the slot, only replace
                // if the current one wouldn't wake the same task.
                !old_waker.will_wake(cx.waker())
            } else {
                true
            };
            if needs_replacement {
                *waker_slot = Some(cx.waker().clone());
            }
        }
        debug_assert!(self.waker_key != NULL_WAKER_KEY);
    }

    /// Safety: callers must first ensure that `self.inner.state`
    /// is `COMPLETE`
    unsafe fn clone_output(&self) -> Arc<F::Output> {
        if let FutureOrOutput::Output(item) = &*self.inner.future_or_output.get() {
            item.clone()
        } else {
            unreachable!()
        }
    }
}

impl<F: Future> Future for Shared<F> {
    type Output = Arc<F::Output>;

    fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
        let this = &mut *self;

        this.set_waker(cx);

        match this.inner.notifier.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that our task handle is currently registered

                return Poll::Pending
            }
            COMPLETE => {
                return unsafe { Poll::Ready(this.clone_output()) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        let waker = local_waker_from_nonlocal(this.inner.notifier.clone());
        let mut cx = cx.with_waker(&waker);

        loop {
            struct Reset<'a>(&'a AtomicUsize);

            impl<'a> Drop for Reset<'a> {
                fn drop(&mut self) {
                    use std::thread;

                    if thread::panicking() {
                        self.0.store(POISONED, SeqCst);
                    }
                }
            }

            let _reset = Reset(&this.inner.notifier.state);

            // Poll the future
            let res = unsafe {
                if let FutureOrOutput::Future(future) = &mut *this.inner.future_or_output.get() {
                    PinMut::new_unchecked(future).poll(&mut cx)
                } else {
                    unreachable!()
                }
            };
            match res {
                Poll::Pending => {
                    // Not ready, try to release the handle
                    match this.inner.notifier.state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Poll::Pending;
                        }
                        REPOLL => {
                            // Gotta poll again!
                            let prev = this.inner.notifier.state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }
                }
                Poll::Ready(output) => {
                    let output = Arc::new(output);
                    unsafe {
                        *this.inner.future_or_output.get() =
                            FutureOrOutput::Output(output.clone());
                    }
                    // Complete the future
                    this.inner.notifier.state.store(COMPLETE, SeqCst);
                    Wake::wake(&this.inner.notifier);
                    return Poll::Ready(output);
                }
            }
        }
    }
}

impl<F> Clone for Shared<F> where F: Future {
    fn clone(&self) -> Self {
        Shared {
            inner: self.inner.clone(),
            waker_key: NULL_WAKER_KEY,
        }
    }
}

impl<F> Drop for Shared<F> where F: Future {
    fn drop(&mut self) {
        if self.waker_key != NULL_WAKER_KEY {
            if let Ok(mut wakers) = self.inner.notifier.wakers.lock() {
                wakers.remove(self.waker_key);
            }
        }
    }
}

impl Wake for Notifier {
    fn wake(arc_self: &Arc<Self>) {
        arc_self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let wakers = &mut *arc_self.wakers.lock().unwrap();
        for (_key, opt_waker) in wakers {
            if let Some(waker) = opt_waker.take() {
                waker.wake();
            }
        }
    }
}
<|endoftext|>


<commit_before>#![cfg(test)]

use configuration::*;
use std::error::Error;
use std::sync::{Arc, Barrier};
use std::sync::atomic::{AtomicUsize, Ordering};
use thread_pool::*;

#[test]
fn worker_thread_index() {
    let pool = ThreadPool::new(Configuration::new().set_num_threads(22)).unwrap();
    assert_eq!(pool.num_threads(), 22);
    assert_eq!(pool.current_thread_index(), None);
    let index = pool.install(|| pool.current_thread_index().unwrap());
    assert!(index < 22);
}

#[test]
fn start_callback_called() {
    let n_threads = 16;
    let n_called = Arc::new(AtomicUsize::new(0));
    // Wait for all the threads in the pool plus the one running tests.
    let barrier = Arc::new(Barrier::new(n_threads + 1));

    let b = barrier.clone();
    let nc = n_called.clone();
    let start_handler: StartHandler = Arc::new(move |_| {
        nc.fetch_add(1, Ordering::SeqCst);
        b.wait();
    });

    let conf = Configuration::new()
        .set_num_threads(n_threads)
        .set_start_handler(start_handler);
    let _ = ThreadPool::new(conf).unwrap();

    // Wait for all the threads to have been scheduled to run.
    barrier.wait();

    // The handler must have been called on every started thread.
    assert_eq!(n_called.load(Ordering::SeqCst), n_threads);
}

#[test]
fn exit_callback_called() {
    let n_threads = 16;
    let n_called = Arc::new(AtomicUsize::new(0));
    // Wait for all the threads in the pool plus the one running tests.
    let barrier = Arc::new(Barrier::new(n_threads + 1));

    let b = barrier.clone();
    let nc = n_called.clone();
    let exit_handler: ExitHandler = Arc::new(move |_| {
        nc.fetch_add(1, Ordering::SeqCst);
        b.wait();
    });

    let conf = Configuration::new()
        .set_num_threads(n_threads)
        .set_exit_handler(exit_handler);
    {
        let _ = ThreadPool::new(conf).unwrap();
        // Drop the pool so it stops the running threads.
    }

    // Wait for all the threads to have been scheduled to run.
    barrier.wait();

    // The handler must have been called on every exiting thread.
    assert_eq!(n_called.load(Ordering::SeqCst), n_threads);
}

#[test]
fn handler_panics_handled_correctly() {
    let n_threads = 16;
    let n_called = Arc::new(AtomicUsize::new(0));
    // Wait for all the threads in the pool plus the one running tests.
    let start_barrier = Arc::new(Barrier::new(n_threads + 1));
    let exit_barrier = Arc::new(Barrier::new(n_threads + 1));

    let start_handler: StartHandler = Arc::new(move |_| {
        panic!("ensure panic handler is called when starting");
    });
    let exit_handler: ExitHandler = Arc::new(move |_| {
        panic!("ensure panic handler is called when exiting");
    });

    let sb = start_barrier.clone();
    let eb = exit_barrier.clone();
    let nc = n_called.clone();
    let panic_handler: PanicHandler = Arc::new(move |_| {
        let val = nc.fetch_add(1, Ordering::SeqCst);
        if val < n_threads {
            sb.wait();
        } else {
            eb.wait();
        }
    });

    let conf = Configuration::new()
        .set_num_threads(n_threads)
        .set_start_handler(start_handler)
        .set_exit_handler(exit_handler)
        .set_panic_handler(panic_handler);
    {
        let _ = ThreadPool::new(conf).unwrap();

        // Wait for all the threads to start, panic in the start handler,
        // and been taken care of by the panic handler.
        start_barrier.wait();

        // Drop the pool so it stops the running threads.
    }

    // Wait for all the threads to exit, panic in the exit handler,
    // and been taken care of by the panic handler.
    exit_barrier.wait();

    // The panic handler must have been called twice on every thread.
    assert_eq!(n_called.load(Ordering::SeqCst), 2 * n_threads);
}
<commit_msg>Remove unused import<commit_after>#![cfg(test)]

use configuration::*;
use std::sync::{Arc, Barrier};
use std::sync::atomic::{AtomicUsize, Ordering};
use thread_pool::*;

#[test]
fn worker_thread_index() {
    let pool = ThreadPool::new(Configuration::new().set_num_threads(22)).unwrap();
    assert_eq!(pool.num_threads(), 22);
    assert_eq!(pool.current_thread_index(), None);
    let index = pool.install(|| pool.current_thread_index().unwrap());
    assert!(index < 22);
}

#[test]
fn start_callback_called() {
    let n_threads = 16;
    let n_called = Arc::new(AtomicUsize::new(0));
    // Wait for all the threads in the pool plus the one running tests.
    let barrier = Arc::new(Barrier::new(n_threads + 1));

    let b = barrier.clone();
    let nc = n_called.clone();
    let start_handler: StartHandler = Arc::new(move |_| {
        nc.fetch_add(1, Ordering::SeqCst);
        b.wait();
    });

    let conf = Configuration::new()
        .set_num_threads(n_threads)
        .set_start_handler(start_handler);
    let _ = ThreadPool::new(conf).unwrap();

    // Wait for all the threads to have been scheduled to run.
    barrier.wait();

    // The handler must have been called on every started thread.
    assert_eq!(n_called.load(Ordering::SeqCst), n_threads);
}

#[test]
fn exit_callback_called() {
    let n_threads = 16;
    let n_called = Arc::new(AtomicUsize::new(0));
    // Wait for all the threads in the pool plus the one running tests.
    let barrier = Arc::new(Barrier::new(n_threads + 1));

    let b = barrier.clone();
    let nc = n_called.clone();
    let exit_handler: ExitHandler = Arc::new(move |_| {
        nc.fetch_add(1, Ordering::SeqCst);
        b.wait();
    });

    let conf = Configuration::new()
        .set_num_threads(n_threads)
        .set_exit_handler(exit_handler);
    {
        let _ = ThreadPool::new(conf).unwrap();
        // Drop the pool so it stops the running threads.
    }

    // Wait for all the threads to have been scheduled to run.
    barrier.wait();

    // The handler must have been called on every exiting thread.
    assert_eq!(n_called.load(Ordering::SeqCst), n_threads);
}

#[test]
fn handler_panics_handled_correctly() {
    let n_threads = 16;
    let n_called = Arc::new(AtomicUsize::new(0));
    // Wait for all the threads in the pool plus the one running tests.
    let start_barrier = Arc::new(Barrier::new(n_threads + 1));
    let exit_barrier = Arc::new(Barrier::new(n_threads + 1));

    let start_handler: StartHandler = Arc::new(move |_| {
        panic!("ensure panic handler is called when starting");
    });
    let exit_handler: ExitHandler = Arc::new(move |_| {
        panic!("ensure panic handler is called when exiting");
    });

    let sb = start_barrier.clone();
    let eb = exit_barrier.clone();
    let nc = n_called.clone();
    let panic_handler: PanicHandler = Arc::new(move |_| {
        let val = nc.fetch_add(1, Ordering::SeqCst);
        if val < n_threads {
            sb.wait();
        } else {
            eb.wait();
        }
    });

    let conf = Configuration::new()
        .set_num_threads(n_threads)
        .set_start_handler(start_handler)
        .set_exit_handler(exit_handler)
        .set_panic_handler(panic_handler);
    {
        let _ = ThreadPool::new(conf).unwrap();

        // Wait for all the threads to start, panic in the start handler,
        // and been taken care of by the panic handler.
        start_barrier.wait();

        // Drop the pool so it stops the running threads.
    }

    // Wait for all the threads to exit, panic in the exit handler,
    // and been taken care of by the panic handler.
    exit_barrier.wait();

    // The panic handler must have been called twice on every thread.
    assert_eq!(n_called.load(Ordering::SeqCst), 2 * n_threads);
}
<|endoftext|>


<commit_before>// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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 std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut, Range};
use std::slice;
use bitslice::{BitSlice, Word};
use bitslice::{bitwise, Union, Subtract};
use indexed_vec::Idx;

/// Represents a set (or packed family of sets), of some element type
/// E, where each E is identified by some unique index type `T`.
///
/// In other words, `T` is the type used to index into the bitvector
/// this type uses to represent the set of object it holds.
#[derive(Eq, PartialEq)]
pub struct IdxSetBuf<T: Idx> {
    _pd: PhantomData<fn(&T)>,
    bits: Vec<Word>,
}

impl<T: Idx> Clone for IdxSetBuf<T> {
    fn clone(&self) -> Self {
        IdxSetBuf { _pd: PhantomData, bits: self.bits.clone() }
    }
}

// pnkfelix wants to have this be `IdxSet<T>([Word]) and then pass
// around `&mut IdxSet<T>` or `&IdxSet<T>`.
//
// WARNING: Mapping a `&IdxSetBuf<T>` to `&IdxSet<T>` (at least today)
// requires a transmute relying on representation guarantees that may
// not hold in the future.

/// Represents a set (or packed family of sets), of some element type
/// E, where each E is identified by some unique index type `T`.
///
/// In other words, `T` is the type used to index into the bitslice
/// this type uses to represent the set of object it holds.
pub struct IdxSet<T: Idx> {
    _pd: PhantomData<fn(&T)>,
    bits: [Word],
}

impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
}

impl<T: Idx> fmt::Debug for IdxSet<T> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
}

impl<T: Idx> IdxSetBuf<T> {
    fn new(init: Word, universe_size: usize) -> Self {
        let bits_per_word = mem::size_of::<Word>() * 8;
        let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word;
        IdxSetBuf {
            _pd: Default::default(),
            bits: vec![init; num_words],
        }
    }

    /// Creates set holding every element whose index falls in range 0..universe_size.
    pub fn new_filled(universe_size: usize) -> Self {
        Self::new(!0, universe_size)
    }

    /// Creates set holding no elements.
    pub fn new_empty(universe_size: usize) -> Self {
        Self::new(0, universe_size)
    }
}

impl<T: Idx> IdxSet<T> {
    unsafe fn from_slice(s: &[Word]) -> &Self {
        mem::transmute(s) // (see above WARNING)
    }

    unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self {
        mem::transmute(s) // (see above WARNING)
    }
}

impl<T: Idx> Deref for IdxSetBuf<T> {
    type Target = IdxSet<T>;
    fn deref(&self) -> &IdxSet<T> {
        unsafe { IdxSet::from_slice(&self.bits) }
    }
}

impl<T: Idx> DerefMut for IdxSetBuf<T> {
    fn deref_mut(&mut self) -> &mut IdxSet<T> {
        unsafe { IdxSet::from_slice_mut(&mut self.bits) }
    }
}

impl<T: Idx> IdxSet<T> {
    pub fn to_owned(&self) -> IdxSetBuf<T> {
        IdxSetBuf {
            _pd: Default::default(),
            bits: self.bits.to_owned(),
        }
    }

    /// Removes all elements
    pub fn clear(&mut self) {
        for b in &mut self.bits {
            *b = 0;
        }
    }

    /// Removes `elem` from the set `self`; returns true iff this changed `self`.
    pub fn remove(&mut self, elem: &T) -> bool {
        self.bits.clear_bit(elem.index())
    }

    /// Adds `elem` to the set `self`; returns true iff this changed `self`.
    pub fn add(&mut self, elem: &T) -> bool {
        self.bits.set_bit(elem.index())
    }

    pub fn range(&self, elems: &Range<T>) -> &Self {
        let elems = elems.start.index()..elems.end.index();
        unsafe { Self::from_slice(&self.bits[elems]) }
    }

    pub fn range_mut(&mut self, elems: &Range<T>) -> &mut Self {
        let elems = elems.start.index()..elems.end.index();
        unsafe { Self::from_slice_mut(&mut self.bits[elems]) }
    }

    /// Returns true iff set `self` contains `elem`.
    pub fn contains(&self, elem: &T) -> bool {
        self.bits.get_bit(elem.index())
    }

    pub fn words(&self) -> &[Word] {
        &self.bits
    }

    pub fn words_mut(&mut self) -> &mut [Word] {
        &mut self.bits
    }

    pub fn clone_from(&mut self, other: &IdxSet<T>) {
        self.words_mut().clone_from_slice(other.words());
    }

    pub fn union(&mut self, other: &IdxSet<T>) -> bool {
        bitwise(self.words_mut(), other.words(), &Union)
    }

    pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
        bitwise(self.words_mut(), other.words(), &Subtract)
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            cur: None,
            iter: self.words().iter().enumerate(),
            _pd: PhantomData,
        }
    }
}

pub struct Iter<'a, T: Idx> {
    cur: Option<(Word, usize)>,
    iter: iter::Enumerate<slice::Iter<'a, Word>>,
    _pd: PhantomData<fn(&T)>,
}

impl<'a, T: Idx> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        let word_bits = mem::size_of::<Word>() * 8;
        loop {
            if let Some((ref mut word, offset)) = self.cur {
                let bit_pos = word.trailing_zeros();
                if bit_pos != word_bits as u32 {
                    let bit = 1 << bit_pos;
                    *word ^= bit;
                    return Some(T::new(bit + offset))
                }
            }

            match self.iter.next() {
                Some((i, word)) => self.cur = Some((*word, word_bits * i)),
                None => return None,
            }
        }
    }
}
<commit_msg>Fix iterator over indexed sets<commit_after>// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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 std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut, Range};
use std::slice;
use bitslice::{BitSlice, Word};
use bitslice::{bitwise, Union, Subtract};
use indexed_vec::Idx;

/// Represents a set (or packed family of sets), of some element type
/// E, where each E is identified by some unique index type `T`.
///
/// In other words, `T` is the type used to index into the bitvector
/// this type uses to represent the set of object it holds.
#[derive(Eq, PartialEq)]
pub struct IdxSetBuf<T: Idx> {
    _pd: PhantomData<fn(&T)>,
    bits: Vec<Word>,
}

impl<T: Idx> Clone for IdxSetBuf<T> {
    fn clone(&self) -> Self {
        IdxSetBuf { _pd: PhantomData, bits: self.bits.clone() }
    }
}

// pnkfelix wants to have this be `IdxSet<T>([Word]) and then pass
// around `&mut IdxSet<T>` or `&IdxSet<T>`.
//
// WARNING: Mapping a `&IdxSetBuf<T>` to `&IdxSet<T>` (at least today)
// requires a transmute relying on representation guarantees that may
// not hold in the future.

/// Represents a set (or packed family of sets), of some element type
/// E, where each E is identified by some unique index type `T`.
///
/// In other words, `T` is the type used to index into the bitslice
/// this type uses to represent the set of object it holds.
pub struct IdxSet<T: Idx> {
    _pd: PhantomData<fn(&T)>,
    bits: [Word],
}

impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
}

impl<T: Idx> fmt::Debug for IdxSet<T> {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
}

impl<T: Idx> IdxSetBuf<T> {
    fn new(init: Word, universe_size: usize) -> Self {
        let bits_per_word = mem::size_of::<Word>() * 8;
        let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word;
        IdxSetBuf {
            _pd: Default::default(),
            bits: vec![init; num_words],
        }
    }

    /// Creates set holding every element whose index falls in range 0..universe_size.
    pub fn new_filled(universe_size: usize) -> Self {
        Self::new(!0, universe_size)
    }

    /// Creates set holding no elements.
    pub fn new_empty(universe_size: usize) -> Self {
        Self::new(0, universe_size)
    }
}

impl<T: Idx> IdxSet<T> {
    unsafe fn from_slice(s: &[Word]) -> &Self {
        mem::transmute(s) // (see above WARNING)
    }

    unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self {
        mem::transmute(s) // (see above WARNING)
    }
}

impl<T: Idx> Deref for IdxSetBuf<T> {
    type Target = IdxSet<T>;
    fn deref(&self) -> &IdxSet<T> {
        unsafe { IdxSet::from_slice(&self.bits) }
    }
}

impl<T: Idx> DerefMut for IdxSetBuf<T> {
    fn deref_mut(&mut self) -> &mut IdxSet<T> {
        unsafe { IdxSet::from_slice_mut(&mut self.bits) }
    }
}

impl<T: Idx> IdxSet<T> {
    pub fn to_owned(&self) -> IdxSetBuf<T> {
        IdxSetBuf {
            _pd: Default::default(),
            bits: self.bits.to_owned(),
        }
    }

    /// Removes all elements
    pub fn clear(&mut self) {
        for b in &mut self.bits {
            *b = 0;
        }
    }

    /// Removes `elem` from the set `self`; returns true iff this changed `self`.
    pub fn remove(&mut self, elem: &T) -> bool {
        self.bits.clear_bit(elem.index())
    }

    /// Adds `elem` to the set `self`; returns true iff this changed `self`.
    pub fn add(&mut self, elem: &T) -> bool {
        self.bits.set_bit(elem.index())
    }

    pub fn range(&self, elems: &Range<T>) -> &Self {
        let elems = elems.start.index()..elems.end.index();
        unsafe { Self::from_slice(&self.bits[elems]) }
    }

    pub fn range_mut(&mut self, elems: &Range<T>) -> &mut Self {
        let elems = elems.start.index()..elems.end.index();
        unsafe { Self::from_slice_mut(&mut self.bits[elems]) }
    }

    /// Returns true iff set `self` contains `elem`.
    pub fn contains(&self, elem: &T) -> bool {
        self.bits.get_bit(elem.index())
    }

    pub fn words(&self) -> &[Word] {
        &self.bits
    }

    pub fn words_mut(&mut self) -> &mut [Word] {
        &mut self.bits
    }

    pub fn clone_from(&mut self, other: &IdxSet<T>) {
        self.words_mut().clone_from_slice(other.words());
    }

    pub fn union(&mut self, other: &IdxSet<T>) -> bool {
        bitwise(self.words_mut(), other.words(), &Union)
    }

    pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
        bitwise(self.words_mut(), other.words(), &Subtract)
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            cur: None,
            iter: self.words().iter().enumerate(),
            _pd: PhantomData,
        }
    }
}

pub struct Iter<'a, T: Idx> {
    cur: Option<(Word, usize)>,
    iter: iter::Enumerate<slice::Iter<'a, Word>>,
    _pd: PhantomData<fn(&T)>,
}

impl<'a, T: Idx> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        let word_bits = mem::size_of::<Word>() * 8;
        loop {
            if let Some((ref mut word, offset)) = self.cur {
                let bit_pos = word.trailing_zeros() as usize;
                if bit_pos != word_bits {
                    let bit = 1 << bit_pos;
                    *word ^= bit;
                    return Some(T::new(bit_pos + offset))
                }
            }

            match self.iter.next() {
                Some((i, word)) => self.cur = Some((*word, word_bits * i)),
                None => return None,
            }
        }
    }
}
<|endoftext|>