diff --git a/src/cursor.rs b/src/cursor.rs index a0c60f0..9bf8f99 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1,9 +1,9 @@ use cairo; use ui_model::Color; -use ui::UI; +use ui::{UI, UiMutex}; use shell::{Shell, NvimMode}; use nvim::{RepaintMode, RedrawEvents}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use glib; @@ -60,19 +60,17 @@ impl State { } pub struct Cursor { - state: Arc>, + state: Arc>, } impl Cursor { pub fn new() -> Cursor { - - Cursor { state: Arc::new(Mutex::new(State::new())) } - + Cursor { state: Arc::new(UiMutex::new(State::new())) } } pub fn start(&mut self) { let state = self.state.clone(); - let mut mut_state = self.state.lock().unwrap(); + let mut mut_state = self.state.borrow_mut(); mut_state.reset(); if let Some(timer_id) = mut_state.timer { glib::source_remove(timer_id); @@ -94,7 +92,7 @@ impl Cursor { bg: &Color) { let current_point = ctx.get_current_point(); - let state = self.state.lock().unwrap(); + let state = self.state.borrow(); ctx.set_source_rgba(1.0 - bg.0, 1.0 - bg.1, 1.0 - bg.2, 0.6 * state.alpha.0); let cursor_width = if shell.mode == NvimMode::Insert { @@ -112,9 +110,9 @@ impl Cursor { } } -fn anim_step(state: &Arc>) -> glib::Continue { +fn anim_step(state: &Arc>) -> glib::Continue { let moved_state = state.clone(); - let mut mut_state = state.lock().unwrap(); + let mut mut_state = state.borrow_mut(); let next_event = match mut_state.anim_phase { AnimPhase::Shown => { @@ -164,7 +162,7 @@ fn anim_step(state: &Arc>) -> glib::Continue { impl Drop for Cursor { fn drop(&mut self) { - if let Some(timer_id) = self.state.lock().unwrap().timer { + if let Some(timer_id) = self.state.borrow().timer { glib::source_remove(timer_id); } } diff --git a/src/ui.rs b/src/ui.rs index 1cd17d4..413ad29 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::cell::{RefCell, Ref, RefMut}; use std::thread; use gtk; @@ -13,14 +13,9 @@ use settings; use shell::{Shell, NvimMode}; use nvim::ErrorReport; - macro_rules! ui_thread_var { ($id:ident, $ty:ty, $expr:expr) => (thread_local!(pub static $id: RefCell<$ty> = { - let thread = thread::current(); - let current_thread_name = thread.name(); - if current_thread_name != Some("main") { - panic!("Can create UI only from main thread, {:?}", current_thread_name); - } + assert_ui_thread(); RefCell::new($expr) });) } @@ -109,7 +104,6 @@ impl Ui { self.shell.add_configure_event(); } - } fn edit_paste() { @@ -148,3 +142,41 @@ fn gtk_delete(_: &ApplicationWindow, _: &Event) -> Inhibit { Inhibit(false) } + +pub struct UiMutex { + data: RefCell, +} + +unsafe impl Send for UiMutex {} +unsafe impl Sync for UiMutex {} + +impl UiMutex { + pub fn new(t: T) -> UiMutex { + UiMutex { data: RefCell::new(t) } + } +} + +impl UiMutex { + pub fn borrow(&self) -> Ref { + assert_ui_thread(); + self.data.borrow() + } + + pub fn borrow_mut(&self) -> RefMut { + assert_ui_thread(); + self.data.borrow_mut() + } +} + + +#[inline] +fn assert_ui_thread() { + match thread::current().name() { + Some("main") => (), + Some(ref name) => { + panic!("Can create UI only from main thread, {}", name); + } + None => panic!("Can create UI only from main thread, current thiread has no name"), + } +} +