All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cosylab.epics.caj.cas.CASServerMonitor Maven / Gradle / Ivy

Go to download

JCA is an EPICS Channel Access library for Java. For more information concerning EPICS or Channel Access please refer to the <a href="http://www.aps.anl.gov/epics">EPICS Web pages</a> or read the <a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/CAref.html">Channel Access manual (3.14)</a>. <p>This module also includes CAJ, A 100% pure Java implementation of the EPICS Channel Access library.</p>

There is a newer version: 2.4.2
Show newest version
/*
 * Copyright (c) 2004 by Cosylab
 *
 * The full license specifying the redistribution, modification, usage and other
 * rights and obligations is included with the distribution of this project in
 * the file "LICENSE-CAJ". If the license is not included visit Cosylab web site,
 * .
 *
 * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
 * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
 * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
 * OR REDISTRIBUTION OF THIS SOFTWARE.
 */

package com.cosylab.epics.caj.cas;

import java.util.LinkedList;

import com.cosylab.epics.caj.cas.handlers.EventAddResponse;

import gov.aps.jca.cas.ProcessVariableEventCallback;
import gov.aps.jca.cas.ServerChannel;
import gov.aps.jca.cas.ServerMonitor;
import gov.aps.jca.dbr.DBR;

/**
 * CAS monitor implementation.
 * @author Matej Sekoranja
 * @version $id$
 */
public class CASServerMonitor extends ServerMonitor implements
		ProcessVariableEventCallback, Runnable {

	/**
	 * Monitor mask.
	 */
	protected short mask;
	
	protected EventAddResponse handler;
	protected CASTransport transport;
	protected short dataType;
	protected int dataCount;

    /**
     * 
     * @param channel ServerChannel
     * @param ioid event Id
     * @param mask monitor mask
     * @param handler EventAddResponse
     * @param transport CASTransport
     * @param dataType data type
     * @param dataCount data count
     */
	public CASServerMonitor(ServerChannel channel, int ioid,
							short mask, EventAddResponse handler, CASTransport transport, short dataType, int dataCount) {
		super(channel, ioid);
		
		this.mask = mask;
		this.handler = handler;
		this.transport = transport;
		this.dataType = dataType;
		this.dataCount = dataCount;
		
		// register to the event dispatcher
		((ProcessVariableEventDispatcher)channel.getProcessVariable().getEventCallback()).registerEventListener(this);
	}

	/**
	 * @see gov.aps.jca.cas.ServerMonitor#destroy()
	 */
	public void destroy() {

		// set destroyed flag and cleat queue (to help GC)
		synchronized (queue) {
			destoryed = true;
			queue.clear();
		}
		
		// unregister from the event dispatcher
		((ProcessVariableEventDispatcher)channel.getProcessVariable().getEventCallback()).unregisterEventListener(this);

		super.destroy();
	}


	/**
	 * @see gov.aps.jca.cas.CompletionCallback#canceled()
	 */
	public void canceled() {
		destroy();
	}

	
	/************************************ DISPATCHING ************************************/
	
	/**
	 * Ordered dispatch queue.
	 */
	protected LinkedList queue = new LinkedList();

	/**
	 * Pending event. 
	 * NOTE: synchronized on queue's monitor. 
	 */
	protected DBR pendingEvent = null;
	
	/**
	 * Flag indicating pending submit.
	 * NOTE: synchronized on queue's monitor. 
	 */
	protected boolean submitPending = false;

	/**
	 * Flag indicating destroy status.
	 * NOTE: synchronized on queue's monitor. 
	 */
	protected boolean destoryed = false;

	/**
	 * Max queue size.
	 * If limit is reached then older events are replaced with the newer.
	 */
	protected static final int MAX_QUEUE_SIZE = 100;

	/**
	 * NOT TO BE CHANGED.
	 * Processing is done one by one - to achieve better fairness.
	 */
	public final void run()
	{
		// get request
		synchronized (queue)
		{
			// if destroyed, bail out
			if (destoryed || queue.isEmpty())
				return;
			
			pendingEvent = (DBR)queue.removeFirst();
		}
		
		// send response
		handler.eventResponse(channel.getProcessVariable(), transport, dataType, dataCount, channel.getSID(), ioid, pendingEvent);

		// this line will always be reached - up code is (has to be) exception safe
		synchronized (queue)
		{
			// reset
			pendingEvent = null;
			submitPending = false;

			if (!queue.isEmpty())
				submit();
		}
		
	}

	/**
	 * Sumbit to be processed. 
	 */
	protected void submit()
	{
		synchronized (queue)
		{
			if (submitPending)
				return;

			// non blocking...
			submitPending = transport.processEvents(this);
			
			// check if request is already processed (in the same thread)
			if (pendingEvent == null)
				submitPending = false;
		}
	}

	/**
	 * @see gov.aps.jca.cas.ProcessVariableEventCallback#postEvent(int, gov.aps.jca.dbr.DBR)
	 */
	public void postEvent(int select, DBR event)
	{
			
		// filter
		if ((select & mask) == 0)
			return;

		synchronized (queue)
		{
			// if destroyed, bail out
			if (destoryed)
				return;

			// replace all previous requests in the queue, if replace policy is set
			if (transport.hasReplaceEventPolicy())
				queue.clear();

			// add to queue	
			queue.addLast(event);

			// discard the oldest one
			if (queue.size() > MAX_QUEUE_SIZE)
				queue.removeFirst();
			
			// initiate submit to dispatcher queue, if necessary
			if (!submitPending)
				submit();
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy