Code Monkey home page Code Monkey logo

parking_lot's Introduction

parking_lot

Rust Crates.io

Documentation (synchronization primitives)

Documentation (core parking lot API)

Documentation (type-safe lock API)

This library provides implementations of Mutex, RwLock, Condvar and Once that are smaller, faster and more flexible than those in the Rust standard library, as well as a ReentrantMutex type which supports recursive locking. It also exposes a low-level API for creating your own efficient synchronization primitives.

When tested on x86_64 Linux, parking_lot::Mutex was found to be 1.5x faster than std::sync::Mutex when uncontended, and up to 5x faster when contended from multiple threads. The numbers for RwLock vary depending on the number of reader and writer threads, but are almost always faster than the standard library RwLock, and even up to 50x faster in some cases.

Features

The primitives provided by this library have several advantages over those in the Rust standard library:

  1. Mutex and Once only require 1 byte of storage space, while Condvar and RwLock only require 1 word of storage space. On the other hand on some platforms (macOS and a few others) the standard library primitives require a dynamically allocated Box to hold OS-specific synchronization primitives. The small size of Mutex in particular encourages the use of fine-grained locks to increase parallelism.
  2. Uncontended lock acquisition and release is done through fast inline paths which only require a single atomic operation.
  3. Microcontention (a contended lock with a short critical section) is efficiently handled by spinning a few times while trying to acquire a lock.
  4. The locks are adaptive and will suspend a thread after a few failed spin attempts. This makes the locks suitable for both long and short critical sections.
  5. Condvar, RwLock and Once work on Windows XP, unlike the standard library versions of those types.
  6. RwLock takes advantage of hardware lock elision on processors that support it, which can lead to huge performance wins with many readers. This must be enabled with the hardware-lock-elision feature.
  7. RwLock uses a task-fair locking policy, which avoids reader and writer starvation, whereas the standard library version makes no guarantees.
  8. Condvar is guaranteed not to produce spurious wakeups. A thread will only be woken up if it timed out or it was woken up by a notification.
  9. Condvar::notify_all will only wake up a single thread and requeue the rest to wait on the associated Mutex. This avoids a thundering herd problem where all threads try to acquire the lock at the same time.
  10. RwLock supports atomically downgrading a write lock into a read lock.
  11. Mutex and RwLock allow raw unlocking without a RAII guard object.
  12. Mutex<()> and RwLock<()> allow raw locking without a RAII guard object.
  13. Mutex and RwLock support eventual fairness which allows them to be fair on average without sacrificing performance.
  14. A ReentrantMutex type which supports recursive locking.
  15. An experimental deadlock detector that works for Mutex, RwLock and ReentrantMutex. This feature is disabled by default and can be enabled via the deadlock_detection feature.
  16. RwLock supports atomically upgrading an "upgradable" read lock into a write lock.
  17. Optional support for serde. Enable via the feature serde. NOTE! this support is for Mutex, ReentrantMutex, and RwLock only; Condvar and Once are not currently supported.
  18. Lock guards can be sent to other threads when the send_guard feature is enabled.

The parking lot

To keep these primitives small, all thread queuing and suspending functionality is offloaded to the parking lot. The idea behind this is based on the Webkit WTF::ParkingLot class, which essentially consists of a hash table mapping of lock addresses to queues of parked (sleeping) threads. The Webkit parking lot was itself inspired by Linux futexes, but it is more powerful since it allows invoking callbacks while holding a queue lock.

Nightly vs stable

There are a few restrictions when using this library on stable Rust:

  • The wasm32-unknown-unknown target is only fully supported on nightly with -C target-feature=+atomics in RUSTFLAGS and -Zbuild-std=panic_abort,std passed to cargo. parking_lot will work mostly fine on stable, the only difference is it will panic instead of block forever if you hit a deadlock. Just make sure not to enable -C target-feature=+atomics on stable as that will allow wasm to run with multiple threads which will completely break parking_lot's concurrency guarantees.

To enable nightly-only functionality, you need to enable the nightly feature in Cargo (see below).

Usage

Add this to your Cargo.toml:

[dependencies]
parking_lot = "0.12"

To enable nightly-only features, add this to your Cargo.toml instead:

[dependencies]
parking_lot = { version = "0.12", features = ["nightly"] }

The experimental deadlock detector can be enabled with the deadlock_detection Cargo feature.

To allow sending MutexGuards and RwLock*Guards to other threads, enable the send_guard option.

Note that the deadlock_detection and send_guard features are incompatible and cannot be used together.

Hardware lock elision support for x86 can be enabled with the hardware-lock-elision feature. This requires Rust 1.59 due to the use of inline assembly.

The core parking lot API is provided by the parking_lot_core crate. It is separate from the synchronization primitives in the parking_lot crate so that changes to the core API do not cause breaking changes for users of parking_lot.

Minimum Rust version

The current minimum required Rust version is 1.56. Any change to this is considered a breaking change and will require a major version bump.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

parking_lot's People

Contributors

alex avatar amanieu avatar apasel422 avatar arthurprs avatar bors[bot] avatar bryanhitc avatar ckaran avatar coolreader18 avatar cryze avatar d3lm avatar dekellum avatar faern avatar jake-shadle avatar lochlanna avatar ltratt avatar m-ou-se avatar malojaffre avatar mbrubeck avatar messense avatar notgull avatar ohanar avatar paulocsanz avatar peamaeq avatar peterthejohnston avatar taiki-e avatar torkleyy avatar valloric avatar waywardmonkeys avatar xampprocky avatar yjhn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parking_lot's Issues

Mappable lock guards

Would it be possible to implement a map method on (some of) the lock guards? There has been talks about it being unsound for some implementations of Mutex, particularly the one in the standard library, but there are ways to do it and it's a very useful feature. Do you think it would work with your particular implementation?

parking_lot_core requires libc >= 0.2.15

As far as I can see pthread_condattr_t and friends were introduced in version 0.2.15 of libc but parking_lot_core says it only depends on ^0.2. Because of this I got some "unresolved name" build errors when I tried to build parking_lot together with libc 0.2.12.

lock_api tests are broken with latest rust

---- src/lib.rs -  (line 29) stdout ----
error[E0046]: not all trait items implemented, missing: `GuardMarker`
  --> src/lib.rs:37:1
   |
11 | unsafe impl RawMutex for RawSpinlock {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `GuardMarker` in implementation
   |
   = note: `GuardMarker` from trait: `type GuardMarker;`

thread 'src/lib.rs -  (line 29)' panicked at 'couldn't compile the test', librustdoc/test.rs:330:13
note: Run with `RUST_BACKTRACE=1` for a backtrace.

"this is an associated function, not a method" error with RwLockUpgradableReadGuard::upgrade

Seeing a compilation error of "this is an associated function, not a method" when trying to call upgrade() on a RwLockUpgradableReadGuard. I've narrowed this down to parking_lot version 0.6.0; version 0.5.5 compiles the below files with no error (just irrelevant warnings about unused vars).

Was this breakage intentional? If so, what's the ergonomic way of calling upgrade() now? Frankly I have no idea how to call this method with >=0.6.0; even the help note from rustc isn't working out for me (maybe I'm dumb though).

Repro rust source file:

extern crate parking_lot;

use parking_lot::RwLock;

fn main() {
    let lock = RwLock::new(());
    let guard1 = lock.upgradable_read();
    let x = guard1.upgrade();
}

Cargo.toml:

[package]
name = "rusty-playground"
version = "0.1.0"

[dependencies]
parking_lot = "=0.6.3"

Compilation error:

$ cargo build
   Compiling rusty-playground v0.1.0 (file:///home/valloric/repos/rusty-playground)
error[E0599]: no method named `upgrade` found for type `lock_api::rwlock::RwLockUpgradableReadGuard<'_, parking_lot::raw_rwlock::ParkingLotRwLock, ()>` in the current scope
 --> src/main.rs:8:20
  |
8 |     let x = guard1.upgrade();
  |             -------^^^^^^^
  |             |      |
  |             |      this is an associated function, not a method
  |             help: use associated function syntax instead: `lock_api::rwlock::RwLockUpgradableReadGuard<'_, parking_lot::raw_rwlock::ParkingLotRwLock, ()>::upgrade`
  |
  = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
  = note: the candidate is defined in an impl for the type `lock_api::rwlock::RwLockUpgradableReadGuard<'_, _, _>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: Could not compile `rusty-playground`.

To learn more, run the command again with --verbose.

Why not spin wait inside the parking_lot park?

You spin a bit in https://github.com/Amanieu/parking_lot/blob/master/src/raw_mutex.rs#L149 .

Why not spin a bit in https://github.com/Amanieu/parking_lot/blob/master/core/src/thread_parker/linux.rs#L49 ?

Maybe I'm missing something but spinning in the parking_lot park should be more efficient than spinning on the address directly because each thread has its own local data that it would spin on.

I benchmarked it and a straightforward attempt seemed to make mutexes slightly faster.

NT Keyed Events-Panic

Hey, I get:
panicked at 'parking_lot requires either NT Keyed Events (WinXP+) or WaitOnAddress/WakeByAddress (Win8+)'
when using a library that depends on parking_lot's Mutex etc.

What exactly does this mean? Do I have to install something in particular?
Running Windows 7, 64bits.

Fails to build from source on x86_64-unknown-linux-gnux32 due to wrong type tv_nsec

Trying to build rustc on x86_64-unknown-linux-gnux32 fails due to an issue with parking_lot on this target with tv_nsec:

   Compiling parking_lot_core v0.2.9
error[E0308]: mismatched types
  --> /home/glaubitz/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.2.9/src/thread_parker/linux.rs:71:26
   |
71 |                 tv_nsec: diff.subsec_nanos() as libc::c_long,
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i64, found i32
help: you can cast an `i32` to `i64`, which will sign-extend the source value
   |
71 |                 tv_nsec: (diff.subsec_nanos() as libc::c_long).into(),
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: Could not compile `parking_lot_core`.

Caused by:
  process didn't exit successfully: `/srv/glaubitz/rust/rust/build/bootstrap/debug/rustc --crate-name parking_lot_core /home/glaubitz/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.2.9/src/lib.rs --error-format json --crate-type lib --emit=dep-info,link -C opt-level=2 --cfg feature="nightly" -C metadata=981ff45ad39e36a6 -C extra-filename=-981ff45ad39e36a6 --out-dir /srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnux32/release/deps --target x86_64-unknown-linux-gnux32 -L dependency=/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnux32/release/deps -L dependency=/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-rustc/release/deps --extern libc=/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnux32/release/deps/liblibc-c7b3face5395fe7c.rlib --extern rand=/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnux32/release/deps/librand-053103d70fc6fed7.rlib --extern smallvec=/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnux32/release/deps/libsmallvec-f17522e856c301a0.rlib --cap-lints allow` (exit code: 101)
warning: build failed, waiting for other jobs to finish...
error: build failed
thread 'main' panicked at 'command did not execute successfully: "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnux32" "-j" "64" "--release" "--features" " jemalloc" "--manifest-path" "/srv/glaubitz/rust/rust/src/rustc/Cargo.toml" "--message-format" "json"
expected success, got: exit code: 101', bootstrap/compile.rs:1061:9

This is a result of tv_nsec not being of the C type long but actually __syscall_slong_t which is a result of the kernel interface on x32 being 64-bit while the system itself is 32-bit.

A possible workaround for this issue would be something like

#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
tv_nsec: diff.subsec_nanos() as i64,
#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
tv_nsec: diff.subsec_nanos() as libc::c_long,

See also: rust-lang/libc#812 and https://sourceware.org/bugzilla/show_bug.cgi?id=16437

CC @malbarbo
CC @jrtc27

Why are these types not in the standard library?

I'm asking myself, if these are faster why aren't they in libstd? I think read something about platform limitations, but it's not really clear why the standard library has to use platform-specific types. I also saw other people wondering about this, might be worth adding it to the README.

Async handling

This is a follow-up from #24, hopefully more explicit :)

So first, a disclaimer: I know literally nothing about the internals of parking_lot, and very little about mutexes.

What I'd be looking for is a way to have parking_lot mutexes play nicely with futures. What I mean by “play nicely” is:

  • It should never block the whole thread, only a task on the thread pool
  • It should return eg. a Future<Item = MutexGuard<'a, T>>

The second point can easily be implemented by wrapping try_lock, so that leaves the first point to handle.

My reflection on parking_lot internals (please tell me if it's wrong) is:

  • There is a “low-level” layer, which puts a thread to sleep, wake up a thread, etc.
  • Upon these building blocks, mutexes are built
  • Upon mutexes, guards are built

Most of the complexity would stand in the second layer above.

What I'm thinking is that, if the first layer could be swapped with an async-friendly layer (that would put a task to sleep instead of the whole thread, wake up a task, etc.), then I think it would become possible to reuse the biggest part of the code, that is in how mutexes are built on top of these primitives.

A way to do that may be to parameterize all parking_lot types on a helper trait that provides said functions, and static-dispatch on it, with type aliases for more convenience.

Now, as stated above, I know nothing about the internals of parking_lot, so I may completely be wrong in my analysis. Feel free to tell it to me if so :)

So, what do you think about this idea of splitting away the low-level task handling from the mutex building?

Optionally disable writer starvation protection?

From the docs of RwLock:

This lock uses a task-fair locking policy which avoids both reader and writer starvation. This means that readers trying to acquire the lock will block even if the lock is unlocked when there are writers waiting to acquire the lock. Because of this, attempts to recursively acquire a read lock within a single thread may result in a deadlock.

I’m looking into building an abstraction on top of parking_lot to protect many objects with a single RwLock<()>. In the expected access patterns, I believe that starvation won’t be a problem but the deadlock with recursive reader access might be. Is it possible to configure RwLock to tweak this behavior?

CC @bholley

Reentrant locks

It would be interesting to have these as separated types.

Wishlist for a 1.0 release?

At some point it'd be nice to restart the conversation about getting this crate into the stdlib, or at least the nursery, and I think that process would be expedited if people had a way of knowing how far this crate is from being considered stable. Is there a checklist of some kind somewhere?

Usage of hardware lock ellision breaks rr.

Hi @Amanieu,

This issue is just to ping you about rr-debugger/rr#1883.

Basically we were hitting this in Servo, and I thought that other people that could be using rr to debug programs that use parking_lot would encounter this.

Basically, HLE makes rr break right now. Probably a runtime check for RUNNING_UNDER_RR is prohibitive (maybe under debug_assertions it isn't?). In any case, maybe a note in the Readme or similar could help someone.

Anyway, feel free to close this at any time, thanks!

-- Emilio

Mappable RwLock guards

This is a logical continuation of #10. It looks like the MappableMutexGuard is implemented, but nothing is done for RwLock. We have a strong case for it: a map with data that needs to be either read or created and then read. Ideally, it would have the following implementation (roughly):

fn get_data(&self, key: Key) -> ReadGuard<Data> {
  // lock the map, but only deal with a particular entry
  let guard = self.lock.upgradable_read().map(|map| map.entry(key));
  // fast path for keys already filled up
  if let Entry::Occupied(e) = *guard {
    return *e;
  }
  // slow path to add a new value
  let data = create_heavy_state(key);
  let gw = guard.upgrade();
  gw.or_insert(data);
  // and return it
  gw.downgrade().or_insert_with(|| ureachable!())
}

Document features

The deadlock_detection feature is documented a bit indirectly via API docs of the core crate. The nightly feature is only discussed on the issue tracker.

If this summary correct, could you please document all features in the README and/or API docs, in a more conspicuous way?

Extract out useful sub-crates.

parking_lot contains a number of useful pieces that are relatively independent. The implementation of SpinWait for example could come in handy for a number of other projects. Any chance of these being split out into independent crates that are then used by parking_lot?

UnwindSafe + RefUnwindSafe

Hi,
I apologize in advance for a question which might seem basic:

The standard library Mutex type implements UnwindSafe + RefUnwindSafe:

impl<T: ?Sized> UnwindSafe for Mutex<T>
impl<T: ?Sized> RefUnwindSafe for Mutex<T>

However, the implementation in a parking_lot doesn't.

The understanding of both implementations currently a bit out of my depth, but would it be practical (or even possible, for that matter) to lift those restrictions (implement the traits) for parking_lot::Mutex?

I encountered this problem, when the library I was writing against bumped it's major API to require those trait bounds, and my code was already using the parking_lot.

Document minimum required Rust version policy

A recent release of parking_lot_core increased the minimum required Rust version to 1.26. The commit was made ~3 months ago.

Would you mind documenting in the README what the policy is to increase the minimum required Rust version?

Poison detection

Poison detection can be very useful, especially for debug builds.

One possible implementation can share the backend already in place for deadlock detection (w/ minor modifications).

Something along those lines could work:

  1. Check if the thread is panicking on each guard drop()
    2a. If so, register it in the wait graph (ex: mutex A waits for mutex A).
    2b. If so, leave the mutex/rwlock locked (not required I think)
  2. Modify the cycle detection to account for such cases

Naturally, calling std::thread::panicking is probably not super cheap so this must go behind a feature flag as well.

Consider bumping the minor version on rustc bumps

This PR bumped the required Rust version from 1.13 to 1.18. While I don't think that's a problem since many users have that version already, I think it's a good practice to bump the minor version instead of the patch version on such a release. Releasing just a patch version can break other Travis builds that assure a certain rustc version works.

Selectable synchronization primitives

Forgive me if this is just totally outside the scope of this crate, given that I'm not really sure what level of added complexity/overhead this feature would add, but it would be wonderful to be able to do a "select" operation on multiple synchronization primitives (or even just multiple of the same kind).

Currently when using the std::sync/pthread primitives whenever I run into a case where I just want to select on e.g. a condition variable and a mutex or two condition variables I have to stop and go back to the whiteboard and figure out another strategy. Being able to select would open up a large number of other strategies and make implementing all sorts of things easier.

Doesn't work on stable

I know it might be obvious for some, but for me I was a little bit disappointed when I found out:

  Compiling parking_lot v0.1.0
/home/jhasse/.cargo/registry/src/github.com-88ac128001ac3a9a/parking_lot-0.1.0/src/lib.rs:101:1: 101:66 error: #[feature] may not be used on the stable release channel
/home/jhasse/.cargo/registry/src/github.com-88ac128001ac3a9a/parking_lot-0.1.0/src/lib.rs:101 #![feature(extended_compare_and_swap, const_fn, integer_atomics)]
                                                                                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Maybe add a note in the README?

Parking lot mutex failing at runtime on Windows 7 32-bit

I have been using the mutex from parking_lot in a number of projects on Windows 10, with no trouble. In particular the fact that it is a fair mutex is extremely valuable to me. When I tried to compile and run my code on Windows 7 however, I ran in to some trouble.

Compilation was completed without any issue. At runtime however, I got the following error printed out in my logs:

2018-04-21 10:09:50.711026800 ERROR nbe - thread 'ble_writer_result' panicked at 'parking_lot requires either NT Keyed Events (WinXP+) or WaitOnAddress/WakeByAddress (Win8+)': C:\dir\src\github.com-1ecc6299db9ec823\parking_lot_core-0.2.10\src\thread_parker/windows/mod.rs:39
2018-04-21 10:09:50.711026800 ERROR nbe - thread 'ble_writer_result' panicked at 'parking_lot requires either NT Keyed Events (WinXP+) or WaitOnAddress/WakeByAddress (Win8+)': C:\dir\src\github.com-1ecc6299db9ec823\parking_lot_core-0.2.10\src\thread_parker/windows/mod.rs:39
2018-04-21 10:09:50.711026800 ERROR nbe - ble_writer_thread terminated with Err: Any

I would have thought the WinXP+ for NT Keyed Events would have implied that Windows 7 was covered by this.

Exposing RawMutex and RawRwLock in the public API?

I'm writing some unsafe code that manages raw pointers directly for perf and I really need to store a RW lock inside a larger data-structure. The parking_lot_core crate has useful primitives to build such a lock, but all what I really need is the RawRwLock type that's already in parking_lot. There's little point in me implementing it from scratch.

Could RawRwLock (and thus likely RawMutex) be exposed in the public API? This would make writing low-level data-structures with embedded locks much easier.

Expose raw locking primitives

Types like ParkingLotRwLock are needed for the outside world in order to build any type safe primitives using lock_api generic interface. Any reason they are not public?

Deadlock detection

How hard would it be to detect deadlocks and other types of "runtime bugs" in debug mode?

parking lot is broken with recent nightly

$ rustc --version
rustc 1.25.0 (84203cac6 2018-03-25)
$ rustup --version
rustup 1.13.0 (ea9259c1b 2018-07-16)
$ cargo --version
cargo 0.26.0 (41480f5cc 2018-02-26)

error[E0658]: use of unstable library feature 'thread_local_state': state querying was recently added (see issue #27716)
   --> /home/travis/.cargo/registry/src/github.com-1ecc6299db9ec823/parking_lot_core-0.3.0/src/parking_lot.rs:169:34
    |
169 |     if let Ok(tls) = THREAD_DATA.try_with(|x| x as *const ThreadData) {

Once<T = ()>

I think that typically when you want a Once, you're calculating a value, as in the example in the documentation. I propose parking_lot make it safe to do so by wrapping the value in the Once as Mutex and such do. I think defaulting the parameter to () would mean this wouldn't be a breaking change.

(It'd be like the lazycell crate's AtomicLazyCell except that if thread A tries to fill the cell while thread B is already doing so, thread A will wait for thread B. lazycell returns an error in this case.)

I think this would almost make it possible to lose the unsafe in said example:

use parking_lot::{Once, ONCE_INIT};

static VAL: Once<usize> = ONCE_INIT;  // error here :-(

// This function will only call `expensive_computation` once, and will
// otherwise always return the value returned from the first invocation.
fn get_cached_val() -> usize { VAL.call_once(expensive_computation) }

fn expensive_computation() -> usize {
    // ...
}

except that I don't think there can be a ONCE_INIT that would work for all types. So to make this work as a static for types other than (), it'd either have to use const fns (unstable) or expose the inner workings of the type (and I guess that'd be back to unsafe anyway as there'd be an UnsafeCell). So for now, this would be beneficial for non-statics, potentially beneficial for nightly with statics, and no worse than before for stable rust with statics.

No unwrap() function in MutexGuard

std::sync::MutexGuard has an unwrap function that returns the contents of the mutex mutably. The lack of this in parking_lot makes it hard to just test it as a drop-in replacement for std::sync::mutex.

Contention statistics

Is there (or will there be) an ability in parking_lot to gather some stats about the effectiveness of locks? E.g. an average wait time, contention ratio, etc? This would assist us greatly in making decisions as to what to lock and how in gfx-rs/gfx#2229 .

Failing to compile on ARM device

I'm relatively new to Rust, mainly just using it to compile a program I need on an ARM device.

The program requires parking_lot which seems to cause the error:

   Compiling parking_lot v0.5.1
error[E0308]: mismatched types
   --> /home/rescue/.cargo/registry/src/github.com-1ecc6299db9ec823/mach_object-0.1.5/src/commands.rs:694:54
    |
694 |         unsafe { Ok(String::from(try!(CStr::from_ptr(buf.as_ptr() as *const i8).to_str()))) }
    |                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

   Compiling string_cache_codegen v0.4.0
error[E0308]: mismatched types
   --> /home/rescue/.cargo/registry/src/github.com-1ecc6299db9ec823/mach_object-0.1.5/src/commands.rs:889:54
    |
889 |         unsafe { Ok(String::from(try!(CStr::from_ptr(s.as_ptr() as *const i8).to_str()))) }
    |                                                      ^^^^^^^^^^^^^^^^^^^^^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error: aborting due to 2 previous errors

error: Could not compile `mach_object`.
warning: build failed, waiting for other jobs to finish...
error: build failed

implement Clone for RwLockReadGuard

Currently RwLock::read_recursive() can be used to achieve the same effect, but clone is easier to use and doesn't require a reference to the underlying lock.

lock types should use fences somewhere

We seem to currently be using plain atomics in the implementation of RwLock and Mutex. However, if you have something like RwLock<Vec<T>>, there's no guarantee that a write to the vector will reach another thread when it acquires a read lock shortly thereafter; you need a memory fence for that.

On x86 this doesn't matter since it has a strongly ordered memory model, but on ARM or w/e it will.

cc @eddyb

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.