On Mon, Feb 25, 2008 at 4:28 PM, dormando <[EMAIL PROTECTED]> wrote: > Steve Chu wrote: > > On Mon, Feb 25, 2008 at 2:51 PM, dormando <[EMAIL PROTECTED]> wrote: > >> I think this is fine? > >> > >> Since the operations are independently atomic, it's perfectly valid for > >> two threads to incr the same value. > >> > > > > But for client api, they seems NOT atomic, because when Thread A just > > has 'item_get' done but before 'add_delta', Thread B can still do > > item_get. > > > > X-> set "foo" 1 > > A-> item_get "foo" > > B-> item_get "foo" > > A-> add_delta "foo" by 1 > > B-> add_delta "foo" by 1 > > > > then A and B both hold value 2, which one should be stored? > > > > And the exact value we need is 3, right? I am not quit sure, correct > > me if i am wrong:) > > The result gets copied into the thread-local 'temp' buffer, then copied > into that connection (implicitly atomic)'s output buffer. > > So actually I read the code wrong the first time. This _should_ do the > right thing: > > We have threads (A, B, X): > > X -> set 'foo' 1 > > A -> process_arithmetic_command() > note thread local storage (char temp[]) > B -> same. > > A -> it = item_get(key, nkey) > (atomically increments the refcount for that item, returns a reference > to it) > B -> same, same time. > (same) > > A -> out_string(c, add_delta(it, incr, delta, temp)); > add_delta runs atomically, copies the result of the addition into the > thread local 'temp' buffer and _returns the 'temp' buffer_ (which > contains 2) > B -> out_string(c, add_delta(it, incr, delta, temp)); > Gets serialized behind A, and its 'temp' then holds a value one higher > than A's (containing 3)
Here I am confused. Every thread has a local var 'temp' and here 'temp' should hold 2. 'temp' is independent, and doesn't share between threads. So thread B should overwrite the value in the slabber. Am I right? > A -> runs out_string(c, temp), with 'temp' having the atomically > incremented value. > A -> inside out_string, copy's the contents of the original 'temp' > buffer into the connection's local write buffer, then sets the > connection into write mode (which will flush its buffer before doing > further processing). Then returns. > A -> returns to the state machine, 'temp' goes to the wolves, etc. > A -> sends value '2' to its client. > > B -> Same thing. Client should receive a '3'. > > Apologies to the original patch author and the list for the confusion :) > I had mentally confused "normal" responses and "get" responses, which > operate differently. > > -Dormando > > > > >> It's possible that with two threads (A, B): > >> > >> X -> set "foo" 1 > >> A -> incr "foo" by 1 > >> B -> incr "foo" by 1 > >> > >> A -> returns 3 > >> B -> returns 3 > >> > >> The only guarantee the slabber makes for returning values, is that they > >> won't get deleted before being transferred through the network. > >> > >> Could be wrong, but that's my impression from checking the sources. > >> > >> -Dormando > >> > >> > >> > >> Steve Chu wrote: > >> > In 'process_arithmetic_command' function: > >> > We first do item_get from slabs and then do add_delta to incr/decr the > value. > >> > > >> > My question is: > >> > Is this atomic in multithread mode? Item_get is atomic and so is > >> > add_delta because they are protected by mutex. But the entire two > >> > operations seems NOT atomic. Two threads can both do item_get with > >> > same key, then both incr it, and write back. > >> > > >> > Anybody can tell me whether it is a bug or not? > >> > > >> > Regards, > >> > > >> > Steve Chu > >> > >> > > > > -- Steve Chu http://stvchu.org
