//
// $Id: Unsafe.java,v 1.1 2003/05/08 21:25:20 mdb Exp $

package com.threerings.util.unsafe;

import com.threerings.util.Log;
import com.samskivert.util.RunAnywhere;

/**
 * A native library for doing unsafe things. Don't use this library. If
 * you must ignore that warning, then be sure you use it sparingly and
 * only in very well considered cases.
 */
public class Unsafe
{
    /**
     * Enables or disables garbage collection. <em>Warning:</em> you will
     * be fucked if you leave it disabled for too long. Do not do this
     * unless you are dang sure about what you're doing and are prepared
     * to test your code on every platform this side of Nantucket.
     *
     * <p> Calls to this method do not nest. Regardless of how many times
     * you disable GC, only one call is required to reenable it.
     */
    public static void setGCEnabled (boolean enabled)
    {
        // we don't support nesting, NOOP if the state doesn't change
        if (_loaded && enabled != _gcEnabled) {
            if (_gcEnabled = enabled) {
                enableGC();
            } else {
                disableGC();
            }
        }
    }

    /**
     * Causes the current thread to block for the specified number of
     * milliseconds. This exists primarily to work around the fact that on
     * Linux, {@link Thread#sleep} is only accurate to around 12ms which
     * is wholly unacceptable.
     */
    public static void sleep (int millis)
    {
        if (_loaded && RunAnywhere.isLinux()) {
            nativeSleep(millis);
        } else {
            try {
                Thread.sleep(millis);
            } catch (InterruptedException ie) {
                Log.info("Thread.sleep(" + millis + ") interrupted.");
            }
        }
    }

    /**
     * Reenable garbage collection after a call to {@link #disableGC}.
     */
    protected static native void enableGC ();

    /**
     * Disables garbage collection.
     */
    protected static native void disableGC ();

    /**
     * Sleeps the current thread for the specified number of milliseconds.
     */
    protected static native void nativeSleep (int millis);

    /**
     * Called to initialize our library.
     */
    protected static native boolean init ();

    /** The current state of GC enablement. */
    protected static boolean _gcEnabled = true;

    /** Whether or not we were able to load and initialize our library. */
    protected static boolean _loaded;

    static {
        try {
            System.loadLibrary("unsafe");
            _loaded = init();
        } catch (UnsatisfiedLinkError e) {
            Log.warning("Failed to load 'unsafe' library: " + e + ".");
        }
    }
}
