Okay, here's a strawman for a new-and-improved proposal. All these would be
in core.
// "Deferred command" = on the other side of the event loop
interface DeferredCommands {
public static DeferredCommands get();
public void add(Command cmd);
public void add(Command cmd, boolean asap); // asap = faster than
setTimeout(0)
public void addPause();
}
// "Finally command" = before you end the current stack trace
interface FinallyCommands {
public static FinallyCommands get();
public void add(Command cmd);
}
// "Incremental command" = call repeatedly quickly to avoid SSWs
interface IncrementalCommands {
public static IncrementalCommands get();
public void add(Command cmd);
public void add(Command cmd, boolean asap);
}
// "Timed command" = call based clock time (aka regular old timers)
interface TimedCommands {
public static TimedCommand get();
public TimerController scheduleOnce(Command cmd, int millis);
public TimerController scheduleRecurring(Command cmd, int millis);
}
// Allows optional control over a timer after it's created.
// If the return values in scheduleOnce, etc. aren't used, extra code can
maybe optimize away.
interface TimerController {
public void pause();
public void resume();
public void cancel();
}
I think that maybe consolidating timers into this mix might be a bit much,
but, then again, if we're graduating "Command" to core, then it seems like
it would be nice to make it the uniform callback interface.
-- Bruce
On Thu, Sep 3, 2009 at 9:28 PM, Bruce Johnson <[email protected]> wrote:
> I like it a lot Ray. (To be completely honest, I knew you were going to say
> all that, so I decided to sandbag and let you do the typing :-)
>
> I question if it's really appropriate to explicitly say "PreEventLoop" and
> "PostEventLoop" considering that...sometimes...the event loop can actually
> run re-entrantly. Those names sound like a very strong guarantee that I
> don't think we can reliably guarantee. It's more like
> "PreCurrentJavaScriptStackFullyUnwinding" and "PostEventLoop".
>
> Actually, to take a step back (which is my very favorite thing to do),
> there are several kinds of things that could be consolidated:
>
> 1) Single-shot timers
> 2) Recurring timers
> 3) Incremental commands that run as soon as possible after the event loop
> (faster than setTimeout(0))
> 4) Incremental commands that run after the event loop via setTimeout(0)
> 5) Deferred commands that run as soon as possible after the event loop
> (faster than setTimeout(0))
> 6) Deferred commands that run after the event loop via setTimeout(0)
> 7) Execute-this-before-you-unwind-the-JS-stack-in-which-it-was-enqueued
> (aka BatchedCommand)
> 8) Arguably, runAsync (although it's purpose is so functionally different
> it would probalby be a mistake to munge it in)
>
> #3 and #5 might look funny, but it is generally possible to run code
> *after* the event loop but *much* sooner than setTimeout(0), which is
> usually clamped to some pretty long duration such as 10ms. The reason you
> wouldn't want to do #3 and #5 as the default for deferred commands is that
> it would keep the CPU overly busy if you did it a bunch in a row. It would
> very likely drain mobile batteries quickly, even.
>
> @Ray (or anyone): Can you think of an awesome way to reconcile those behind
> a consistent API?
>
>
>
>
>
>
>
> On Thu, Sep 3, 2009 at 4:52 PM, Joel Webber <[email protected]> wrote:
>
>> ++(++Ray)
>> Anything we can do to sensibly get this crap out of .user and into .core
>> (or some other common location) would be very, very good.
>> If, as a side-effect, we could get DeferredCommand to *not* use
>> IncrementalCommand (the latter brings in fairly significant dependencies
>> that are enough to matter for small apps), that would be even better.
>>
>>
>> On Thu, Sep 3, 2009 at 4:46 PM, Scott Blum <[email protected]> wrote:
>>
>>> ++Ray.
>>>
>>>
>>> On Thu, Sep 3, 2009 at 4:38 PM, Ray Ryan <[email protected]> wrote:
>>>
>>>> The mechanism is just brilliant. I have reservations about the api.
>>>>
>>>> <bikeshed>
>>>> "it seemed kinda nice to have one less type"
>>>>
>>>> Except that we have one more type, BatchedCommand, which looks exactly
>>>> like Command, except with a different name, and you have to subclass it
>>>> rather than implement it...
>>>>
>>>> A simple thing we could do is:
>>>>
>>>> - create com.google.gwt.core.client,
>>>> - change com.google.gwt.user.client.Command to extend the new one
>>>> - deprecate com.google.gwt.user.client.Command
>>>> - And have BatchedCommand accept com.google.gwt.core.client
>>>>
>>>> And the two names, "DeferredComand" and "BatchedCommand", don't give
>>>> much clue as to which does what. And of course BatchedCommand doesn't
>>>> actually provide any batching service.
>>>>
>>>> If we were doing all this from scratch, I suspect we would wind up with
>>>> something like this in core (presuming we're happy with IncrementalCommand
>>>> and addPause):
>>>>
>>>> package com.google.gwt.core.dispatch
>>>>
>>>> public interface Command {
>>>> void execute();
>>>> }
>>>>
>>>> public interface IncrementalCommand {
>>>> boolean execute();
>>>> }
>>>>
>>>> public class PreEventLoopDispatcher {
>>>> public static PreEventLoopDispatcher get(); { ... }
>>>>
>>>> public void addCommand(Command c);
>>>> }
>>>>
>>>> public class PostEventLoopDispatcher {
>>>> public static PostEventLoopDispatcher get(); { ... }
>>>>
>>>> public void addCommand(Command c);
>>>> public void addCommand(IncrementalCommand c);
>>>> public void addPause();
>>>> }
>>>>
>>>> Note the avoidance of statics to make commands more testable, a
>>>> recurring subject.
>>>>
>>>> Seems like we could do this, deprecate the existing classes, and make
>>>> them wrappers around the new.
>>>>
>>>> </bikeshed>
>>>>
>>>> On Wed, Sep 2, 2009 at 11:36 PM, Ray Cromwell <[email protected]>wrote:
>>>>
>>>>>
>>>>> Could this also be used as a general pattern to batch DOM updates from
>>>>> multiple Widgets performing updates? e.g. a current approach to avoid the
>>>>> overhead, of say, installing a dozen widgets, is to concatenate all the
>>>>> HTML
>>>>> together, slam it into innerHTML, and then wrap the widgets around the
>>>>> HTML.
>>>>> But this rather breaks the nice OO design people are used to with widgets.
>>>>> Templating is an alternative, but I'm wondering, why can't we make all of
>>>>> the attachment stuff happen via a batch queue. A special optimizer on the
>>>>> queue could even recognize instances of when DOM updates can be coalesced
>>>>> and leverage documentFragment or innerHTML.
>>>>> e.g.
>>>>>
>>>>> VerticalPanel vp = ...
>>>>> vp.add(new Label())
>>>>> vp.add(new Label())
>>>>>
>>>>> The objects are constructed, but the HTML mutations are
>>>>> deferred/queued. When adding a DOM mutation to the queue, you could check
>>>>> if
>>>>> existing queue data isOrHasChild the new DOM mutation element, and if so,
>>>>> just modify the queue element (coalesce) rather than appending another
>>>>> queue
>>>>> item. Then, when processing the queue, you only need to add the roots to
>>>>> the
>>>>> DOM, attaching/modifying enmasse.
>>>>>
>>>>> This would preserve the OO-ness of constructing widget hierarchies
>>>>> without requiring 'foreign' string-based templating.
>>>>>
>>>>> -Ray
>>>>>
>>>>>
>>>>> On Wed, Sep 2, 2009 at 5:13 PM, Bruce Johnson <[email protected]>wrote:
>>>>>
>>>>>> On Wed, Sep 2, 2009 at 6:07 PM, Scott Blum <[email protected]>wrote:
>>>>>>
>>>>>>> I do agree with John that we should really discuss how this can be
>>>>>>> implemented.
>>>>>>
>>>>>>
>>>>>> It's already implemented!
>>>>>>
>>>>>>
>>>>>>> Is there some magic trick to make the browser execute a piece of
>>>>>>> code at the time you want, or do we need to go and modify all our event
>>>>>>> code
>>>>>>> (like with the global uncaught exception handler)?
>>>>>>
>>>>>>
>>>>>> No trick, it's as bad as you'd hope it wasn't. On the positive side,
>>>>>> it's already been done -- I'm just augmenting the tests for the various
>>>>>> subsystems such as RequestBuilder and event dispatching to make sure we
>>>>>> tighten the correctness noose as much as possible.
>>>>>>
>>>>>> Longer term, Bob and I both would really like to find a general
>>>>>> mechanism for making this pattern easy to do from any path into a GWT
>>>>>> module
>>>>>> from "the outside", exactly along the lines of what Matt was talking
>>>>>> about.
>>>>>> I think rolling this functionality into gwt-exporter (and then rolling
>>>>>> that
>>>>>> sort of functionality directly into GWT proper) will get us pretty far
>>>>>> down
>>>>>> the road.
>>>>>>
>>>>>> Code review request forthcoming, possibly tomorrow.
>>>>>>
>>>>>> -- Bruce
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>
>> >>
>>
>
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---