0.2.11
Tokio examples are using blocking mutexes, like in https://github.com/tokio-rs/tokio/blob/master/examples/tinydb.rs. Technically in this context it is provable, that it doesn't cause a deadlock, but locking mutexes in async code is a missuse - this should be switched to either use channels, or async aware mutex, to learn good practices by examples.
I couldn't find any use of Mutex, std::sync, or anything like a lock call in the example you reference. Could you give a line number or otherwise explain further?
@dekellum I am sorry, my mistake - posted wrong file, tinyhttps instead of tinidb. Anyway, in https://github.com/tokio-rs/tokio/blob/master/examples/tinydb.rs there is a mutexed variable in line 59 which is locked in 157. I am aware, that this is actually not a big problem here - because the mutex is released before any awaiting call, there is no deadlock, however it still involves blocking call in the future.
I may prepare PR (checking all examples for such issues) in the weekend, I just want to confirm that it is something which should be done.
I see. The tinydb example has a long history and was converted to async鈾痑wait (61aee5fc2) before the tokio::sync::Mutex was particularly complete.
Using a blocking Mutex may still be valid, IMO for short or minimally-contended operations, but I agree it would be more _idiomatic_ for this example to use the async tokio::sync::Mutex. Such a PR should hopefully be well received.
In this case and in _some_ cases its actually better to use a blocking mutex. We may want to promote usage of our internal mutex since this was written before that was a thing.
I think we also should probably document in what situations you should use which type of mutex to clear that up. But using a std::sync::Mutex isn't a misuse and can be totally valid.
@LucioFranco do you have some source which would explain when using blocking mutex in async code may be better than anything else? My undestanding is that if locking this mutex would ever block, it would block polling feature it is in, and this is agains any async rules. On the other hand if it is provable, that the mutex would be never locked in two different tasks, then it should be possible to resign from mutex at all (possibly redesigning solution).
I may have some inaccurate knowledge in terms of async-related optimizations, but I would really like to improve myself if so.
@hashedone we do not have things really written down yet, but I think we will include a section once the site gets updated a bit more.
Basically, it comes down to how fast your critical sections are and how much contention you have on that one component. In some cases, locking a mutex, updating a value, dropping the lock can be faster than the work required to lock a async mutex. In that case it makes sense to use a std mutex since its faster.
As for blocking, its never _don't_ block but its what are you blocking on and what is the potential length it could be blocked for. A mutex with a small critical section will not block for very long if the contention is low enough.
Its probably worth it to write up more on this once I find some time.
We have an entire chapter on this in the tutorial now, as well as a section on the API reference.
Most helpful comment
@hashedone we do not have things really written down yet, but I think we will include a section once the site gets updated a bit more.
Basically, it comes down to how fast your critical sections are and how much contention you have on that one component. In some cases, locking a mutex, updating a value, dropping the lock can be faster than the work required to lock a async mutex. In that case it makes sense to use a std mutex since its faster.
As for blocking, its never _don't_ block but its what are you blocking on and what is the potential length it could be blocked for. A mutex with a small critical section will not block for very long if the contention is low enough.
Its probably worth it to write up more on this once I find some time.