1 // Copyright 2013-2015, The Gtk-rs Project Developers. 2 // See the COPYRIGHT file at the top-level directory of this distribution. 3 // Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT> 4 5 //! General — Library initialization and miscellaneous functions 6 7 use gdk_sys; 8 use std::cell::Cell; 9 use std::ptr; 10 use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; 11 12 thread_local! { 13 static IS_MAIN_THREAD: Cell<bool> = Cell::new(false) 14 } 15 16 static INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT; 17 18 /// Asserts that this is the main thread and either `gdk::init` or `gtk::init` has been called. 19 macro_rules! assert_initialized_main_thread { 20 () => { 21 if !::rt::is_initialized_main_thread() { 22 if ::rt::is_initialized() { 23 panic!("GDK may only be used from the main thread."); 24 } else { 25 panic!("GDK has not been initialized. Call `gdk::init` or `gtk::init` first."); 26 } 27 } 28 }; 29 } 30 31 /// No-op. 32 macro_rules! skip_assert_initialized { 33 () => {}; 34 } 35 36 /// Asserts that neither `gdk::init` nor `gtk::init` has been called. 37 macro_rules! assert_not_initialized { 38 () => { 39 if ::rt::is_initialized() { 40 panic!("This function has to be called before `gdk::init` or `gtk::init`."); 41 } 42 }; 43 } 44 45 /// Returns `true` if GDK has been initialized. 46 #[inline] is_initialized() -> bool47pub fn is_initialized() -> bool { 48 skip_assert_initialized!(); 49 INITIALIZED.load(Ordering::Acquire) 50 } 51 52 /// Returns `true` if GDK has been initialized and this is the main thread. 53 #[inline] is_initialized_main_thread() -> bool54pub fn is_initialized_main_thread() -> bool { 55 skip_assert_initialized!(); 56 IS_MAIN_THREAD.with(|c| c.get()) 57 } 58 59 /// Informs this crate that GDK has been initialized and the current thread is the main one. set_initialized()60pub unsafe fn set_initialized() { 61 skip_assert_initialized!(); 62 if is_initialized_main_thread() { 63 return; 64 } else if is_initialized() { 65 panic!("Attempted to initialize GDK from two different threads."); 66 } 67 INITIALIZED.store(true, Ordering::Release); 68 IS_MAIN_THREAD.with(|c| c.set(true)); 69 } 70 init()71pub fn init() { 72 assert_not_initialized!(); 73 unsafe { 74 gdk_sys::gdk_init(ptr::null_mut(), ptr::null_mut()); 75 set_initialized(); 76 } 77 } 78