Is there a reason why we just don't add Runnable and Callable<V> to the JRE
emul and use those instead of Command? This design seems to parallel some of
the patterns in ExecutorService. I could see some of those patterns being
useful (like completion queues, which would be useful for staged
animations).
-Ray


On Thu, Sep 3, 2009 at 7:08 PM, Bruce Johnson <br...@google.com> wrote:

> 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 <br...@google.com> 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 <j...@google.com> 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 <sco...@google.com> wrote:
>>>
>>>> ++Ray.
>>>>
>>>>
>>>> On Thu, Sep 3, 2009 at 4:38 PM, Ray Ryan <rj...@google.com> 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 
>>>>> <cromwell...@gmail.com>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 <br...@google.com>wrote:
>>>>>>
>>>>>>>  On Wed, Sep 2, 2009 at 6:07 PM, Scott Blum <sco...@google.com>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
-~----------~----~----~----~------~----~------~--~---

Reply via email to