Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul and make Condvar::wait_timeout public #21132

Merged
merged 1 commit into from
Jan 17, 2015

Conversation

sfackler
Copy link
Member

The implementation is a direct adaptation of libcxx's condition_variable implementation.

I also added a wait_timeout_with method, which matches the second overload in C++'s condition_variable. The implementation right now is kind of dumb but it works. There is an outstanding issue with it: as is it doesn't support the use case where a user doesn't care about poisoning and wants to continue through poison.

r? @alexcrichton @aturon

@sfackler
Copy link
Member Author

I think there's a pretty easy tweak that can be made to wait_timeout_with to fix the poison issue, but I'm too tired to properly think it through right now. I'll fix it up tomorrow.

@sfackler
Copy link
Member Author

Another thing to consider here is that we may want to rename wait_timeout to wait_for. This matches with C++'s API and allows room for the addition of a wait_until method that takes an absolute time in some future release when std gains a time library.

let time_t_max: libc::time_t = Int::max_value();
let timeout = if time_t_max - dur.num_seconds() > sys_now.tv_sec {
libc::timespec {
tv_sec: sys_now.tv_sec + dur.num_seconds(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this use .checked_add to check for overflow instead?

@alexcrichton
Copy link
Member

There is an outstanding issue with it: as is it doesn't support the use case where a user doesn't care about poisoning and wants to continue through poison.

One possibly very weird thing to do would be to give the closure LockResult<&mut MutexGuard<T>> and then expect it to return Result<bool, PoisonError<&mut MutexGuard<T>>>. That's a pretty horrendous signature though, so I don't think we'd want to do that.

@sfackler
Copy link
Member Author

I don't think it'd need to return anything other than the bool. It's not passed ownership of the guard, so it can't unlock and relock, right?

@alexcrichton
Copy link
Member

I was thinking it could commonly be called as:

foo.wait_timeout_with(lock, duration, |state| Ok(try!(state).condition()));

The try! macro would somewhat necessitate returning something, although we could use FromError to do some more tricky. Altogether though it doesn't feel right no matter how I look at it, so I'm not a super huge fan of the idea.

@sfackler
Copy link
Member Author

I think we need to work out conventions on how the poisoning stuff should actually be used. My thought was you have the common cases where you don't expect to be poisoned, so you just unwrap and propagate the failure, or you don't care about poisoning so you'd call some method on LockResult to just give you the MutexGuard no matter what.

@alexcrichton
Copy link
Member

Yeah currently those looks like:

foo.unwrap() // assertion that "a poison is bad"
foo.unwrap_or_else(|e| e.into_guard()) // assertion that "I'm ok with poisons"

@sfackler
Copy link
Member Author

Just pushed fixes up in a new commit.

// Apparently android provides this in some other library?
#[cfg(not(target_os = "android"))]
#[link(name = "rt")]
extern {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was lost in movement to a different location

@sfackler
Copy link
Member Author

Updated

dur: Duration,
mut f: F)
-> LockResult<(MutexGuard<'a, T>, bool)>
where F: FnMut(&mut LockResult<MutexGuard<'a, T>>) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry when I said &mut T I meant:

where F: FnMut(LockResult<&mut T>) -> bool

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sure that seems reasonable. We'll definitely want to rename into_guard then though.

@alexcrichton
Copy link
Member

Ok this is all looking pretty good to me, would like @aturon's opinion as well, however.

@sfackler
Copy link
Member Author

Re-updated. Ideally, the function would take a &'a mut T, but I couldn't get the lifetimes to work :(

EDIT: Oh wait, that lifetime wouldn't make any sense at all.

@aturon
Copy link
Member

aturon commented Jan 16, 2015

So, I'm basically fine with this as an initial, experimental API.

In the long run, I'd like to nix the _with variance in favor of something more compositional -- like a generic adapter that can work with any timeout-based method + a closure for cancellation. But we can tackle that later. (Basically I would be opposed to making the _with variant #[stable] until we've explored more general solutions.)

@alexcrichton
Copy link
Member

r=me with a squash

@sfackler sfackler force-pushed the wait_timeout branch 3 times, most recently from 9881c4a to 5639f78 Compare January 16, 2015 07:46
**The implementation is a direct adaptation of libcxx's
condition_variable implementation.**

pthread_cond_timedwait uses the non-monotonic system clock. It's
possible to change the clock to a monotonic via pthread_cond_attr, but
this is incompatible with static initialization. To deal with this, we
calculate the timeout using the system clock, and maintain a separate
record of the start and end times with a monotonic clock to be used for
calculation of the return value.
bors added a commit that referenced this pull request Jan 17, 2015
**The implementation is a direct adaptation of libcxx's condition_variable implementation.**

I also added a wait_timeout_with method, which matches the second overload in C++'s condition_variable. The implementation right now is kind of dumb but it works. There is an outstanding issue with it: as is it doesn't support the use case where a user doesn't care about poisoning and wants to continue through poison.

r? @alexcrichton @aturon
bors added a commit that referenced this pull request Jan 17, 2015
**The implementation is a direct adaptation of libcxx's condition_variable implementation.**

I also added a wait_timeout_with method, which matches the second overload in C++'s condition_variable. The implementation right now is kind of dumb but it works. There is an outstanding issue with it: as is it doesn't support the use case where a user doesn't care about poisoning and wants to continue through poison.

r? @alexcrichton @aturon
@bors bors merged commit 08f6380 into rust-lang:master Jan 17, 2015
@sfackler sfackler deleted the wait_timeout branch November 26, 2016 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants