dev@grizzly.java.net

Re: [Fwd: [Issue 53] AttributeHolder needs maps with parameterized types <T>]

From: Ken Cavanaugh <Ken.Cavanaugh_at_Sun.COM>
Date: Fri, 15 Feb 2008 20:19:05 -0800
Harsha Godugu wrote:
Jeanfrancois Arcand wrote:
Hi Harsha,

Hi Jeanfrancois,

Harsha Godugu wrote:
Jeanfrancois Arcand wrote:
Hi Alexey,

Oleksiy Stashok wrote:
Hi,

IMHO this bug should be closed.
Don't think we really need this extension to apply to our AttributeHolder implementation.
As attributes are used both inside Grizzly framework and outside, by developers, it's difficult to make any assumptions about possible parameter types.

What do you think?

I agree :-)

-- Jeanfrancoid
I disagree   :-(

Reason.. think about a generic use-case of Collections (since you are using a Map..)  in the places where we /Grizzly is using  Keys .. for example, in SlectorHandler, Collector,

Collector :-)
oops.. I meant to say Controller .. (out of subject /context... all these terms are going in a rhyme like.. controller, selector, collection, handler... with a great difference in meaning!)

 Context...   What would be the
BEST to describe an attribute in a collection, in the context of grizzly's Context, SelectorHandler, Controller?  does it really a String type?  Actually, the way Grizzly using the *term* attribute is not even appropriate. Why?   attribute is something that describes a specific distinguishable feature of the particular object (or instance).  The way grizzly uses here is, to store SOME objects and their references, in case it needs at various scopes.  This forces users to "create" their own strings?keys  (to accommodate in) to retrieve the  references.

Right. Might not be perfect, but a lot of API use that approach:

http://java.sun.com/j2se/1.4.2/docs/api/javax/net/ssl/SSLSession.html
http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContext.html
And all of them suffer a string hash lookup on every attribute access.  That is a String hash computation
and comparison, and these are expensive operations to perform (possibly multiple times) every time we
read bytes from a channel.

I have a similar problem in the codegen library.  Codegen generates a Java-like AST from method calls.
I have visitors for the AST that generate classfiles using ASM.  The general problem is that the AST
needs to have dynamic attributes added to it by a visitor so that another visitor can utilize that information.

I wanted a solution to this problem that is:
  1. Type safe
  2. The key names are actually checked at compile time
  3. It is extremely efficient: the basic cost should be essentially an ArrayList get call.
The interface is used as follows:

First, declare an attribute somewhere like this:

    public final static Attribute<MyLabel> statementStartLabel =
       new Attribute<MyLabel>( MyLabel.class, "statementStartLabel", makeLabel ) ;

Here makeLabel is a NullaryFunction<MyLabel> (that is, a

    interface NullaryFunction<T> {
        public T evaluate() ;
    }

    in the ORB's generic function library)

which returns a default value for the attribute when it is accessed for the first time and
does not have a previously set value.

This attribute then always takes or returns a MyLabel type, so it is type safe.

Accessing the label then looks like:

    MyLabel ssl = statementStartLabel.get( node ) ; // equivalent to ssl = node.statementStartLabel

    statementStartLabel.set( node, ssl ) ; // equivalent to node.statementStartLabel = ssl

where full type checking is enforced by the generic type.

You can view the code at the following location:

http://mercurial2.foundry.sun.com/corba/corba-master/file/245ec1acda14/orblib/src/share/classes/com/sun/corba/se/impl/orbutil/codegen

The relevant classes are:
This might be a consideration for Grizzly 2.0.  The basic implementation is fairly simple, and could be completed abstracted
from the rest of the codegen library fairly easily.  The delegation mechanism is not required, and neither are the
annotations controlling how codegen AST nodes are copied using the fast reflective object copier library.

The design tradeoff here is that there should only be a small number of unique attributes in the system, so that the
AttributedObject arraylists are not too large (say 10-30 attributes, not hundreds).  Many other designs are possible,
depending on exactly how a Map<Integer,Object> is implemented, with the assumption that the keys are small contiguously
allocated non-negative integers.  For example, segmented maps could be used, but then the lookup cost is higher.
Saving space costs time in this case.

Ken.