[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[aspectj-users] Using advice to wrap a call into a thread
|
I just started expliring AOP and i started rewriting an application of
mine and along the way checking
to see if there was anything i could make cleaner by using aspects. When
i finally got it to work I realized
all I need was a new SWT Display object, but the problem i ran into is
still intriguiging. In the first lines
of my existing code a splash screen is drawn. This splash screen has a
progress bar which is updated by
a simple timer. However getting it to run in the background, without a
new display object for it requires
the drawing code be in the main thread, the timer to be in a seperate
and the update of the progress bar
to be in a new thread syncing to display thread. I know that AOP is
rather useless in GUI programming
but it was more of an exercise than anything. I thought it would be neet
to just write the splash screen code
as if it was the only program running, causing all other execution to
stop until it was done, and then add
an aspect which would put it in the background. Code - bs as follows:
main program:
Display = new Display();
new SplashScreen();
while(true){
if(!Display.readAndDispatch())
Display.sleep();
}
splash screen:
Shell shell = new Shell(xtellirad2AOP.Display, SWT.NO_TRIM);
shell.pack();
shell.open();
//draw image
while(true){
try{
Thread.sleep(10);
//update progress bar
}catch(Exception e){}
}
then came my aspect, my solution was to create a new thread and run it
when new splashscreen was called, and
when any SWT constructor or method is called in splashscreen, a new
thread is created and Display.syncExex()'d
this is a mess, there has got to be a better way to do this. I know some
of my reflect code should be changed
to use argument types from the signature, but i realized a new Display()
would work much better before I got that
far and it would not help to illustrate my point, here is the aspect:
public aspect BackgroundThread {
class ConstructorRunner implements Runnable{
public Object output;
private Object[] arguments;
private Constructor constructor;
public ConstructorRunner(String signature, Object[] arguments){
this.arguments = arguments;
signature = signature.substring(0,signature.indexOf('('));
Class argumentTypes[] = new Class[arguments.length];
for(int i=0; i < arguments.length; i++){
argumentTypes[i] = arguments[i].getClass();
if(argumentTypes[i] == Integer.class)
argumentTypes[i] = int.class;
}
try{
Class shellDefinition = Class.forName(signature);
constructor = shellDefinition.getConstructor(argumentTypes);
}catch(Exception e){e.printStackTrace();}
}
public void run(){
try{
output = constructor.newInstance(arguments);
}catch(Exception e){e.printStackTrace();}
}
}
class MethodRunner implements Runnable{
private Object object;
private Method method;
private Object arguments[];
public Object output;
public MethodRunner(Object object, String signature, Object
arguments[]){
this.arguments = arguments;
this.object = object;
Class argumentTypes[] = new Class[arguments.length];
for(int i=0; i < arguments.length; i++){
argumentTypes[i] = arguments[i].getClass();
if(argumentTypes[i] == Integer.class)
argumentTypes[i] = int.class;
}
signature = signature.substring(signature.lastIndexOf('.') +
1, signature.indexOf('('));
try{
method = object.getClass().getMethod(signature, argumentTypes);
}catch(Exception e){e.printStackTrace();}
}
public void run(){
try{
output = method.invoke(object, arguments);
}catch(Exception e){e.printStackTrace();}
}
}
pointcut init() : call(SplashScreen.new());
pointcut widgetConstructor() : call(org.eclipse.swt.*.*.new(..));
pointcut widgetMethod() : call(public * org.eclipse.swt.*.*.*(..));
SplashScreen around(): init() && !within(BackgroundThread){
new Thread(new
ConstructorRunner(thisJoinPoint.getSignature().toString(),
thisJoinPoint.getArgs())).start();
return null;
}
Object around (): widgetConstructor() && within(SplashScreen){
ConstructorRunner cr = new
ConstructorRunner(thisJoinPoint.getSignature().toString(),
thisJoinPoint.getArgs());
xtellirad2AOP.Display.syncExec(cr);
return cr.output;
}
Object around (): widgetMethod() && within(SplashScreen){
MethodRunner or = new MethodRunner(thisJoinPoint.getTarget(),
thisJoinPoint.getSignature().toString(), thisJoinPoint.getArgs());
xtellirad2AOP.Display.syncExec(or);
return or.output;
}
}
I'm sure there are other more useful applications for this kind of
aspect, is there another way to save/transfer/execute what proceed()
is going to do?
Cheers,
jonpry
jon at nospam xtelli dot net