Leistungen

Details of the JLayer Framework

The JLayer framework is an open-source implementation hosted on GitHub, its Javadoc can be found here. Here we present the technical details using an (artificial) example.


The JLayer Annotations

The JLayer framework includes four annotations, all of which are used in the following unit class example.

  @LayerUnit
  class Unit {
	@LayerField
	Type x;
	
	@LayerField
	Unit[] v;
	
	@LayerField
	Type[] w;
	
	@LayerMethod
	Type f(Type p){…};
		
	@LayerMethod
	Type g(@LayerParam Type p){…};
  }
  

The JLayer Annotation Processor

As class Unit is marked by the annotation @LayerUnit, its compilation leads to the generation of class Layer_Unit_.

  class Layer_Unit_ … {
    …
    // field items 
    Layer<Unit,Type> x;
    VectorLayer<Unit,Unit> v;
    VectorLayer<Unit,Type> w;
    …
    // method items 
    BasedLayer<Type> f(Type p) …;
    BasedLayer<Type> g(Layer<?,Type> p) …;
    …
  }
  

This class contains the identifiers of all fields marked with @LayerField and all methods marked with @LayerMethod, with their declarations chosen so that arrays with object elements of type Unit can be wrapped in the desired way.

  …
  // declaring arrays
  Unit a1[];
  Unit a2[][];
  …
  // the arrays have to be created and initialized
  …
  // then they can be wrapped
  Layer_Unit_ wa1 = new Layer_Unit_(a1);
  Layer_Unit_ wa2 = new Layer_Unit_(a2);

Field Layers, Method Layers and Based Layers

At this point, the "lifted dot notation" can be used to access the so called layers.

  • wa1.x, wa1.v, wa1.w, wa2.x, wa2.v, wa2.w are called field layers
  • wa1.f(), wa1.g(), wa2.f(), wa2.g() are called method layers
  • wa1.x, wa1.v, wa1.w, wa1.f(), wa1.g() are one-dimensional layers
  • wa2.x, wa2.v, wa2.w, wa2.f(), wa2.g() are two-dimensional layers
  • wa1.x and wa2.x have element type Type
  • wa1.v and wa2.v have element type Unit[] and are also called vector layers
  • wa1.w and wa2.w have element type Type[] and are also called vector layers

The wrapped arrays wa1 and wa2 can somehow be identified with the arrays a1 and a2, respectively. However, they are also of a layer type that we call based layer. In contrast to a field layer, a based layer represents not just a "slice" of an array, but an entire array.


Linking Field Layers and Based Layers

For linking objects the JLayer framework uses mathematical relations over indices to specify the desired topologies. These relations must correspond to the following interface.

  interface Relation {
	boolean contains(int[] ix, int[] iy);
  }
  

To collect the chosen references, vector fields are used. More precisely, for the actual linking process the generic Type VectorLayer<U,T>, provides two methods.

  interface VectorLayer<U,T> … {
    // connecting layers
    void connect(Layer<?,T> layer, Relation rel);
	
    // associating vector layers
    void associate(VectorLayer<?,T> layer, Relation rel);
  }
  

Three examples are used to illustrate how these methods work. In all examples, rel is an arbitrary relation.

Connecting vector layers with based layers

  wa1.v.connect(wa2, rel);
  

After executing connect(), the following sentence applies:

  • vector a1[i].v contains a reference to object a2[j][k]
    ⇔ the index pair ([i],[j][k]) belongs to relation rel.

Connecting vector layers with field layers

  wa1.w.connect(wa2.x, rel);
  

Here, the following applies after the execution:

  • vector a1[i].w contains a reference to object a2[j][k].x
    ⇔ the index pair ([i],[j][k]) belongs to relation rel.

Associating vector layers with each other

  wa1.w.associate(wa2.w, rel);
  

Linking the two reference vectors here means linking them by an object of type Type, which is being created on this occasion, so that after the execution of associate() the following applies:

  • vectors a1[i].w and a2[j][k].w contain a reference to the same object of type T
    ⇔ the index pair ([i],[j][k]) belongs to relation rel.

Invoking Method Layers

To illustrate the invocation of method layers, we have to differentiate between two cases, which depend on whether the underlying annotated method has a parameter annotated itself - with @LayerParam - or not. In the example given above these cases are represented by methods f() or g(), respectively.


Parameters without annotation

Method f() represents the case that the method layer takes over the parameter list of the underlying method as it is. However, if a method like f(), returns a value, the corresponding method layer returns an array (or layer) of values:

  Type p0;				// the parameter
  p0 = …;				// setting the parameter
  BasedLayer<Type> ra1;			// based layer for return values
  ra1 = wa1.f(p0);			// invocation of the method layer
  

Note, that the dimensionality of the returned based layer ra1 is one, as it corresponds to the dimensionality of the method layer wa1.f().


The effect of annotation @LayerParam

The method g() has a parameter annotated with @LayerParam. An appropriately wrapped array (or parameter layer) must therefore be passed to the method layer as a parameter:

  Type[][] par2;			// the parameter array
  …					// setting the parameter array
  BasedLayer<Type> wpar2;
  wpar2 = new LayerBase<Type>(par2);	// wrapping the parameter array
  …
  BasedLayer<Type> ra2;			// based layer for return values
  ra2 = wa2.g(wpar2);			// invocation of the method layer
  

Here, the dimensionality of the returned based layer ra2 is two, as it corresponds to the dimensionality of the method layer wa2.g().


Parallel implementation

The annotation @LayerMethod is equipped with a parameter runtimeMode being of enum type RuntimeMode:

  public enum RuntimeMode {
	LOOP, FORKJOIN
  }
  

The default value is RuntimeMode.LOOP and causes the method layer to be executed in a loop. If you want to have the parallel implementation, you have to set the runtimeMode accordingly:

  @LayerMethod(runtimeMode=RuntimeMode.FORKJOIN)
  Type f(Type p){…};
  

Now the methods are executed in parallel, where the implementation is based on the Java Fork/Join Framework, which provides tools to help speed up parallel processing by attempting to use all available processor cores. Essentially, the standard loop is broken into a number of "partial loops" according to the number of available cores.


Final Remarks

  • A unit class must be a top-level class or a static member immediately nested in a top-level unit class, i.e. all other classes marked by the annotation @LayerUnit are ignored by the JLayer annotation processor.
  • The generated wrapper classes have constructors only for one-, two-, or three-dimensional arrays.
  • The elements of field layers may have any type. However, vector layers, i.e. field layers with element type T[] can only be linked, if the underlying type T is a class type with a parameterless constructor. Only in that case they are equipped with methods connect() and associate().
  • The @LayerField annotation has an isIndex parameter of type boolean, with a default value of false. If the value is true and the field item is of type int[], then the corresponding field layers are automatically indexed, when wrapping an appropiate object array.