001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.util;
006
007import java.io.IOException;
008import java.nio.ByteBuffer;
009import java.util.concurrent.atomic.AtomicBoolean;
010
011/** WPIUtil JNI. */
012public class WPIUtilJNI {
013  static boolean libraryLoaded = false;
014  static RuntimeLoader<WPIUtilJNI> loader = null;
015
016  /** Sets whether JNI should be loaded in the static block. */
017  public static class Helper {
018    private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
019
020    /**
021     * Returns true if the JNI should be loaded in the static block.
022     *
023     * @return True if the JNI should be loaded in the static block.
024     */
025    public static boolean getExtractOnStaticLoad() {
026      return extractOnStaticLoad.get();
027    }
028
029    /**
030     * Sets whether the JNI should be loaded in the static block.
031     *
032     * @param load Whether the JNI should be loaded in the static block.
033     */
034    public static void setExtractOnStaticLoad(boolean load) {
035      extractOnStaticLoad.set(load);
036    }
037
038    /** Utility class. */
039    private Helper() {}
040  }
041
042  static {
043    if (Helper.getExtractOnStaticLoad()) {
044      try {
045        loader =
046            new RuntimeLoader<>(
047                "wpiutiljni", RuntimeLoader.getDefaultExtractionRoot(), WPIUtilJNI.class);
048        loader.loadLibrary();
049      } catch (IOException ex) {
050        ex.printStackTrace();
051        System.exit(1);
052      }
053      libraryLoaded = true;
054    }
055  }
056
057  /**
058   * Force load the library.
059   *
060   * @throws IOException if the library failed to load
061   */
062  public static synchronized void forceLoad() throws IOException {
063    if (libraryLoaded) {
064      return;
065    }
066    loader =
067        new RuntimeLoader<>(
068            "wpiutiljni", RuntimeLoader.getDefaultExtractionRoot(), WPIUtilJNI.class);
069    loader.loadLibrary();
070    libraryLoaded = true;
071  }
072
073  /**
074   * Write the given string to stderr.
075   *
076   * @param str String to write.
077   */
078  public static native void writeStderr(String str);
079
080  /** Enable mock time. */
081  public static native void enableMockTime();
082
083  /** Disable mock time. */
084  public static native void disableMockTime();
085
086  /**
087   * Set mock time.
088   *
089   * @param time The desired time in microseconds.
090   */
091  public static native void setMockTime(long time);
092
093  /**
094   * Returns the time.
095   *
096   * @return The time.
097   */
098  public static native long now();
099
100  /**
101   * Returns the system time.
102   *
103   * @return The system time.
104   */
105  public static native long getSystemTime();
106
107  /**
108   * Creates an event. Events have binary state (signaled or not signaled) and may be either
109   * automatically reset or manually reset. Automatic-reset events go to non-signaled state when a
110   * WaitForObject is woken up by the event; manual-reset events require ResetEvent() to be called
111   * to set the event to non-signaled state; if ResetEvent() is not called, any waiter on that event
112   * will immediately wake when called.
113   *
114   * @param manualReset true for manual reset, false for automatic reset
115   * @param initialState true to make the event initially in signaled state
116   * @return Event handle
117   */
118  public static native int createEvent(boolean manualReset, boolean initialState);
119
120  /**
121   * Destroys an event. Destruction wakes up any waiters.
122   *
123   * @param eventHandle event handle
124   */
125  public static native void destroyEvent(int eventHandle);
126
127  /**
128   * Sets an event to signaled state.
129   *
130   * @param eventHandle event handle
131   */
132  public static native void setEvent(int eventHandle);
133
134  /**
135   * Sets an event to non-signaled state.
136   *
137   * @param eventHandle event handle
138   */
139  public static native void resetEvent(int eventHandle);
140
141  /**
142   * Creates a semaphore. Semaphores keep an internal counter. Releasing the semaphore increases the
143   * count. A semaphore with a non-zero count is considered signaled. When a waiter wakes up it
144   * atomically decrements the count by 1. This is generally useful in a single-supplier,
145   * multiple-consumer scenario.
146   *
147   * @param initialCount initial value for the semaphore's internal counter
148   * @param maximumCount maximum value for the samephore's internal counter
149   * @return Semaphore handle
150   */
151  public static native int createSemaphore(int initialCount, int maximumCount);
152
153  /**
154   * Destroys a semaphore. Destruction wakes up any waiters.
155   *
156   * @param semHandle semaphore handle
157   */
158  public static native void destroySemaphore(int semHandle);
159
160  /**
161   * Releases N counts of a semaphore.
162   *
163   * @param semHandle semaphore handle
164   * @param releaseCount amount to add to semaphore's internal counter; must be positive
165   * @return True on successful release, false on failure (e.g. release count would exceed maximum
166   *     value, or handle invalid)
167   */
168  public static native boolean releaseSemaphore(int semHandle, int releaseCount);
169
170  static native long allocateRawFrame();
171
172  static native void freeRawFrame(long frame);
173
174  static native long getRawFrameDataPtr(long frame);
175
176  static native void setRawFrameData(
177      long frame, ByteBuffer data, int size, int width, int height, int stride, int pixelFormat);
178
179  static native void setRawFrameInfo(
180      long frame, int size, int width, int height, int stride, int pixelFormat);
181
182  /**
183   * Waits for a handle to be signaled.
184   *
185   * @param handle handle to wait on
186   * @throws InterruptedException on failure (e.g. object was destroyed)
187   */
188  public static native void waitForObject(int handle) throws InterruptedException;
189
190  /**
191   * Waits for a handle to be signaled, with timeout.
192   *
193   * @param handle handle to wait on
194   * @param timeout timeout in seconds
195   * @return True if timeout reached without handle being signaled
196   * @throws InterruptedException on failure (e.g. object was destroyed)
197   */
198  public static native boolean waitForObjectTimeout(int handle, double timeout)
199      throws InterruptedException;
200
201  /**
202   * Waits for one or more handles to be signaled.
203   *
204   * <p>Invalid handles are treated as signaled; the returned array will have the handle error bit
205   * set for any invalid handles.
206   *
207   * @param handles array of handles to wait on
208   * @return array of signaled handles
209   * @throws InterruptedException on failure (e.g. no objects were signaled)
210   */
211  public static native int[] waitForObjects(int[] handles) throws InterruptedException;
212
213  /**
214   * Waits for one or more handles to be signaled, with timeout.
215   *
216   * <p>Invalid handles are treated as signaled; the returned array will have the handle error bit
217   * set for any invalid handles.
218   *
219   * @param handles array of handles to wait on
220   * @param timeout timeout in seconds
221   * @return array of signaled handles; empty if timeout reached without any handle being signaled
222   * @throws InterruptedException on failure (e.g. no objects were signaled and no timeout)
223   */
224  public static native int[] waitForObjectsTimeout(int[] handles, double timeout)
225      throws InterruptedException;
226
227  /** Utility class. */
228  protected WPIUtilJNI() {}
229}