/************************************************************************************** * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package com.espertech.esper.core.service; import com.espertech.esper.client.EventBean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * A spin-locking implementation of a latch for use in guaranteeing delivery between * a single event produced by a single statement and consumable by another statement. */ public class InsertIntoLatchSpin { private static final Log log = LogFactory.getLog(InsertIntoLatchSpin.class); // The earlier latch is the latch generated before this latch private InsertIntoLatchFactory factory; private InsertIntoLatchSpin earlier; private long msecTimeout; private EventBean payload; private volatile boolean isCompleted; /** * Ctor. * @param earlier the latch before this latch that this latch should be waiting for * @param msecTimeout the timeout after which delivery occurs * @param payload the payload is an event to deliver */ public InsertIntoLatchSpin(InsertIntoLatchFactory factory, InsertIntoLatchSpin earlier, long msecTimeout, EventBean payload) { this.factory = factory; this.earlier = earlier; this.msecTimeout = msecTimeout; this.payload = payload; } /** * Ctor - use for the first and unused latch to indicate completion. */ public InsertIntoLatchSpin(InsertIntoLatchFactory factory) { this.factory = factory; isCompleted = true; earlier = null; msecTimeout = 0; } /** * Returns true if the dispatch completed for this future. * @return true for completed, false if not */ public boolean isCompleted() { return isCompleted; } /** * Blocking call that returns only when the earlier latch completed. * @return payload of the latch */ public EventBean await() { if (!earlier.isCompleted) { long spinStartTime = factory.getTimeSourceService().getTimeMillis(); while(!earlier.isCompleted) { Thread.yield(); long spinDelta = factory.getTimeSourceService().getTimeMillis() - spinStartTime; if (spinDelta > msecTimeout) { log.info("Spin wait timeout exceeded in insert-into dispatch at " + msecTimeout + "ms for " + factory.getName() + ", consider disabling insert-into between-statement latching for better performance"); break; } } } return payload; } /** * Called to indicate that the latch completed and a later latch can start. */ public void done() { isCompleted = true; earlier = null; } }