ThreadFuture would send a mutex to the thread it spawned, which would then immediately lock that mutex to pass it into whichever blocking callback wanted to write to the data inside it.
Meanwhile, calling poll on that ThreadFuture would also lock that mutex, blocking until the spawned thread finished running and hence defeating the entire purpose of using a future, and possibly even causing the spawned thread to block instead if poll was called fast enough, causing a deadlock.
This is fixed by separating the data and waker into two separate mutexes; calling poll always sets the waker but only try_locks the mutex for data.
ThreadFuture would send a mutex to the thread it spawned, which would then immediately lock that mutex to pass it into whichever blocking callback wanted to write to the data inside it.
Meanwhile, calling
poll
on that ThreadFuture would also lock that mutex, blocking until the spawned thread finished running and hence defeating the entire purpose of using a future, and possibly even causing the spawned thread to block instead ifpoll
was called fast enough, causing a deadlock.This is fixed by separating the
data
andwaker
into two separate mutexes; callingpoll
always sets thewaker
but onlytry_lock
s the mutex fordata
.