Home AMX User Forum Duet/Cafe Duet

Concurrency

Anyone have a good way to transfer execution from a Timer's Thread back to the Thread that called it when times up?

Comments

  • PhreaKPhreaK Posts: 966
    Which Timer are we talking about here, the one from java.util or the SDK one?

    If you are just looking to link something to the tail of another thread Thread.join() is what you are after. This will pause the thread that it is called from until the thread you are joining completes.
  • JasonSJasonS Posts: 229
    I'm using the AMX one out of laziness. It is being called from a thread that is handling IP communication. I need the thread to pause until it is closer to the increment of a minute so that it can update time on a device that doesn't accept seconds. Currently this code runs in the timers thread so the offset across multiple threads becomes progressively greater. Can join be used with the AMX Timer? Doesn't it's thread keep running since all Timers use the same thread?

    I was trying to use a CountDownLatch, but it is throwing an IOException when it encounters the await().
    package com.ctsi_usa.duet.virtual.test.dr1_0_0;
    
    import java.util.Properties;
    import java.util.concurrent.CountDownLatch;
    
    import org.osgi.framework.BundleContext;
    
    import com.amx.duet.da.NetLinxDevice;
    import com.amx.duet.devicesdk.Utility;
    import com.amx.duet.util.Timer;
    import com.amx.duet.util.TimerListener;
    
    public class VirtualTest extends Utility{
    
    	Timer timer1 = null;
    	Timer timer2 = null;
    	
    	final CountDownLatch cdl = new CountDownLatch(1);
    	
    	TimerListener timerHandler = new InnerTimerHandler(cdl);
    
    	public VirtualTest() {
    		super();
    	}
    
    	/**
    	 * @param bctxt
    	 * @param nd
    	 * @param props
    	 */
    	public VirtualTest(BundleContext bctxt, NetLinxDevice nd, Properties props) {
    		super(bctxt, nd, props);
    		timer1 = new Timer(timerHandler, 5000);
    		System.out.println("timer1 started");
    		Thread.currentThread().setName("VirtualTest main Thread");
    		timer1.start();
    		new Thread(new InnerRunnable(cdl)).start();
    		
    	}
    
    	private class InnerTimerHandler implements TimerListener {
    
    		CountDownLatch latch;
    		
    		public InnerTimerHandler(CountDownLatch latch) {
    			this.latch = latch;
    		}
    		
    		/* (non-Javadoc)
    		 * @see com.amx.duet.util.TimerListener#handleTimerEvent(com.amx.duet.util.Timer)
    		 */
    		public void handleTimerEvent(Timer arg0) {
    			if (arg0.equals(timer1)) {
    				System.out.println("timer1 code ran in " + Thread.currentThread().getName());
    			} else if (arg0.equals(timer2)) {
    				System.out.println("timer2 cdl.countDown() running in " + Thread.currentThread().getName());
    				latch.countDown();
    			}
    		}
    		
    	}
    	
    	private class InnerRunnable implements Runnable {
    
    		CountDownLatch latch;
    		
    		public InnerRunnable(CountDownLatch latch) {
    			this.latch = latch;
    		}
    		
    		/* (non-Javadoc)
    		 * @see java.lang.Runnable#run()
    		 */
    		public void run() {
    			System.out.println("InnerRunnable Thread Started");
    			Thread.currentThread().setName("InnerRunnable Thread");
    			//cdl = new CountDownLatch(1);
    			timer2 = new Timer(timerHandler, 8000);
    			timer2.start();
    			System.out.println("timer2 started");
    			try {
    				latch.await();
    				System.out.println("code after cdl.await() running in " + Thread.currentThread().getName());
    			} catch (Exception e) {
    				System.out.println("cdl.await() Exception");
    				e.printStackTrace();
    			}
    		}
    		
    	}
    }
    
    This code requires Master Firmware 4.x.x Java Libraries

    This is the Output:

    (0000051591) Framework launched
    (0000052248) Creating Thread Pool
    (0000052415) AmxSslServerSocket(int,int): got called
    (0000055100) Device Access: No DriverLocators found
    (0000056433) Morpheus: Starting devicesdkrt.jar
    (0000062868) Morpheus: Starting snapirouter.jar
    (0000078798) timer1 started
    (0000078824) InnerRunnable Thread Started
    (0000078826) timer2 started
    (0000078828) cdl.await() Exception
    (0000078829) java.io.IOException
    (0000078833) at sun.misc.Unsafe.compareAndSwapObject (Native Method)
    (0000078835) at java.util.concurrent.locks.AbstractQueuedSynchronizer.compare
    AndSetHead (Unknown Source, bco=9)
    (0000078837) at java.util.concurrent.locks.AbstractQueuedSynchronizer.enq (Un
    known Source, bco=32)
    (0000078838) at java.util.concurrent.locks.AbstractQueuedSynchronizer.addWait
    er (Unknown Source, bco=47)
    (0000078839) at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcqui
    reSharedInterruptibly (Unknown Source, bco=7)
    (0000078841) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire
    SharedInterruptibly (Unknown Source, bco=27)
    (0000078892) at java.util.concurrent.CountDownLatch.await (Unknown Source, bc
    o=8)
    (0000078894) at com.ctsi_usa.duet.virtual.test.dr1_0_0.VirtualTest$InnerRunna
    ble.run (VirtualTest.java:123)
    (0000078895) at java.lang.Thread.run (Unknown Source, bco=16)
    (0000080081) SNAPIRouter: UtilityComponent loaded
    (0000080207) SNAPIRouter: ModuleComponent loaded
    (0000083815) timer1 code ran in TimerDaemon
    (0000086829) timer2 cdl.countDown() running in TimerDaemon
  • JasonSJasonS Posts: 229
    Found a solution, it doesn't even require the new libraries. I'm kind of disappointed.
    public class SyncObject {
        public SyncObject() {
             super();
        }
    
        public void doWait() throws InterruptedException {
            synchronized(this) {
                this.wait();
            }
        }
    
        public void doNotify() {
            synchronized(this) {
                this.notify();
            }
        }
    }
    
    import com.amx.duet.util.Timer;
    import com.amx.duet.util.TimerListener;
    
    public class SyncTimer {
    
        private SyncObject sync;
        private Timer timer;
        private InnerHandler handler = this.new InnerHandler();
    
        public SyncTimer(long time, SyncObject sync) {
            super();
            timer = new Timer(handler, time);
            this.sync = sync;
        }
    
        public void start() {
            timer.start();
        }
    
        private class InnerHandler implements TimerListener {
    
            public void handleTimerEvent(Timer arg0) {
                if (arg0.equals(timer) && sync != null) {
                    System.out.println("SyncTimer timed out in " + Thread.currentThread().getName());
                    sync.doNotify();
                }
            }
        }
    }
    
    import java.util.Properties;
    import org.osgi.framework.BundleContext;
    import com.amx.duet.da.NetLinxDevice;
    import com.amx.duet.devicesdk.Utility;
    import com.amx.duet.util.Timer;
    import com.amx.duet.util.TimerListener;
    
    public class VirtualTest extends Utility{
    
    	SyncTimer timer2;
    	SyncObject sync;
    	
    	public VirtualTest() {
    		super();
    	}
    
    	/**
    	 * @param bctxt
    	 * @param nd
    	 * @param props
    	 */
    	public VirtualTest(BundleContext bctxt, NetLinxDevice nd, Properties props) {
    		super(bctxt, nd, props);
    		Thread.currentThread().setName("VirtualTest main Thread");
    		new Thread(this.new InnerRunnable()).start();
    	}
    	
    	private class InnerRunnable implements Runnable {
    		
    		public void run() {
    			System.out.println("InnerRunnable Thread Started");
    			Thread.currentThread().setName("InnerRunnable Thread");
    			sync = new SyncObject();
    			timer2 = new SyncTimer(8000, sync);
    			timer2.start();
    			try {
    				sync.doWait();
    				System.out.println("code after sync.doWait() running in " + Thread.currentThread().getName());
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    Output:

    (0000046272) Framework launched
    (0000046929) Creating Thread Pool
    (0000047141) AmxSslServerSocket(int,int): got called
    (0000049256) Device Access: No DriverLocators found
    (0000050594) Morpheus: Starting devicesdkrt.jar
    (0000055953) Morpheus: Starting snapirouter.jar
    (0000072411) InnerRunnable Thread Started
    (0000073642) SNAPIRouter: UtilityComponent loaded
    (0000073761) SNAPIRouter: ModuleComponent loaded
    (0000080500) SyncTimer timed out in TimerDaemon
    (0000080502) code after sync.doWait() running in InnerRunnable Thread
Sign In or Register to comment.