]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/windows/mutex.rs
doc: remove incomplete sentence
[rust.git] / src / libstd / sys / windows / mutex.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use prelude::v1::*;
12
13 use sync::atomic;
14 use alloc::{mod, heap};
15
16 use libc::DWORD;
17 use sys::sync as ffi;
18
19 const SPIN_COUNT: DWORD = 4000;
20
21 pub struct Mutex { inner: atomic::AtomicUint }
22
23 pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::ATOMIC_UINT_INIT };
24
25 unsafe impl Sync for Mutex {}
26
27 #[inline]
28 pub unsafe fn raw(m: &Mutex) -> ffi::LPCRITICAL_SECTION {
29     m.get()
30 }
31
32 impl Mutex {
33     #[inline]
34     pub unsafe fn new() -> Mutex {
35         Mutex { inner: atomic::AtomicUint::new(init_lock() as uint) }
36     }
37     #[inline]
38     pub unsafe fn lock(&self) {
39         ffi::EnterCriticalSection(self.get())
40     }
41     #[inline]
42     pub unsafe fn try_lock(&self) -> bool {
43         ffi::TryEnterCriticalSection(self.get()) != 0
44     }
45     #[inline]
46     pub unsafe fn unlock(&self) {
47         ffi::LeaveCriticalSection(self.get())
48     }
49     pub unsafe fn destroy(&self) {
50         let lock = self.inner.swap(0, atomic::SeqCst);
51         if lock != 0 { free_lock(lock as ffi::LPCRITICAL_SECTION) }
52     }
53
54     unsafe fn get(&self) -> ffi::LPCRITICAL_SECTION {
55         match self.inner.load(atomic::SeqCst) {
56             0 => {}
57             n => return n as ffi::LPCRITICAL_SECTION
58         }
59         let lock = init_lock();
60         match self.inner.compare_and_swap(0, lock as uint, atomic::SeqCst) {
61             0 => return lock as ffi::LPCRITICAL_SECTION,
62             _ => {}
63         }
64         free_lock(lock);
65         return self.inner.load(atomic::SeqCst) as ffi::LPCRITICAL_SECTION;
66     }
67 }
68
69 unsafe fn init_lock() -> ffi::LPCRITICAL_SECTION {
70     let block = heap::allocate(ffi::CRITICAL_SECTION_SIZE, 8)
71                         as ffi::LPCRITICAL_SECTION;
72     if block.is_null() { alloc::oom() }
73     ffi::InitializeCriticalSectionAndSpinCount(block, SPIN_COUNT);
74     return block;
75 }
76
77 unsafe fn free_lock(h: ffi::LPCRITICAL_SECTION) {
78     ffi::DeleteCriticalSection(h);
79     heap::deallocate(h as *mut _, ffi::CRITICAL_SECTION_SIZE, 8);
80 }