- From: Felix Halim <felix.halim@gmail.com>
- Date: Fri, 7 Jan 2011 11:37:10 +0800
- 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 UTC