Revision: 7664
Author: b...@google.com
Date: Thu Mar 4 07:49:01 2010
Log: Created wiki page through web user interface.
http://code.google.com/p/google-web-toolkit/source/detail?r=7664
Added:
/wiki/SoftPermutations.wiki
=======================================
--- /dev/null
+++ /wiki/SoftPermutations.wiki Thu Mar 4 07:49:01 2010
@@ -0,0 +1,69 @@
+#summary Runtime rebind evaluation (draft)
+
+= Introduction =
+
+Deferred-binding type replacement always requires a separate hard
permutation. This contributes to permutation explosion. One technique for
[ControllingPermutationExplosion controlling permutation explosion] is to
allow certain rebind decisions to be evaluated at runtime thereby
collapsing two or more hard permutations together.
+
+= Details =
+
+To address the common use-case of rendering-engine variants where using
deferred-binding:
+{{{
+<!-- Define an adjunct property -->
+<define-property name="webkitVariant" values="none, safari, chrome,
android, iphone" />
+<!-- Collapse all of its values -->
+<collapse-property name="webkitVariant" values="*" />
+<!-- Additional property provider to distinguish Chrome from Safari,
etc... -->
+<property-provider name="webkitVariant">...</property-provider>
+
+<!-- Default value -->
+<set-property name="webkitVariant" value="none">
+ <none>
+ <when-property-is name="user.agent" value="safari" />
+ </none>
+</set-property>
+
+<!-- Regular rebind rules -->
+<replace-with name="com.google.ServiceImplAndroid">
+ <when-property-is name="webkitVariant" value="android" />
+ <when-type-is name="com.google.Service" />
+</replace-with>
+
+<!-- Generators are fine as well -->
+<generate-with name="com.google.ChromeServiceGenerator">
+ <when-property-is name="webkitVariant" value="chrome" />
+ <when-type-is name="com.google.Service" />
+</generate-with>
+}}}
+
+Instead of adding an extra `5 * N` factor to the number of hard
permutations where `GWT.create(Service.class)` would be replaced with a
`new ServiceImpl()`, the `GWT.create()` call is replaced with a call to a
factory method, whose implementation looks like:
+
+{{{
+public static Object com_google_Service() {
+ switch (CollapsedPropertyHolder.permutationId$) {
+ case 0:
+ return new ServiceImplAndroid();
+ case 1:
+ return new ServiceImplChrome();
+ }
+ return new ServiceImplSafari();
+}
+}}}
+
+Even though there is a runtime aspect to the construction of a new
`ServiceImpl` type, the virtual-permutation-specific method dispatch uses
standard polymorphic dispatch to the implementation object and is subject
to normal compiler optimizations. This continues to recommend the pattern
of assigning the implementation type to a static, final field, e.g.
`private static final Service = GWT.create(Service.class)`.
+
+= Virtual permutation id =
+
+The virtual permutation id is determined on module startup by examining
the values returned by the deferred-biding property providers. Every value
is assigned an arbitrary ordinal value. These ordinal values are then
combined in a manner similar to computing an element memory offset in a
multi-dimension array of known size. Given the following module definition
snippet:
+{{{
+<collapse-property name="user.agent" value="safari, ie8" />
+<collapse-property name="locale" value="en_US, en_GB, en_AU" />
+<collapse-property name="foo" value="bar, baz" />
+}}}
+The virtual permutation would be computed as:
+{{{
+int user_agent = "safari".equals(user_agent_value) ?
1 : "ie8".equals(user_agent_value) ? 0 : die();
+int locale = "en_AU".equals(locale_value) ?
2 : "en_US".equals(locale_value) ? 1 : "en_GB".equals(locale_value) ? 0 :
die();
+int foo = "bar".equals(foo_value) ? 1 : "baz".equals(foo_value) ? 0 :
die();
+permutationId$ = user_agent * 1 + locale * 2 + foo * 6;
+}}}
+The multiplier sequence is [1], [user.agent], [user.agent + locale].
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors