- From: Darin Fisher <darin@chromium.org>
- Date: Fri, 2 Oct 2009 21:58:33 -0700
On Fri, Oct 2, 2009 at 9:43 PM, Jonas Sicking <jonas at sicking.cc> wrote: > >> >> > Moreover, there are other examples which have been discussed on >>>>> the >>>>> >> >> > list. There are some DOM operations that can result in a frame >>>>> >> >> > receiving >>>>> >> >> > a DOM event synchronously. That can result in a nesting of >>>>> storage >>>>> >> >> > locks, >>>>> >> >> > which can force us to have to implicitly unlock the outermost >>>>> lock to >>>>> >> >> > avoid >>>>> >> >> > deadlocks. Again, the programmer will have very poor >>>>> visibility into >>>>> >> >> > when >>>>> >> >> > these things can happen. >>>>> >> >> >>>>> >> >> So far I don't think it has been shown that these events need to >>>>> be >>>>> >> >> synchronous. They all appear to be asynchronous in gecko, and in >>>>> the >>>>> >> >> case of different-origin frames, I'm not even sure there's a way >>>>> for >>>>> >> >> pages to detect if the event was fired asynchronously or not. >>>>> >> > >>>>> >> > IE and WebKit dispatch some of them synchronously. It's hard to >>>>> say >>>>> >> > which >>>>> >> > is correct or if it causes any web compat isues. I'm also not >>>>> sure that >>>>> >> > we >>>>> >> > have covered all of the cases. >>>>> >> >>>>> >> It still seems to me that it's extremely unlikely that pages depend >>>>> on >>>>> >> cross origin events to fire synchronously. I can't even think of a >>>>> way >>>>> >> to test if a browser dispatches these events synchronously or not. >>>>> Can >>>>> >> you? >>>>> > >>>>> > i agree that it seems uncommon. maybe there could be some odd app >>>>> that >>>>> > does something after resizing an iframe that could be dependent on >>>>> the >>>>> > event handler setting some data field. this kind of thing is >>>>> probably even >>>>> > less common in the cross-origin case. >>>>> >>>>> But how would you read that data field in the cross-origin frame? I >>>>> think it might be possible, but extremely hard. >>>>> >>>>> >>>> Yeah. >>>> >>>> My concern is simply that I cannot prove that I don't have to worry >>>> about this >>>> problem. Future web APIs might also inadvertently make matters worse. >>>> >>> >>> I agree it's not ideal, but at the same time I don't think that not >>> allowing synchronous cross-origin APIs is a huge burden. You campaigned >>> heavily against that when we were designing postMessage for wholly other >>> reasons. I would imagine those reasons will hole true no matter what. >>> >> >> Agreed. That's a good point. In that case, I was concerned about stack >> depth. The same issue might apply here. Hmm... >> > > As far as I can see it does. > > > >> >> ...snip... >> >>> >>>>> >> >> Not quite sure I follow your proposal. How would you for example >>>>> >> >> increase the value of a property by one without risking race >>>>> >> >> conditions? Or keep two values in different properties in sync? >>>>> I.e. >>>>> >> >> so that if you update one always update the other, so that they >>>>> never >>>>> >> >> have different values. >>>>> >> >> >>>>> >> >> / Jonas >>>>> >> > >>>>> >> > >>>>> >> > Easy. Just like with database, the transaction is the storage >>>>> lock. >>>>> >> > Any >>>>> >> > storage >>>>> >> > operation performed on that transaction are done atomically. >>>>> However, >>>>> >> > all >>>>> >> > storage >>>>> >> > operations are asynchronous. You basically string together >>>>> asynchronous >>>>> >> > storage >>>>> >> > operations by using the same transaction for each. >>>>> >> > We could add methods to get/set multiple items at once to simplify >>>>> life >>>>> >> > for >>>>> >> > the coder. >>>>> >> >>>>> >> I think I still don't understand your proposal, could you give some >>>>> >> code examples? >>>>> >> >>>>> > >>>>> > >>>>> > ripping off database: >>>>> > interface ValueStorage { >>>>> > void transaction(in DOMString namespace, in >>>>> > ValueStorageTransactionCallback callback); >>>>> > }; >>>>> > interface ValueStorageTransactionCallback { >>>>> > void handleEvent(in ValueStorageTransaction transaction); >>>>> > }; >>>>> > interface ValueStorageTransaction { >>>>> > void readValue(in DOMString name, in ValueStorageReadCallback >>>>> callback); >>>>> > void writeValue(in DOMString name, in DOMString value); >>>>> > }; >>>>> > interface ValueStorageReadCallback { >>>>> > void handleEvent(in ValueStorageTransaction transaction, in >>>>> DOMString >>>>> > value); >>>>> > }; >>>>> > then, to use these interfaces, you could implement thread-safe >>>>> increment: >>>>> > window.localStorage.transaction("slice", function(transaction) { >>>>> > transaction.readValue("foo", function(transaction, fooValue) { >>>>> > transaction.writeValue("foo", ++fooValue); >>>>> > }) >>>>> > }) >>>>> > to fetch multiple values, you could do this: >>>>> > var values = []; >>>>> > var numValues = 10; >>>>> > function readNextValue(transaction) { >>>>> > if (values.length == numValues) >>>>> > return; // done! >>>>> > var index = values.length; >>>>> > transaction.readValue("value" + index, function(transaction, value) >>>>> { >>>>> > values.push(value); >>>>> > readNextValue(transaction); >>>>> > }) >>>>> > } >>>>> > window.localStorage.transaction("slice", readNextValue); >>>>> > This has the property that all IO is non-blocking and the "lock" is >>>>> held >>>>> > only >>>>> > for a very limited scope. The programmer is however free to extend >>>>> the >>>>> > life of the lock as needed. >>>>> >>>>> What do you mean by that the "lock" is held for only a very limited >>>>> scope? You still want to prevent modifications for as long as the >>>>> transaction is being used right? I.e. no modifications can happen >>>>> between the read and the write in the first example, and between the >>>>> different reads in the second. >>>>> >>>> >>>> Yes. I only meant that the programmer doesn't have to call a special >>>> function to close the transaction. It closes by virtue of the last >>>> handleEvent >>>> call referring to the transaction returning. >>>> >>> >>> So wouldn't you implement this transaction using a lock? To prevent other >>> pages from accessing the localStorage? >>> >>> >> Yes, but it wouldn't need to be a normal mutex if that's what you mean. >> You could just defer callbacks until the transaction completes. It is >> purely asynchronous locking. >> > > So how is that then different from from using a Storage API, but only > letting you get a reference to the Storage object using a asynchronous API? > And of course not allowing the Storage object to be stored in a variable and > used outside the callback. > > The difference is that storage IO is fully asynchronous in the API I proposed. It doesn't have to block the calling thread for reads. I think that is important. We should never design any APIs that involve synchronous IO (filesystem or network) from the main UI thread. -Darin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20091002/a2d3764a/attachment.htm>
Received on Friday, 2 October 2009 21:58:33 UTC