--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
We also don't have CondVars.
Hey Fred,While I support this in general, there are a bunch of controversial things / google3isms. For an example of controversial, I think the recommended commenting practice may be debatable. I am all for it, but I don't know if others are. So I'm concerned about saying it's "strongly recommended", especially since most (all?) of our code doesn't follow this convention. Also, there are many places in the document that reference Mutex instead of Lock. We also don't have CondVars.
That was a great read, thanks for sharing. I'd like to know what's recommended in chromium regarding this:"""Why not always use AutoLock?Critical section boundaries do not always make it convenient to use AutoLock. Even when they do, programmers should be aware that using AutoLock is not always an improvement.Like scoped_ptr, AutoLock introduces a tradeoff in readability. It makes it clear that the lock is released, but because the Release() becomes implicit, it may become less clear when it is released, especially in complex routines with long blocks."""I actually find AutoLock and scoped_ptr way easier to read and understand, and way more robust regarding future edits around the code in scope. So what's the encouraged style for chromium?
I think it's worthwhile for the top of the document to suggest that
you shouldn't use explicit locking in Chromium except as a last resort
where you've definitively demonstrated that PastTask and kin simply
won't do the job. My general feeling is that for most developers,
once they're trying to decide whether they need a lock or not, they've
already lost the battle, and no amount of documenting things is going
to salvage the situation.
-scott
(Also, since it's not obvious how to edit the document, you have to
scroll all the way down and click the 'Sign In' link way at the bottom
before the 'Edit' controls show up.)
> This is yet another m3b'ism. He hates RAII. I think he would prefer we use C
> instead of C++. I strongly recommend using AutoLock.
Done.
> This is yet another reason why I'd be cautious about all the recommendations
> which haven't been discussed here. Internally, this doc is in m3b's home
> directory, and not an official document (although widely referenced, because
> m3b has many solid recommendations and is a concurrency badass). I recommend
> selectively copying parts rather than doing a wholesale copy and
> post-trim/edit. It's a wonderful read for anyone who cares about
> concurrency, but be cautious about some of the recommendations here, which
> are also debated internally, since Googlers are very contentious about
> style.
This document is actually already pretty cut-down from the original.
But I guess I wasn't ruthless enough in trimming it.
> Note, we only have 2 thread priority levels, so the priority section is
> largely irrelevant, and I'd actually simply rather the vast majority
> Chromium engineers not think about thread priorities at all. Honestly, I'd
> rather people try to avoid Locks. Chromium style is to keep most code single
> threaded and use message passing. I'd rather be consistent and not encourage
> people to use Locks.
Removed, and posted a warning at the top.
> What's the motivation here for this document? While an awesome concurrency
> doc, I'd rather we spend more time improving documentation about our
> Chromium patterns. And perhaps advocating using the thread annotation style
> commenting with our Locks. Just my two cents.
Basically, this came out of
http://code.google.com/p/chromium/issues/detail?id=117469 and the
underlying bug, which would have likely been prevented by the
recommendations in the document. Even though 99% of the time we
should be using TaskRunner/MessageLoops, the other 1% of the time it's
useful to have a document which outlines the best practices and the
pitfalls of using locks/CVs.
On Mon, Mar 12, 2012 at 5:38 PM, William Chan (陈智昌)
<will...@chromium.org> wrote:
> While you're at it, remember that there is no Await() either in Lock. Also
> there's no ReaderAcquire(). Also, in Chromium we do std::deque instead of
> "using std::deque;" (ew!!!).
Done.
> I think in chrome code, we tend to do the opposite. Use "messages"
> (PostTask) in doubt, but mutexes locally when it makes sense. Worth noting
> IMO.
Done.
On Mon, Mar 12, 2012 at 5:57 PM, Scott Hess <sh...@chromium.org> wrote:
> I think it's worthwhile for the top of the document to suggest that
> you shouldn't use explicit locking in Chromium except as a last resort
> where you've definitively demonstrated that PastTask and kin simply
> won't do the job. My general feeling is that for most developers,
> once they're trying to decide whether they need a lock or not, they've
> already lost the battle, and no amount of documenting things is going
> to salvage the situation.
Done.
Hmm. Perhaps it doesn't belong under 'coding style', but maybe it
still belongs under 'Practices'? Maybe the threading document belongs
there, too; I wouldn't have thought to look in design documents for
nitty-gritty technical stuff like using threads and such.
This is yet another m3b'ism. He hates RAII. I think he would prefer we use C instead of C++. I strongly recommend using AutoLock.This is yet another reason why I'd be cautious about all the recommendations which haven't been discussed here. Internally, this doc is in m3b's home directory, and not an official document (although widely referenced, because m3b has many solid recommendations and is a concurrency badass). I recommend selectively copying parts rather than doing a wholesale copy and post-trim/edit. It's a wonderful read for anyone who cares about concurrency, but be cautious about some of the recommendations here, which are also debated internally, since Googlers are very contentious about style.Note, we only have 2 thread priority levels, so the priority section is largely irrelevant, and I'd actually simply rather the vast majority Chromium engineers not think about thread priorities at all. Honestly, I'd rather people try to avoid Locks. Chromium style is to keep most code single threaded and use message passing. I'd rather be consistent and not encourage people to use Locks.What's the motivation here for this document? While an awesome concurrency doc, I'd rather we spend more time improving documentation about our Chromium patterns. And perhaps advocating using the thread annotation style commenting with our Locks. Just my two cents.
I think the closest section would be the 'Development Tips & Tricks'
section, although I think if we were to move the threading/mutex docs
there, we'd have to rename it something like 'Development Guides'.
What do you think?
Hello everyone,With permission, and on siggi@'s suggestion, I took Mike Burrows' excellent (internal-only) document on mutexes and condition variables and put an
We shouldn't be using these low-level synchronization primitives very often, but when we need to, this document explains the best practices and pitfalls of doing so.There are some TODOs in the document: one to get the anchor links working, and the rest to verify some assertions about efficiency and functionality. Perhaps someone with more sites-fu can fix the first, and someone with deeper knowledge of the behavior of the OS-specific primitives we use can fill in the rest.Let me know if you have any questions, comments, or suggestions!- Fred
I agree, that works.-Darin
Plus a lot of times people just want to wait on a boolean. In such cases, please use WaitableEvent instead.
--
Of course! Everyone, feel free to expand and improve the document.
Lock
."I had a look at this document, it's really good (one of the best I've read) but it left me with a couple of unanswered questions, and I'm hoping some experts reading this can set the record straight.From the document: "Variables accessed by more than one thread and written by at least one thread should be protected consistently by aLock
."Does this apply to booleans? Is there a consensus on how booleans should be treated in Chrome code? Do they need full locking? Declaring as volatile OK? Or don't bother? My own understanding is that booleans do need some kind of locking, even though booleans are atomic, because there is a possibility of a change made in one thread not becoming visible in another thread. Is this actually true on systems we care about?
My second question is about this assertion from the document: "An exception to this rule is that fields may be initialized in constructors without a mutex, since no other thread should be able to reference the memory at that time."I seem to remember reading something a long time ago that contradicted this assertion (and claimed it to be a common myth). Unfortunately, I can't remember where I read this, and haven't been able to find anything I'd trust as definitive. The claim I read was (IIRC): if you allocate a new object, initialize one of the fields (in initialization list or ctor), then access the object from another thread without using a memory barrier, the other thread might see the "default" value of the field, and not the correctly-initialized value.
On Fri, Mar 23, 2012 at 10:20 AM, Fred Akalin <aka...@chromium.org> wrote:Of course! Everyone, feel free to expand and improve the document.I had a look at this document, it's really good (one of the best I've read) but it left me with a couple of unanswered questions, and I'm hoping some experts reading this can set the record straight.From the document: "Variables accessed by more than one thread and written by at least one thread should be protected consistently by aLock
."Does this apply to booleans? Is there a consensus on how booleans should be treated in Chrome code? Do they need full locking? Declaring as volatile OK?
Or don't bother? My own understanding is that booleans do need some kind of locking, even though booleans are atomic,
My second question is about this assertion from the document: "An exception to this rule is that fields may be initialized in constructors without a mutex, since no other thread should be able to reference the memory at that time."
I seem to remember reading something a long time ago that contradicted this assertion (and claimed it to be a common myth). Unfortunately, I can't remember where I read this, and haven't been able to find anything I'd trust as definitive. The claim I read was (IIRC): if you allocate a new object, initialize one of the fields (in initialization list or ctor), then access the object from another thread without using a memory barrier, the other thread might see the "default" value of the field, and not the correctly-initialized value.So I was wondering if anyone could support the document's assertion with a reference, saying "yes, this is definitely safe, no memory-barrier needed, because of X, Y and Z...". Or maybe the problem is theoretical and simply doesn't occur on any machine or implementation we care about?Thanks,Lambros
In general, you should not reason your way around locking. Removing
the need to do locking by removing the need to access the value from
multiple threads, +1. But removing it by arguing that your access
patterns are so structured as to make it not necessary should only be
left to experts.
[To be clear, I am not suggesting that I am an expert, or that there
is some way to bless Chromium team members. Rather, history is
littered with bugs and security holes written by people reasoning
their way around locking primitives. It's just a hard problem.]
> My second question is about this assertion from the document: "An exception
> to this rule is that fields may be initialized in constructors without a
> mutex, since no other thread should be able to reference the memory at that
> time."
>
> I seem to remember reading something a long time ago that contradicted this
> assertion (and claimed it to be a common myth). Unfortunately, I can't
> remember where I read this, and haven't been able to find anything I'd trust
> as definitive. The claim I read was (IIRC): if you allocate a new object,
> initialize one of the fields (in initialization list or ctor), then access
> the object from another thread without using a memory barrier, the other
> thread might see the "default" value of the field, and not the
> correctly-initialized value.
>
> So I was wondering if anyone could support the document's assertion with a
> reference, saying "yes, this is definitely safe, no memory-barrier needed,
> because of X, Y and Z...". Or maybe the problem is theoretical and simply
> doesn't occur on any machine or implementation we care about?
Being able to access the value without an intervening memory barrier
implies that someone was walking a shared data structure without
holding a lock. I think.
-scott
On Fri, Mar 23, 2012 at 10:20 AM, Fred Akalin <aka...@chromium.org> wrote:Of course! Everyone, feel free to expand and improve the document.I had a look at this document, it's really good (one of the best I've read) but it left me with a couple of unanswered questions, and I'm hoping some experts reading this can set the record straight.From the document: "Variables accessed by more than one thread and written by at least one thread should be protected consistently by aLock
."Does this apply to booleans? Is there a consensus on how booleans should be treated in Chrome code? Do they need full locking?
Declaring as volatile OK?
Or don't bother? My own understanding is that booleans do need some kind of locking, even though booleans are atomic, because there is a possibility of a change made in one thread not becoming visible in another thread. Is this actually true on systems we care about?
My second question is about this assertion from the document: "An exception to this rule is that fields may be initialized in constructors without a mutex, since no other thread should be able to reference the memory at that time."I seem to remember reading something a long time ago that contradicted this assertion (and claimed it to be a common myth). Unfortunately, I can't remember where I read this, and haven't been able to find anything I'd trust as definitive. The claim I read was (IIRC): if you allocate a new object, initialize one of the fields (in initialization list or ctor), then access the object from another thread without using a memory barrier, the other thread might see the "default" value of the field, and not the correctly-initialized value.
So I was wondering if anyone could support the document's assertion with a reference, saying "yes, this is definitely safe, no memory-barrier needed, because of X, Y and Z...". Or maybe the problem is theoretical and simply doesn't occur on any machine or implementation we care about?
Thanks,Lambros
On Fri, Mar 23, 2012 at 12:11 PM, Lambros Lambrou <lambros...@chromium.org> wrote:
On Fri, Mar 23, 2012 at 10:20 AM, Fred Akalin <aka...@chromium.org> wrote:Of course! Everyone, feel free to expand and improve the document.I had a look at this document, it's really good (one of the best I've read) but it left me with a couple of unanswered questions, and I'm hoping some experts reading this can set the record straight.From the document: "Variables accessed by more than one thread and written by at least one thread should be protected consistently by aLock
."Does this apply to booleans? Is there a consensus on how booleans should be treated in Chrome code? Do they need full locking?YesDeclaring as volatile OK?volatile doesn't do what you think it does. It only tells the compiler how to generate the code (force a memory access, enforce compiler-level ordering rules), but it's orthogonal to cpu-level reordering.Or don't bother? My own understanding is that booleans do need some kind of locking, even though booleans are atomic, because there is a possibility of a change made in one thread not becoming visible in another thread. Is this actually true on systems we care about?yes
My second question is about this assertion from the document: "An exception to this rule is that fields may be initialized in constructors without a mutex, since no other thread should be able to reference the memory at that time."I seem to remember reading something a long time ago that contradicted this assertion (and claimed it to be a common myth). Unfortunately, I can't remember where I read this, and haven't been able to find anything I'd trust as definitive. The claim I read was (IIRC): if you allocate a new object, initialize one of the fields (in initialization list or ctor), then access the object from another thread without using a memory barrier, the other thread might see the "default" value of the field, and not the correctly-initialized value.So I was wondering if anyone could support the document's assertion with a reference, saying "yes, this is definitely safe, no memory-barrier needed, because of X, Y and Z...". Or maybe the problem is theoretical and simply doesn't occur on any machine or implementation we care about?You need a memory barrier, but in chrome code, you have an implicit one when, say, you post a task to the other thread. Constructing a case where you'd pass the object to another thread without a memory barrier (and otherwise correct) is pretty hard. You need to pass the object through some shared state, that you'd need to lock to modify. One exception is a global object with static construction. But those are forbidden.AntoineThanks,Lambros