This page documents rules (or at least guidelines) for creating and returning SCL lists from SCL methods (executing in the SAS server) to a Java client or other remote.
When using remote SAS server objects from a Java client, you may declare your methods in a remote interface using either
void method(input-arguments, ...);
or
returnType method(input-arguments, ...);
In SCL Version 6.12, SCL does not support returning values
from methods, so all SCL methods are effectively void
.
The convention for Java methods that have non-void return
types is that
the return value is the first parameter of the SCL
method. The return parameter is treated as an output parameter.
All other method parameters are input only.
label: method return-parameter 8 input-parameters...; ... endmethod;
SCL methods "return" a value by assigning to the first parameter.
SCL lists are passed as numeric parameters. The data types allowed are basically numbers (doubles), Strings, and HListInterface.
Thus, an SCL method may create and return an SCL list to the Java caller:
Java interface:
public interface SCLListsInterface { HListInterface newList(double size);
and the SCL implementation:
newList: method result 8 size 8; result = makelist(size); endmethod;
The problem with this simple implementation is that on each call to the newList method, a new SCL list is created and never deleted.
An HListInterface in the Java client corresponds to an SCL list in the SAS server running SCL. However, whereas Java does automatic memory management (such as garbage collection), there is no garbage collection in SCL. Lists cannot be freely created whenever requested by a remote Java client. The SCL class must manage the lists it creates, and delete lists no longer in use.
Here are some guidelines:
SAS-Marshaling subsystem: read SAS/Connect packet create lists to call method call SCL method write return packet delete all lists created here with no recursive deletes
MODEL.SCL /* SAMPLE METHOD */ /* GET DATA */ /* outlist = remoteobject.getdata(start,end); */ getdata: method out_datavec 8 in_startobs 8 in_endobs 8; /* start every method */ link MakeGlocalList; /* set return handle to the list */ out_datavec = reuselist; do i = in_startobs to in_endobs; rc = insert... end; endmethod; /* overridden _TERM_ method */ subterm: link GarbageCollector; call super(_self_,_method_); endmethod; /* MAKEGLOBALLIST: create a 'remembered' list handle */ MakeGlobalList: link GarbageCollector; reuselist = makelist(); return; /* GARBAGECOLLECTOR: clean up */ GarbageCollector: /* free any lists from last call, "reuselist" is an instance attr */ if reuselist > 0 then do; rc = dellist(reuselist,'Y'); reuselist=0; end; return;
VIEWER.SCL call SEND(model,'getNewPosition',pos); xCoordinate = getNitem(pos,1); yCoordinate = getNitem(pos,2); call SEND(model,'getNewSize',sz); mysz = copylist(sz,'Y'); ... /* much later */ width = getNitem(mysz,1); height = getNitem(mysz,2); rc = dellist(mysz,'Y');
MODEL.SCL getstuff: method out 8 parm1 $ parm2 $; /* free any lists from the last call */ if reuselist > 0 then do; reuselist = dellist(reuselist,'Y'); reuselist = 0; end; /* if the user gave us a list use it and do not create a * tagged list */ if out < 1 then do; reuselist = makelist(); out = reuselist; end; rc = insert(out,... VIEW.SCL mylist = makelist(); Call SEND(model,'getStuff',mylist,'Neat','Stuff');
Using the above rules there are two significant benefits:
The HListInterface defines a print method, and the HList class (the implementation of HListInterface) implements the print method, but this method prints with no line breaks, so the output is somewhat hard to decipher. Below is a Java method for printing a list to a PrintWriter such as System.out:
public static void print(PrintWriter out, HListInterface l) { for(int i=0;i<l.count();i++) { HListItem child = l.getItem(i); String childName = l.getName(i); if(child instanceof ListItem) { HListInterface childList = l.getList(i); out.println("Walking child list:" + childList); print(out, childList); } else if(child instanceof StringItem) { String childString = l.getString(i); out.println("String child=" + childString); } else if(child instanceof DoubleItem) { double childDouble = l.getDouble(i); out.println("Double child=" + childDouble); } } }