W3C home > Mailing lists > Public > public-webapps@w3.org > January to March 2011

Re: [chromium-html5] LocalStorage inside Worker

From: Felix Halim <felix.halim@gmail.com>
Date: Fri, 7 Jan 2011 11:37:10 +0800
Message-ID: <AANLkTikJGjDN2U7j4dELnX9=9xFPKv2MOwtHoK8gLy31@mail.gmail.com>
To: Jonas Sicking <jonas@sicking.cc>
Cc: Jeremy Orlow <jorlow@chromium.org>, public-webapps WG <public-webapps@w3.org>
On Fri, Jan 7, 2011 at 6:11 AM, Jonas Sicking <jonas@sicking.cc> wrote:
>> On Sat, Jan 1, 2011 at 4:22 AM, Felix Halim <felix.halim@gmail.com> wrote:
>>> 5: Why not make localStorage accessible from the Workers as "read only" ?
>
> Unfortunately this is not possible. Since localStorage is
> synchronously accessed, if we allowed workers to access it that would
> mean that we no longer have a shared-nothing-message-passing threading
> model. Instead we'd have a shared memory threading model which would
> require locks, mutexes, etc.

What I was suggesting as "read only" is like a "snapshot". So, when
the main html page spawn a worker, a (consistent) snapshot of the
localStorage is build at that point of time and passed on to the
worker. This is the same as creating a worker and sending the first
message to it (which is the localStorage content, but the difference
is the snapshot can be more efficient for the main page thread I
believe).

Now, any changes to the localStorage, will NOT get changed inside any
worker. The only way for the workers to get an updated value of the
localStorage is to listen to the events emitted by the localStorage
object, like:

// inside a worker
localStorage.on('update', function(key,value){
  // key is the key which value has changed since the last event (or
the first snapshot)
  // value is the new value
});

I think, this way is OK if you are intending to get the latest value
of the localStorage.

I think for most use cases, people access localStorage inside workers
just because the data is already in the localStorage (like many
settings and preferences set earlier on the main page). The pure data
that changing, are sent via message passing instead.

So, I'm talking about immutable localStorage inside worker (and
ability to listen if you will).



> Making it readonly unfortunately doesn't help. Consider worker code like:
>
> var x = 0;
> if (localStorage.foo < 10) {
>  x += localStorage.foo;
> }
>
> would you expect x ever being something other than 0 or 1?

The localStorage.foo value will never change since the creation of
this worker and will always be consistent with other attributes of
localStorage (as it is a consistent snapshot).


> That said. As I have suggested before (don't remember if it was here
> or on the whatwg list), if we create a new version of localStorage,
> where you can only get a reference to the localStorage object
> asynchronously, then we should be fine. So something like:
>
> var s;
> getBetterStorage(function(storage) {
>  storage.foo += storage.bar;
>  storage.baz = "hello world";
>  storage.text = "she sells sea schells by the sea shore";
>  s = storage;
>  setTimeout("runlater", 10);
> });

Allowing localStorage to be modified inside worker is not safe!

Consider this in the main page thread:

// I want to keep 'balance' a positive number
if (localStorage['balance'] > price){
    setTimeout( buy_the_item , 1000 ); // I believe calling setTimeout
releases the lock to the localStorage
}

function buy_the_item(){
   localStorage['balance'] -= price;
   // now localStorage['balance'] MAY BE NEGATIVE since it's possibly
modified by a worker just before entering this block
}


So, my proposal still stands, DO NOT MODIFY the value of localStorage
inside workers. The one and only thread that can alter localStorage
value is the MAIN page thread. The workers can only listen to
changes.If the workers really need to change localStorage value, it
must notify the MAIN page (out of bound) using message passing and let
the MAIN page deal with the changes. In the case above the main page
will get notified if some other worker wants to buy another item (but
only the main page can actually buy the item!).

Of couse the main page can also listen to the changes to the
localStorage when the 'balance' changes and updates accordingly, but I
think it's not a good way of communicating with workers (message
passing is the way).



> function runlater() {
>  s.foo = "bar"; // throws an exception
> }

Agree, changing values of the localStorage inside worker throws an exception.

> would work fine, both in workers and outside them. It would also
> remove the racyness that many localStorage implementations have since
> they don't implement the storage mutex.

In my proposal, listening to localStorage changes only needs eventual
consistency and can be very efficient.


Felix Halim
Received on Friday, 7 January 2011 08:03:27 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 18:49:42 GMT