Home | Papers | Reports | Projects | Code Fragments | Dissertations | Presentations | Posters | Proposals | Lectures given | Course notes |
<< 10. Concurrent Processes and Transactions | 12. Petrinets >> |
11. Asynchronous Fractal CalculationWerner Van Belle1 - werner@yellowcouch.org, werner.van.belle@gmail.com Abstract : In this excercise we convert a julia-set calculator to work distributed. This lecture was given in 2001-2002 and 2002-2003
Reference:
Werner Van Belle; Asynchronous Fractal Calculation; |
import java.rmi.*; import java.lang.String; import java.awt.*; import java.awt.event.*; import java.awt.image.*; /** * calculates a julia set for the given coordinates and sends an answer * back */ public class FractalCalcer extends Actor { Color colorscheme[]; int XS = 0; int YS = 0; int PREC = 7; public FractalCalcer(String name) throws RemoteException { super(name); colorscheme=new Color[PREC+1]; for (int i=0; i<PREC; i++) { int phase=5*i/PREC; colorscheme[i]= new Color((phase+0)%6,phase,(phase+0)%6); } colorscheme[PREC]=Color.black; } void drawMandleBrot(BufferedImage g, int w, int h) { double x, y, t, cx, cy; int k; for (double i=-2; i<2; i+=4.0/w) for (double j=-2; j<2; j+=4.0/h) { x=0; y=0; cx = i; cy=j; for (k=0; k<PREC; k++) { t = x*x-y*y+cx; y = 2*x*y+cy; x = t; if (x*x+y*y>=4) break; } g.setRGB((int)((i+2)*w/4), (int)((j+2)*h/4),colorscheme[k].getRGB()); } } void drawJuliaBSM(BufferedImage g, double cx, double cy, int w, int h) { double x, y, t; int k; for (double i=-2; i<2; i+=4.0/w) for (double j=-2; j<2; j+=4.0/h) { x = i; y=j; for (k=0; k<PREC; k++) { t = x*x-y*y+cx; y = 2*x*y+cy; x = t; if (x*x+y*y >= 4) break; } g.setRGB((int)((i+2)*w/4), (int)((j+2)*h/4),colorscheme[k].getRGB()); } } public void handleMessage(Message m) { if (m instanceof CalcRequest) { // if it is a calcrequest we calculate the juliaset CalcRequest cr=(CalcRequest)m; BufferedImage img; img=new BufferedImage(XS, YS, BufferedImage.TYPE_INT_RGB); drawJuliaBSM(img, 0, 0.8, XS, YS); //drawMandleBrot(img, XS, YS); // and return the answer CalcRequest request=(CalcRequest)m; sendMessage(request.returnTo,new ImageMessage(img,XS,YS)); } else super.handleMessage(m); } public static void main(String args[]) { try { new FractalCalcer(args[0]); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } } }
import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.rmi.*; import java.rmi.server.*; class FractalBufferedImage extends Canvas { BufferedImage image; int XS=0; int YS=0; FractalBufferedImage() { Frame f = new Frame(); f.setSize(XS,YS); f.add(this); f.show(); } public void setImage(BufferedImage img) { image=img; repaint(0); } public void paint(Graphics g) { if (image!=null) g.drawImage(image,0,0,this); } } public class FractalServer extends Actor { protected FractalBufferedImage painter; protected String client; public FractalServer(String name, String args[]) throws RemoteException { super(name); painter=new FractalBufferedImage(); client=args[1]; // send a calc-request to the first client sendMessage(client,new CalcRequest(name)); } public void handleMessage(Message m) { if (m instanceof ImageMessage) { ImageMessage im=(ImageMessage)m; painter.setImage(im.convertToBufferedImage()); } else super.handleMessage(m); } public static void main(String args[]) { try { new FractalServer(args[0],args); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } } }
import java.rmi.*; import java.rmi.server.*; import java.lang.reflect.*; import java.util.*; class MessageQueue { private boolean iswaiting=false; private Message busywith=null; private LinkedList ll = new LinkedList(); /** * Creates a messagequeue, which can be used to implement a synchronous * receive at consumer side and an asynchronous send ad producer side. In * other words. The push is asynchrounous and puts a message in the Q, * while the pop blocks if there is no message available. */ public MessageQueue() { } public synchronized void push(Message o) { ll.addLast(o); notify(); } /** * Blocking pop to retrieve the next message on the Q. If the Q is empty * this method will block until a message is pushed upon the Q. This method * is used to synchronize two threads to each other using a consumer * producer like approach. */ public synchronized Message pop() { try { if (ll.isEmpty()) { iswaiting=true; busywith=null; wait(); iswaiting=false; } busywith = (Message)ll.getFirst(); ll.removeFirst(); return busywith; } catch(Exception e) { e.printStackTrace(); } return null; } } public class Actor extends UnicastRemoteObject implements ActorInterface, Runnable, Remote { protected String actor; private MessageQueue messages; public Actor(String name) throws RemoteException { try { actor=name; Naming.bind(name,this); messages=new MessageQueue(); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } new Thread(this).start(); } public void sendMessage(String target, Message m) { try { Remote rr=Naming.lookup(target); System.out.println(actor+" sends message"); ActorInterface r = (ActorInterface)rr; r.receiveMessage(m); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } } public void receiveMessage(Message m) throws RemoteException { try { System.out.println(actor+" received message"); messages.push(m); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } } public void run() { while(true) { Message m=messages.pop(); try { System.out.println(actor+" starts handling message"); handleMessage(m); System.out.println(actor+" stops handling message"); } catch (Exception e) { System.out.println("While handling message an error occured" + e); e.printStackTrace(); } } } public void handleMessage(Message m) { System.out.println("Please define a handleMessage(Message m) in your subclass"); } }
import java.rmi.*; public interface ActorInterface extends java.rmi.Remote { public void receiveMessage(Message m) throws RemoteException; }
import java.rmi.*; import java.lang.String; import java.awt.*; import java.awt.event.*; import java.awt.image.*; /** * calculates a julia set for the given coordinates and sends an answer * back */ public class AnimatedFractalCalcer extends Actor { Color colorscheme[]; int XS = 0; int YS = 0; int PREC = 7; public AnimatedFractalCalcer(String name) throws RemoteException { super(name); colorscheme=new Color[PREC+1]; for (int i=0; i<PREC; i++) { int phase=5*i/PREC; colorscheme[i]= new Color((phase+0)%6,phase,(phase+0)%6); } colorscheme[PREC]=Color.black; } void drawMandleBrot(BufferedImage g, int w, int h) { double x, y, t, cx, cy; int k; for (double i=-2; i<2; i+=4.0/w) for (double j=-2; j<2; j+=4.0/h) { x=0; y=0; cx = i; cy=j; for (k=0; k<PREC; k++) { t = x*x-y*y+cx; y = 2*x*y+cy; x = t; if (x*x+y*y>=4) break; } g.setRGB((int)((i+2)*w/4), (int)((j+2)*h/4),colorscheme[k].getRGB()); } } void drawJuliaBSM(BufferedImage g, double cx, double cy, int w, int h) { double x, y, t; int k; for (double i=-2; i<2; i+=4.0/w) for (double j=-2; j<2; j+=4.0/h) { x = i; y=j; for (k=0; k<PREC; k++) { t = x*x-y*y+cx; y = 2*x*y+cy; x = t; if (x*x+y*y >= 4) break; } g.setRGB((int)((i+2)*w/4), (int)((j+2)*h/4),colorscheme[k].getRGB()); } } public void handleMessage(Message m) { if (m instanceof JuliaRequest) { // if it is a calcrequest we calculate the juliaset JuliaRequest cr=(JuliaRequest)m; BufferedImage img; img=new BufferedImage(XS, YS, BufferedImage.TYPE_INT_RGB); drawJuliaBSM(img, cr.cx, cr.cy, XS, YS); sendMessage(cr.returnTo,new ImageMessage(img,XS,YS,actor,cr.id)); } else super.handleMessage(m); } public static void main(String args[]) { try { new AnimatedFractalCalcer(args[0]); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } } }
public class CalcRequest implements Message { public String returnTo; public CalcRequest(String returnImageTo) { returnTo=returnImageTo; } }
import java.util.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.rmi.*; import java.rmi.server.*; class FractalBufferedImage extends Canvas { BufferedImage image; int XS=0; int YS=0; FractalBufferedImage() { Frame f = new Frame(); f.setSize(XS,YS); f.add(this); f.show(); } public void setImage(BufferedImage img) { image=img; repaint(0); } public void paint(Graphics g) { if (image!=null) g.drawImage(image,0,0,this); } } public class FractalAnimator extends Actor { protected FractalBufferedImage painter; protected String clients[]; protected double x, dx; protected int sendid, nextid; protected Vector inQueue; public FractalAnimator(String name, String args[]) throws RemoteException { super(name); painter=new FractalBufferedImage(); clients=args; inQueue=new Vector(0,0); x = -1.0; dx = 0.2; nextid = 1; sendid = 1; askForNextFrames(); } protected void askForNextFrame(String proc) { x+=dx; sendMessage(proc,new JuliaRequest(actor,0.0,x,sendid++)); } protected void askForNextFrames() { int i=1; while(i<clients.length) { askForNextFrame(clients[i]); i++; } } protected boolean showFrameWhenAppropriate(ImageMessage frame) { // if this is the one we were waiting for, show it if (nextid == frame.id) { nextid++; painter.setImage(frame.convertToBufferedImage()); return true; } return false; } protected void newFrameArrived(ImageMessage frame) { System.out.print("frame "+frame.id+" arrived, was expecting "+nextid+" "); if (!showFrameWhenAppropriate(frame)) inQueue.add(frame); Iterator it=inQueue.iterator(); while(it.hasNext()) { ImageMessage j=(ImageMessage)it.next(); if (showFrameWhenAppropriate(j)) it.remove(); } } public void handleMessage(Message m) { if (m instanceof ImageMessage) { ImageMessage im=(ImageMessage)m; newFrameArrived(im); askForNextFrame(im.answerFrom); } else super.handleMessage(m); } public static void main(String args[]) { try { new FractalAnimator(args[0],args); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } } }
import java.awt.*; import java.awt.image.*; public class ImageMessage implements Message { public int xs; public int ys; public int id; int[] content; String answerFrom; public ImageMessage(BufferedImage img, int x, int y) { xs=x; ys=y; content=img.getRGB(0, 0, xs, ys, null, 0, xs); } public ImageMessage(BufferedImage img, int x, int y, String from, int i) { this(img,x,y); id=i; answerFrom=from; } public BufferedImage convertToBufferedImage() { BufferedImage image; image=new BufferedImage(xs, ys, BufferedImage.TYPE_INT_RGB); // im.setRGB(0,0,XS,YS,im.getImageData()); image.setRGB(0,0,xs,ys,content,0,xs); return image; } }
public class JuliaRequest implements Message { public String returnTo; public double cx,cy; public int id; public JuliaRequest(String returnImageTo, double ax, double ay, int i) { returnTo=returnImageTo; cx=ax; cy=ay; id=i; } }
import java.rmi.*; import java.io.*; interface Message extends Serializable { }
http://werner.yellowcouch.org/ werner@yellowcouch.org |