The landing of bugs 58904 and 456272 have brought a new synchronization API to the Mozilla platform. I think I’m safe in saying that the old API (PRLock, nsAutoLock, and friends) is deprecated in favor of the new. But this is a good thing; you’ll prefer the new one, trust me.
The carrots
We’ve improved the API in the following ways
- all classes are in the
mozillanamespace - the “bare” primitives (
Mutex,Monitor,CondVar) can now be allocated on the stack or as direct class members. Their constructors use a proto-non-failingmalloc, so your code will never see out-of-memory errors. - the primitives and their RAII wrappers (
MutexAutoLock/Unlock,MonitorAutoEnter) provide methods to assert that the primitive is “owned,” or not, by the currently executing thread. These should be used liberally in your code to enforce locking invariants (the assertions disappear in optimized builds). - the deadlock detector used by the new primitives in debug builds is asymptotically (and practically) more efficient than the old, should catch more deadlocks, and is now thread safe (!).
The sticks
As with any change to core APIs, this one will require a lot of rewriting. We’ll keep the old one around for a while, but new patches should use the new API. (Aside: Shawn Wilsher has been an early adopter, for the storage code. Check out what he’s been doing for some real-world examples.)
We’ve been extending our static analysis/refactoring tools to make upgrading old code easier. Hopefully, few people will need to worry about this. I’ll soon be blogging about our work; I think it’s a good example of how sweeping changes to existing code can be done quite easily, by one or two guys, in a matter of weeks.
The main change to the API that may cause some consternation is the removal of the nsAutoLock::lock/unlock and nsAutoMonitor::Enter/Exit methods from MutexAutoLock and MonitorAutoEnter. It has been decreed that they are bad news. Unfortunately, these are fairly difficult to rewrite automatically, so we may need to recruit a few module owners to help out.
Further reference
Most of the new API is documented on MDC. But please ping cjones on IRC if you have more questions or concerns.
[EDIT I see from PMO that I should be h4 and below.]
Comments (5)
> Their constructors use a proto-non-failing malloc, so your code will never see out-of-memory errors.
The patch looks like the way it doesn’t fail is by aborting:
+ mLock = PR_NewLock();
+ if (!mLock)
+ NS_RUNTIMEABORT(“Can’t allocate mozilla::Mutex”);
seems like a horrible idea to me, but whatever…
Hey, I said *proto*-non-failing, didn’t I?
BTW, it’s not all that bad of an idea, especially for sync primitives.
There is no plans to expand the API beyond what NSPR provides, correct? (In particular, a trylock would be awesome, but isn’t exposed by NSPR.)
Do the magic rewriting tools 1) have a useful install that can run outside of the environment of whoever runs them now, and 2) run on non-libxul (i.e. external) code?
There are no plans to extend the API at the moment, but we could add |Trylock()| pretty easily. NSPR already has it, but it’s private to NSPR. You can file a bug on it if you’d find it really useful.
> 1) have a useful install that can run outside of the environment of whoever runs them now
Sort of. The install is a little tedious, but it’s documented here:
https://developer.mozilla.org/En/Pork
However, there’s a “magic” new tool that hasn’t landed yet. It should happen soon. I’ll blog about it in the near future.
> 2) run on non-libxul (i.e. external) code?
Yup, nothing Mozilla-specific here.
I very much agree, a try lock would be great and seems like a good time to add it given these changes.