/*******************************************************************************
* Copyright (c) 2009 Clark N. Hobbie
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Clark N. Hobbie - initial API and implementation
*******************************************************************************/
package org.eclipse.ecf.ipc.semaphore;
import org.eclipse.ecf.ipc.IPCPackage;
/**
* <P>
* An internal class that provides an interface into the system for implementing
* semaphores.
* </P>
* <H2>Exceptions</H2>
* <P>
* To keep the native methods as simple as possible, the exceptions thrown in
* response to error conditions signal the nature of the error using integer
* codes. The codes are defined by the class constants whose names start with
* "ERROR_". For example, ERROR_UNKNOWN_HANDLE is used if the platform does not
* recognize the handle passed to it.
* </P>
*
* <H2>Virtual Files</H2>
* <P>
* Each semaphore is associated with a file in the file system. That file may
* or may not be required by the underlying operating system.
* </P>
*
* <P>
* In the case of Linux, the contents of this file will be the absolute path of
* the file.
* </P>
*
* <P>
* In the case of Windows, the contents of the file will be an integer value
* uniquely identifies the semaphore.
* </P>
*
* @author Clark N. Hobbie
*/
public class SemaphoreNative {
static {
IPCPackage.initializePackage();
}
/**
* Does this particular native implementation support getting a semaphore's
* value?
*/
protected static Boolean ourSupportsGetValue;
/**
* Does this particular native implementation support setting a semaphore's
* value other than calling decrement methods?
*/
protected static Boolean ourSupportsSetValue;
/**
* Native routines should return this to signal that the routine executed
* without problems.
*/
public static final int RESULT_SUCCESS = 0;
/**
* The semaphore operation failed for an unanticipated reason.
*/
public static final int RESULT_UNKNOWN_ERROR = 1;
/**
* The semaphore operation failed for a reason that is specific to the
* platform.
*/
public static final int RESULT_PLATFORM_ERROR = 2;
/**
* The semaphore operation failed because the native platform does not
* recognize the handle used.
*/
public static final int RESULT_UNKNOWN_HANDLE = 3;
/**
* A value returned by the decrement method to signal that the method failed
* because the semaphore value was less than 1 and the specified timeout
* elapsed.
*/
public static final int RESULT_TIMEOUT = 4;
/**
* Access to the semaphore was denied when a particular operation was
* attempted.
*/
public static final int RESULT_ACCESS_DENIED = 5;
/**
* The requested method is not implemented by the native layer.
*/
public static final int RESULT_NOT_IMPLEMENTED = 6;
/**
* The semaphore has been incremented too many times.
*/
public static final int RESULT_TOO_MANY_INCREMENTS = 7;
/**
* Denotes that the actual name for a semaphore should be an integer value.
*/
public static final int METHOD_INTEGER = 0;
/**
* Denotes that the actual name for a semaphore should be absolute path to
* the virtual file.
*/
public static final int METHOD_FILE_NAME = 1;
/**
* Connect to the underlying semaphore, creating it if it does not already
* exist.
* <P>
* The return value will be greater than 0 if the method was successful.
* This indicates that the value can be used in future calls to this classes
* methods.
* <P>
* If the return value is less than 0, then the native method failed.
* Multiplying the return value by -1 should produce a result that
* corresponds to one of the return codes defined by this class. That is,
* the absolute value should match one of the RESULT_ constants.
* <P>
* The return value should never be equal to 0.
*
* @param name
* The logical name of the semaphore.
* @param initialValue
* The initial value of the semaphore.
* @return See description. A value greater than 0 means success, a value
* less than 0 means failure. The return value should not be equal
* to zero.
*/
public static native void connect(SemaphoreResult result, String name,
int initialValue);
/**
* Increase the value of the semaphore by 1.
*
* @param handle
* A logical value that the operating system uses to identify the
* semaphore.
* @return 0 if successful, otherwise -1.
*/
public static native void increment(SemaphoreResult result, long handle);
/**
* Decrease the value of the semaphore by 1 if it is available; if not
* available wait at least the specified period of time for it to become
* available.
* <P>
* The value used for handle should be one that is returned by the connect
* method.
* <P>
* The native method always checks to see if the semaphore is available. The
* only question is whether or not the method will wait for the semaphore if
* it is not currently available.
* <P>
* If the timeout is less than or equal to zero, the method will not wait
* for the semaphore to become available. If the semaphore is currently
* available, then it will decrement it, but if it is not available then the
* method returns immediately with a return code of {@link #RESULT_TIMEOUT}.
* <P>
* If the timeout is greater than zero, the method will wait some
* unspecified period of time that is greater than or equal to the specified
* timeout for the semaphore to become available. If the semaphore is
* currently available, the method decrements it and returns. If the
* semaphore is not available, then the method waits some unspecified period
* of time for it to become available. If the semaphore becomes available,
* the method decrements it and returns {@link #RESULT_SUCCESS}. If the
* semaphore does not become available in the period of time, the method
* returns {@link #RESULT_TIMEOUT}.
* <P>
* The underlying operating system may not provide the requested resolution
* for nanoseconds. Generally speaking, the resolution should be at least 1
* millisecond.
* <P>
* At present, the method returns some value other than DECREMENT_TIMEOUT if
* it fails for some other reason, such as the semaphore does not exist.
*
* @param handle
* Which semaphore to use.
* @param timeout
* The amount of time, in nanoseconds, to wait for the semaphore
* to become available if it is not currently available.
* @return {@link #RESULT_SUCCESS} if the method decrements the semaphore,
* otherwise some other RESULT_ code is returned.
*/
public static native void decrement(SemaphoreResult result, long handle,
long timeout);
/**
* Gets the current value of the semaphore.
* <P>
* The method returns 0 or greater on success and a negative value on
* failure. If the value indicates success, the return value is also the
* value of the semaphore. If negative, the absolute value corresponds to
* one the the RESULT_ constants.
*
* @param handle
* The semaphore to query.
* @return See description.
*/
public static native int getValue(SemaphoreResult result, long handle);
public static native boolean supportsGetValue();
/**
* Set the value of the semaphore, without regards to other processes.
* <P>
* This method replaces whatever value the semaphore had with the value
* passed to the method.
*
* @param handle
* The handle corresponding the semaphore to modify.
* @param value
* The new value for the semaphore.
* @return {@link #RESULT_SUCCESS} on success, otherwise a different RESULT_
* code.
*/
public static native int setValue(SemaphoreResult result, long handle,
int value);
public static native boolean supportsSetValue();
public static native void createResult(SemaphoreResult result, String name,
int maxValue, int initialValue);
public static native void linkTest();
/**
* Return the method that this platform uses in order to create a name for a
* semaphore.
*
* @return This method should return one of the METHOD_ constants.
*/
public static native int getNamingMethod();
}