Changeset 14632


Ignore:
Timestamp:
03/02/14 10:05:53 (3 years ago)
Author:
mevenson
Message:

Fix CL:SLEEP for intervals less than a millisecond.

For intervals less than or equal to a nanosecond, including an
interval of zero, the current thread merely yields execution to other
threads.

Fixes <http://abcl.org/trac/ticket/345>.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/LispThread.java

    r14608 r14632  
    12381238        }
    12391239    };
    1240 
    1241 
    1242     public static final long javaSleepInterval(LispObject lispSleep)
    1243 
    1244     {
    1245         double d =
    1246             checkDoubleFloat(lispSleep.multiplyBy(new DoubleFloat(1000))).getValue();
    1247         if (d < 0)
    1248             type_error(lispSleep, list(Symbol.REAL, Fixnum.ZERO));
    1249 
    1250         return (d < Long.MAX_VALUE ? (long) d : Long.MAX_VALUE);
    1251     }
     1240   
     1241    final static DoubleFloat THOUSAND = new DoubleFloat(1000);
     1242
     1243    static final long sleepMillisPart(LispObject seconds) {
     1244      double d
     1245        = checkDoubleFloat(seconds.multiplyBy(THOUSAND)).getValue();
     1246      if (d < 0) {
     1247        type_error(seconds, list(Symbol.REAL, Fixnum.ZERO));
     1248      }
     1249      return (d < Long.MAX_VALUE ? (long) d : Long.MAX_VALUE);
     1250    }
     1251
     1252    static final int sleepNanosPart(LispObject seconds) {
     1253      double d  // d contains millis
     1254        = checkDoubleFloat(seconds.multiplyBy(THOUSAND)).getValue();
     1255      double n = d * 1000000; // sleep interval in nanoseconds
     1256      d = 1.0e6 * ((long)d); //  sleep interval to millisecond precision
     1257      n = n - d;
     1258
     1259      return (n < Integer.MAX_VALUE ? (int) n : Integer.MAX_VALUE);
     1260    }
     1261
    12521262
    12531263    @DocString(name="sleep", args="seconds",
    1254     doc="Causes the invoking thread to sleep for SECONDS seconds.\n"+
    1255         "SECONDS may be a value between 0 1and 1.")
     1264    doc="Causes the invoking thread to sleep for an interveral expressed in SECONDS.\n"
     1265      + "SECONDS may be specified as a fraction of a second, with intervals\n"
     1266      + "less than or equal to a nanosecond resulting in a yield of execution\n"
     1267      + "to other waiting threads rather than an actual sleep.")
    12561268    private static final Primitive SLEEP = new Primitive("sleep", PACKAGE_CL, true)
    12571269    {
     
    12591271        public LispObject execute(LispObject arg)
    12601272        {
    1261 
    1262             try {
    1263                 Thread.sleep(javaSleepInterval(arg));
    1264             }
    1265             catch (InterruptedException e) {
    1266                 currentThread().processThreadInterrupts();
    1267             }
    1268             return NIL;
     1273          long millis = sleepMillisPart(arg);
     1274          int nanos = sleepNanosPart(arg);
     1275
     1276          try {
     1277            if (millis == 0 && nanos == 0) {
     1278              Thread.yield();
     1279            } else {
     1280              Thread.sleep(millis, nanos);
     1281            }
     1282          } catch (InterruptedException e) {
     1283            currentThread().processThreadInterrupts();
     1284          }
     1285          return NIL;
    12691286        }
    12701287    };
     
    14191436    };
    14201437
    1421     @DocString(name="object-wait", args="object &optional timeout")
     1438    @DocString(
     1439    name="object-wait", args="object &optional timeout",
     1440    doc="Causes the current thread to block until object-notify or object-notify-all is called on OBJECT.\n"
     1441       + "Optionally unblock execution after TIMEOUT seconds.  A TIMEOUT of zero\n"
     1442       + "means to wait indefinitely.\n"
     1443       + "\n"
     1444       + "See the documentation of java.lang.Object.wait() for further\n"
     1445       + "information.\n"
     1446    )
    14221447    private static final Primitive OBJECT_WAIT =
    14231448        new Primitive("object-wait", PACKAGE_THREADS, true)
     
    14441469        {
    14451470            try {
    1446                 object.lockableInstance().wait(javaSleepInterval(timeout));
     1471        object.lockableInstance().wait(sleepMillisPart(timeout),
     1472               sleepNanosPart(timeout));
    14471473            }
    14481474            catch (InterruptedException e) {
Note: See TracChangeset for help on using the changeset viewer.