Comments (8)
Modulo the need to use 64-bit atomics, a ThreadId
approach can be made almost entirely identical in performance to the current one: in std::thread
when the current thread threadlocal, also have a thread local that only stores the thread ID and is set when the current thread is initialized and claims a thread ID. current_thread_unique_ptr
is replaced with consuming something like the following from std::thread
:
// in std::thread
thread_local! {
static CURRENT: OnceCell<Thread> = const { OnceCell::new() };
static CURRENT_ID: Cell<Option<ThreadId>> = const { Cell::new(None) };
}
/// Sets the thread handle for the current thread.
///
/// Panics if the handle has been set already or when called from a TLS destructor.
pub(crate) fn set_current(thread: Thread) {
CURRENT.with(|current| {
current.set(thread).unwrap();
CURRENT_ID.set(Some(thread.id()));
});
}
/// Gets a handle to the thread that invokes it.
///
/// In contrast to the public `current` function, this will not panic if called
/// from inside a TLS destructor.
pub(crate) fn try_current() -> Option<Thread> {
CURRENT
.try_with(|current| {
let thread = current.get_or_init(|| Thread::new(imp::Thread::get_name())).clone();
CURRENT_ID.set(thread.id().as_u64().get());
})
.ok()
}
/// Gets the id of the thread that invokes it.
///
/// If called from inside a TLS destructor and the thread was never
/// assigned an id, returns `None`.
pub(crate) fn try_current_id() -> Option<ThreadId> {
if CURRENT_ID.get().is_none() {
let _ = try_current();
}
CURRENT_ID.get()
}
The common case -- the thread was created by Rust and has its Thread
data already created -- only gains a pointer read and predicted comparison against zero over the current current_thread_unique_ptr
which uses the thread local address.
from rust.
This is a bit of rule-lawyering, but this isn't guaranteed. The documentation of lock
says:
This function will block the caller until it is available to acquire the lock. Upon returning, the thread is the only thread with the lock held. When the thread calling this method already holds the lock, the call succeeds without blocking.
And all of these things are fulfilled, even in the case you describe.
from rust.
Upon returning, the thread is the only thread with the lock held.
That part is false, since according to the documentation lock is unlocked when a lock guard is dropped. No lock guard is ever dropped in the example, so another thread still holds the lock.
If you would like to allow this execution, you would have to update the documentation to explain when and why lock was unlocked. Although, I would consider this to be clearly undesirable behavior.
Furthermore we already have ThreadId with necessary guarantees could be used to address the issue.
from rust.
so another thread still holds the lock
No, the other thread has died.
Furthermore we already have ThreadId with necessary guarantees could be used to address the issue.
Unfortunately, getting the ThreadId
is much more expensive, as it lives in Thread
, which is Drop
, and therefore needs a TLS destructor. Also, it will not be available in TLS destructors. We can get around this, of course, but the current approach is quite efficient, so it will be hard to beat.
from rust.
I agree that if this behavior stays as is, it should at least be very explicitly documented (something like "If a thread previously held the lock and terminated without releasing it, another thread may then be able to acquire the lock without deadlocking"). Still I'd prefer for the semantics to be "If any thread terminates while holding a lock, no other thread may ever reacquire the lock", which would require something like ThreadId
which is unique over the lifetime of the process. I'm not convinced that the ThreadId
approach would be much slower than the current one, it's mostly just cloning and then dropping an Arc, which is 2 atomic ops, and it saves a library call. On the other hand, using ThreadId
would then always require a 64 bit ID, which might need some form of spin lock protecting every access on platforms that don't have 64 bit atomics.
from rust.
I know the point of Reentrant
is to avoid deadlock, but my thinking is that if someone uses ManuallyDrop
on the guard, they probably had a good reason for it, and might want to keep it locked. I'm kinda fighting my own bias here though, since I've also been trying to prevent deadlocks in Rust.
from rust.
As this seems important to so many people, we should definitely add those docs.
I'm opposed to fixing this however, unless we find a really efficient solution. This gets called on every single println!
, so it's definitely on the hot path. Also, we might consider using pthread_self
for this in the future, which might be more efficient on Linux than the TLS access. pthread_id
s can get reused, so if we fix this, we wouldn't be able to do that.
from rust.
Since the tid is only ever written to while holding a mutex, we could just use a seqlock to store it on platforms which only support 32-bit atomics (which I believe all platforms with std
do), something like this: https://rust.godbolt.org/z/6dEnqz8be . While this means at least 4 atomic operations per tid access (including a store) instead of just 1, this seems acceptable to me because it would only affect 32 bit platforms anyways, the majority of platforms could just use a single 64 bit atomic access. Also, reader-writer contention would be extremely low, as the tid only gets written to when a thread acquires the first lock and when the last lock gets released. Would this together with the more efficient ThreadId
fetching by @CAD97 be a reasonable tradeoff to allow the stricter guarantee for process-lifetime unique thread ids?
from rust.
Related Issues (20)
- ICE on stable due to messed up target/ directory HOT 7
- Unheplful Borrow Error Related to Use of Borrows in Loop
- ICE: `assertion failed: layout.is_sized()` HOT 6
- Tracking Issue for future-compatibility warning `SELF_CONSTRUCTOR_FROM_OUTER_ITEM`
- ICE: `error performing operation: fully_perform` HOT 3
- Couldn't evaluate constant const with `-Zpolymorphize=on` HOT 2
- missing diagnostic HOT 1
- std::fs::symlink_metadata + set_permissions makes unintuitive behavior HOT 2
- test
- AST pretty-printer produces invalid syntax for postfix match
- ICE: `Layout::compute: unexpected type '_'` HOT 1
- The compiler keeps going on Ctrl-C HOT 13
- Document minimum supported versions for apple operating systems to platform documentation HOT 3
- Performance regression: rustc failed to optimize `_mm256_avg_epu8` after 1.75.0 HOT 8
- Future version of mingw-w64 breaks externally linking some math functions
- Tracking Issue for `macro_metavar_expr_concat` HOT 13
- Debug for FilePermissions prints the mode in decimal. HOT 3
- Improve error[E0492]: statics cannot refer to interior mutable data HOT 1
- `-C linker-plugin-lto` prevents vectorization of `mem::swap` at `-C opt-level=3` HOT 6
- Null reference in `PanicInfo.location().file()` when panicking on target `aarch64-nintendo-switch-freestanding` HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rust.