[Russell Warren]
I'm guessing no, since it skips down through any Lock semantics,
[Tim Peters] Good guess :-) It's also unsafe because some internal conditions must
be notified whenever the queue becomes empty (else you risk deadlock).
[Fredrik Lundh] "also" ? if it weren't for the other things, the clear() call itself
would have been atomic enough, right ?
Define "other things" :-) For example, Queue.get() relies on that
when self._empty() is false, it can do self._get() successfully.
That's 100% reliable now because the self.not_empty condition is in
the acquired state across both operations. If some yahoo ignores the
underlying mutex and clears the queue after self._empty() returns true
but before pop() executes self._get(), the call to the latter will
raise an exception. That kind of failure is what I considered to be
an instance of a problem due to the OP's "skips down through any Lock
semantics"; the failure to notify internal conditions that the queue
is empty is a different _kind_ of problem, hence my "also" above.
If you're just asking whether deque.clear() is "atomic enough" on its
own, define "enough" :-) It has to decref each item in the deque, and
that can end up executing arbitrary Python code (due to __del__
methods or weakref callbacks), and that in turn can allow the GIL to
be released allowing all other threads to run, and any of that
Python-level code may even mutate the deque _while_ it's being
cleared.
The C code in deque_clear() looks threadsafe in the sense that it
won't blow up regardless -- and that's about the strongest that can
ever be said for a clear() method. dict.clear() is actually a bit
stronger, acting as if a snapshot were taken of the dict's state at
the instant dict.clear() is called. Any mutations made to the dict
as a result of decref side effects while the original state is getting
cleared survive. In contrast, if a new item is added to a deque d
(via decref side effect) while d.clear() is executing, it won't
survive. That's "atomic enough" for me, but it is kinda fuzzy.