Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Cache behaviour as an aspect

You should use "around" advice, so that way you can get the returned value
the first time around, and then not call 'proceed' when what you need is
already in the table.

Below is a code sample (free to anyone to use) that shows how proceed is
used, and how to avoid the call from being made if it's in the cache
already.

-Macneil

import java.util.Hashtable;

public class ComputeValues {
  private int x;

  public ComputeValues(int x) {
    this.x = x;
  }

  public int hardComputation(int j) {
    System.out.println("- Crunch!");
    return (int)Math.pow(x, j);
  }

  public static void main(String[] args) {
    ComputeValues a = new ComputeValues(5);
    for (int i=1; i<=3; ++i)
      a.hardComputation(i);
    a.hardComputation(2);
    a.hardComputation(3);
  }
}

privileged aspect ComputationCaching {
  private Hashtable table = new Hashtable();

  pointcut hardStuff(ComputeValues cv, int val):
    target(cv) && execution(int hardComputation(int)) && args(val);

  int around(ComputeValues cv, int val): hardStuff(cv, val) {
    System.out.println("Computing with " + cv.x + " and " + val);

    Hashtable objs = (Hashtable)table.get(cv);
    if (objs != null) {
      Integer cached = (Integer)objs.get(new Integer(val));
      if (cached != null) {
        System.out.println("- Using precomputed value: " + cached.intValue());
        // it's already in the table, return instead of calling proceed
        return cached.intValue();
      }
    }

    int result = proceed(cv, val);
    System.out.println("- Computed for the first time: " + result);
    if (objs == null) {
      objs = new Hashtable();
      table.put(cv, objs);
    }
    // now that we have it, put it in the table!
    objs.put(new Integer(val), new Integer(result));
    return result;
  }
}

> Hi,
>
>  Im trying to implement cache behaviour as an aspect. My initial approach
> was to implement a class wich performs a calculation in a oblivious manner,
> and I expected to develop an Aspect for the class wich would return the
> cached value when possible. The trick is that I couldnt find a way to
> override the returned value, is this possible? if not, is there some kind
> pattern to achieve this?
>
> This is the code for the class:
>
> public class Screen {
>
> 	private int width;
> 	private int height;
>
> 	public Screen() {
> 	}
>
> 	public void setSize(int width, int height) {
> 		this.width = width;
> 		this.height = height;
> 	}
> 	//this is the calculation method
> 	public int getIndexByCoordenates(int x, int y) {
> 		return y * width + x;
> 	}
> }
>
> This is the code for the aspect:
>
> public aspect ScreenCacheAspect {
>
> 	//cache matrix
> 	private int [][] screen;
>
> 	//initialize cache matrix
> 	before(Screen scr, int x, int y): call(void Screen.setSize(int,int)) &&
> target(scr) && args(x,y){
> 		this.screen = new int[x][y];
> 		for(int i = 0; i < x; i++) {
> 			for (int j = 0; j < y; j++) {
> 				screen[i][j] = -1;
> 			}
> 		}
> 	}
> 	//if in cache return value from cache
> 	before(Screen scr, int x, int y):
> 				call(int Screen.getIndexByCoordinates(int,int)) && target(scr) &&
> args(x,y) {
> 		if (screen[x][y] != -1) {
> 			//HOW TO IMPLEMENT THIS?
> 			return screen[x][y];
> 		}
> 	}
> 	//if not in cache, store the calculated value.
> 	after(Screen scr, int x, int y) returning (int index):
> 				call(int Screen.getIndexByCoordinates(int,int)) && target(scr) &&
> args(x,y) {
> 		if (screen[x][y] == -1) {
> 			screen[x][y] = index;
> 		}
> 	}
> }
>
> thanks in advance,
> Gabriel
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users
>


Back to the top