On Fri, Oct 2, 2009 at 9:58 PM, Darin Fisher <span dir="ltr"><<a href="mailto:darin@chromium.org">darin@chromium.org</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="gmail_quote"><div><div class="h5"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class="gmail_quote"><div><div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="gmail_quote"><div><div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class="gmail_quote"><div><div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="gmail_quote"><div><div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><div>
>> >> Not quite sure I follow your proposal. How would you for example<br>
>> >> increase the value of a property by one without risking race<br>
>> >> conditions? Or keep two values in different properties in sync? I.e.<br>
>> >> so that if you update one always update the other, so that they never<br>
>> >> have different values.<br>
>> >><br>
>> >> / Jonas<br>
>> ><br>
>> ><br>
>> > Easy. Just like with database, the transaction is the storage lock.<br>
>> > Any<br>
>> > storage<br>
>> > operation performed on that transaction are done atomically. However,<br>
>> > all<br>
>> > storage<br>
>> > operations are asynchronous. You basically string together asynchronous<br>
>> > storage<br>
>> > operations by using the same transaction for each.<br>
>> > We could add methods to get/set multiple items at once to simplify life<br>
>> > for<br>
>> > the coder.<br>
>><br>
>> I think I still don't understand your proposal, could you give some<br>
>> code examples?<br>
>><br>
><br>
><br>
> ripping off database:<br>
> interface ValueStorage {<br>
> void transaction(in DOMString namespace, in<br>
> ValueStorageTransactionCallback callback);<br>
> };<br>
> interface ValueStorageTransactionCallback {<br>
> void handleEvent(in ValueStorageTransaction transaction);<br>
> };<br>
> interface ValueStorageTransaction {<br>
> void readValue(in DOMString name, in ValueStorageReadCallback callback);<br>
> void writeValue(in DOMString name, in DOMString value);<br>
> };<br>
> interface ValueStorageReadCallback {<br>
> void handleEvent(in ValueStorageTransaction transaction, in DOMString<br>
> value);<br>
> };<br>
> then, to use these interfaces, you could implement thread-safe increment:<br>
> window.localStorage.transaction("slice", function(transaction) {<br>
> transaction.readValue("foo", function(transaction, fooValue) {<br>
> transaction.writeValue("foo", ++fooValue);<br>
> })<br>
> })<br>
> to fetch multiple values, you could do this:<br>
> var values = [];<br>
> var numValues = 10;<br>
> function readNextValue(transaction) {<br>
> if (values.length == numValues)<br>
> return; // done!<br>
> var index = values.length;<br>
> transaction.readValue("value" + index, function(transaction, value) {<br>
> values.push(value);<br>
> readNextValue(transaction);<br>
> })<br>
> }<br>
> window.localStorage.transaction("slice", readNextValue);<br>
> This has the property that all IO is non-blocking and the "lock" is held<br>
> only<br>
> for a very limited scope. The programmer is however free to extend the<br>
> life of the lock as needed.<br>
<br>
</div></div>What do you mean by that the "lock" is held for only a very limited<br>
scope? You still want to prevent modifications for as long as the<br>
transaction is being used right? I.e. no modifications can happen<br>
between the read and the write in the first example, and between the<br>
different reads in the second.<br></blockquote><div><br></div></div></div><div>Yes. I only meant that the programmer doesn't have to call a special</div><div>function to close the transaction. It closes by virtue of the last handleEvent</div>
<div>call referring to the transaction returning.</div></div></blockquote></div></div><div><br>So wouldn't you implement this transaction using a lock? To prevent other pages from accessing the localStorage?<br><br></div>
</div></blockquote><div><br></div></div></div><div>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.</div>
</div></blockquote></div></div><div><br>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.<br>
</div></div></blockquote><br></div></div><div>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.</div>
<div><br></div><div>We should never design any APIs that involve synchronous IO (filesystem or network) from the main UI thread.</div></div></blockquote><div><br>Ah, that's a different problem from what I thought you talked about initially.<br>
<br>I wasn't part of the initial design-phase of this API. But as I understand it, the idea was that it's expected that people will store small enough amounts of information in localStorage that the database can be kept in memory. Behind the scenes you can always write to disc asynchronously in order to reduce risk of dataloss in case of crash.<br>
<br>I'm not sure if this is practical or not. I suspect that many times it won't be. However even here a asynchronous getter would help since you can read in the full database into memory at that point.<br><br>/ Jonas<br>
</div></div>