Changeset 12040


Ignore:
Timestamp:
07/12/09 18:36:47 (14 years ago)
Author:
ehuelsmann
Message:

Add synchronization like in Java through the special operator SYNCHRONIZED-ON.

Location:
trunk/abcl/src/org/armedbear/lisp
Files:
1 added
5 edited

Legend:

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

    r12030 r12040  
    10131013    // ### make-thread
    10141014    private static final Primitive MAKE_THREAD =
    1015         new Primitive("make-thread", PACKAGE_EXT, true, "function &key name")
     1015        new Primitive("make-thread", PACKAGE_THREADS, true, "function &key name")
    10161016    {
    10171017        @Override
     
    10391039    // ### threadp
    10401040    private static final Primitive THREADP =
    1041         new Primitive("threadp", PACKAGE_EXT, true, "object",
     1041        new Primitive("threadp", PACKAGE_THREADS, true, "object",
    10421042          "Boolean predicate as whether OBJECT is a thread.")
    10431043    {
     
    10511051    // ### thread-alive-p
    10521052    private static final Primitive THREAD_ALIVE_P =
    1053         new Primitive("thread-alive-p", PACKAGE_EXT, true, "thread",
     1053        new Primitive("thread-alive-p", PACKAGE_THREADS, true, "thread",
    10541054          "Boolean predicate whether THREAD is alive.")
    10551055    {
     
    10701070    // ### thread-name
    10711071    private static final Primitive THREAD_NAME =
    1072         new Primitive("thread-name", PACKAGE_EXT, true, "thread",
     1072        new Primitive("thread-name", PACKAGE_THREADS, true, "thread",
    10731073          "Return the name of THREAD if it has one.")
    10741074    {
     
    11141114    // ### mapcar-threads
    11151115    private static final Primitive MAPCAR_THREADS =
    1116         new Primitive("mapcar-threads", PACKAGE_EXT, true, "function",
     1116        new Primitive("mapcar-threads", PACKAGE_THREADS, true, "function",
    11171117          "Applies FUNCTION to all existing threads.")
    11181118    {
     
    11351135    // ### destroy-thread
    11361136    private static final Primitive DESTROY_THREAD =
    1137         new Primitive("destroy-thread", PACKAGE_EXT, true, "thread",
     1137        new Primitive("destroy-thread", PACKAGE_THREADS, true, "thread",
    11381138          "Mark THREAD as destroyed.")
    11391139    {
     
    11591159    // order is not guaranteed.
    11601160    private static final Primitive INTERRUPT_THREAD =
    1161         new Primitive("interrupt-thread", PACKAGE_EXT, true,
     1161        new Primitive("interrupt-thread", PACKAGE_THREADS, true,
    11621162          "thread function &rest args",
    11631163          "Interrupts THREAD and forces it to apply FUNCTION to ARGS.\nWhen the function returns, the thread's original computation continues. If  multiple interrupts are queued for a thread, they are all run, but the order is not guaranteed.")
     
    11861186    // ### current-thread
    11871187    private static final Primitive CURRENT_THREAD =
    1188         new Primitive("current-thread", PACKAGE_EXT, true, "",
     1188        new Primitive("current-thread", PACKAGE_THREADS, true, "",
    11891189          "Returns a reference to invoking thread.")
    11901190    {
     
    12121212    };
    12131213
     1214    static {
     1215        //FIXME: this block has been added for pre-0.16 compatibility
     1216        // and can be removed the latest at release 0.22
     1217        try {
     1218            PACKAGE_EXT.export(Symbol.intern("MAKE-THREAD", PACKAGE_THREADS));
     1219            PACKAGE_EXT.export(Symbol.intern("THREADP", PACKAGE_THREADS));
     1220            PACKAGE_EXT.export(Symbol.intern("THREAD-ALIVE-P", PACKAGE_THREADS));
     1221            PACKAGE_EXT.export(Symbol.intern("THREAD-NAME", PACKAGE_THREADS));
     1222            PACKAGE_EXT.export(Symbol.intern("MAPCAR-THREADS", PACKAGE_THREADS));
     1223            PACKAGE_EXT.export(Symbol.intern("DESTROY-THREAD", PACKAGE_THREADS));
     1224            PACKAGE_EXT.export(Symbol.intern("INTERRUPT-THREAD", PACKAGE_THREADS));
     1225            PACKAGE_EXT.export(Symbol.intern("CURRENT-THREAD", PACKAGE_THREADS));
     1226        }
     1227        catch (ConditionThrowable ct) { }
     1228    }
     1229
    12141230    // ### use-fast-calls
    12151231    private static final Primitive USE_FAST_CALLS =
     
    12231239        }
    12241240    };
     1241
     1242    // ### synchronized-on
     1243    private static final SpecialOperator SYNCHRONIZED_ON =
     1244        new SpecialOperator("synchronized-on", PACKAGE_THREADS, true,
     1245                            "form &body body")
     1246    {
     1247        @Override
     1248        public LispObject execute(LispObject args, Environment env)
     1249            throws ConditionThrowable
     1250        {
     1251          if (args == NIL)
     1252            return error(new WrongNumberOfArgumentsException(this));
     1253
     1254          LispThread thread = LispThread.currentThread();
     1255          synchronized (eval(args.car(), env, thread).lockableInstance()) {
     1256              return progn(args.cdr(), env, thread);
     1257          }
     1258        }
     1259    };
     1260
     1261    // ### object-wait
     1262    private static final Primitive OBJECT_WAIT =
     1263        new Primitive("object-wait", PACKAGE_THREADS, true,
     1264                      "object &optional timeout")
     1265    {
     1266        @Override
     1267        public LispObject execute(LispObject object)
     1268            throws ConditionThrowable
     1269        {
     1270            try {
     1271                object.lockableInstance().wait();
     1272            }
     1273            catch (InterruptedException e) {
     1274                currentThread().processThreadInterrupts();
     1275            }
     1276            catch (IllegalMonitorStateException e) {
     1277                return error(new IllegalMonitorState());
     1278            }
     1279            return NIL;
     1280        }
     1281
     1282        @Override
     1283        public LispObject execute(LispObject object, LispObject timeout)
     1284            throws ConditionThrowable
     1285        {
     1286            try {
     1287                object.lockableInstance().wait(javaSleepInterval(timeout));
     1288            }
     1289            catch (InterruptedException e) {
     1290                currentThread().processThreadInterrupts();
     1291            }
     1292            catch (IllegalMonitorStateException e) {
     1293                return error(new IllegalMonitorState());
     1294            }
     1295            return NIL;
     1296        }
     1297    };
     1298
     1299    // ### object-notify
     1300    private static final Primitive OBJECT_NOTIFY =
     1301        new Primitive("object-notify", PACKAGE_THREADS, true,
     1302                      "object")
     1303    {
     1304        @Override
     1305        public LispObject execute(LispObject object)
     1306            throws ConditionThrowable
     1307        {
     1308            try {
     1309                object.lockableInstance().notify();
     1310            }
     1311            catch (IllegalMonitorStateException e) {
     1312                return error(new IllegalMonitorState());
     1313            }
     1314            return NIL;
     1315        }
     1316    };
     1317
     1318    // ### object-notify-all
     1319    private static final Primitive OBJECT_NOTIFY_ALL =
     1320        new Primitive("object-notify-all", PACKAGE_THREADS, true,
     1321                      "object")
     1322    {
     1323        @Override
     1324        public LispObject execute(LispObject object)
     1325            throws ConditionThrowable
     1326        {
     1327            try {
     1328                object.lockableInstance().notifyAll();
     1329            }
     1330            catch (IllegalMonitorStateException e) {
     1331                return error(new IllegalMonitorState());
     1332            }
     1333            return NIL;
     1334        }
     1335    };
     1336
     1337
    12251338}
  • trunk/abcl/src/org/armedbear/lisp/compiler-pass1.lisp

    r11923 r12040  
    303303    (push 'CATCH result)
    304304    (setf (block-form block) result)
     305    block))
     306
     307(defun p1-threads-synchronized-on (form)
     308  (let* ((synchronized-object (p1 (cadr form)))
     309         (body (cddr form))
     310         (block (make-block-node '(THREADS:SYNCHRONIZED-ON)))
     311         (*blocks* (cons block *blocks*))
     312         result)
     313    (dolist (subform body)
     314      (let ((op (and (consp subform) (%car subform))))
     315        (push (p1 subform) result)
     316        (when (memq op '(GO RETURN-FROM THROW))
     317          (return))))
     318    (setf (block-form block)
     319          (list* 'threads:synchronized-on synchronized-object
     320                 (nreverse result)))
    305321    block))
    306322
     
    10411057                  (THROW                p1-throw)
    10421058                  (TRULY-THE            p1-truly-the)
    1043                   (UNWIND-PROTECT       p1-unwind-protect)))
     1059                  (UNWIND-PROTECT       p1-unwind-protect)
     1060                  (THREADS:SYNCHRONIZED-ON
     1061                                        p1-threads-synchronized-on)))
    10441062    (install-p1-handler (%car pair) (%cadr pair))))
    10451063
  • trunk/abcl/src/org/armedbear/lisp/compiler-pass2.lisp

    r11962 r12040  
    11321132                 190 ; arraylength
    11331133                 191 ; athrow
     1134                 194 ; monitorenter
     1135                 195 ; monitorexit
    11341136                 198 ; ifnull
    11351137                 202 ; label
     
    76817683        (emit-move-from-stack target representation)))))
    76827684
     7685(defknown p2-threads-synchronized-on (t t) t)
     7686(defun p2-threads-synchronized-on (block target)
     7687  (let* ((form (block-form block))
     7688         (*register* *register*)
     7689         (object-register (allocate-register))
     7690         (BEGIN-PROTECTED-RANGE (gensym))
     7691         (END-PROTECTED-RANGE (gensym))
     7692         (EXIT (gensym)))
     7693    (compile-form (cadr form) 'stack nil)
     7694    (emit-invokevirtual +lisp-object-class+ "lockableInstance" nil
     7695                        +java-object+) ; value to synchronize
     7696    (emit 'dup)
     7697    (astore object-register)
     7698    (emit 'monitorenter)
     7699    (label BEGIN-PROTECTED-RANGE)
     7700    (compile-progn-body (cddr form) target)
     7701    (emit 'goto EXIT)
     7702    (label END-PROTECTED-RANGE)
     7703    (aload object-register)
     7704    (emit 'monitorexit)
     7705    (emit 'athrow)
     7706
     7707    (label EXIT)
     7708    (aload object-register)
     7709    (emit 'monitorexit)
     7710    (push (make-handler :from BEGIN-PROTECTED-RANGE
     7711                        :to END-PROTECTED-RANGE
     7712                        :code END-PROTECTED-RANGE
     7713                        :catch-type 0) *handlers*)))
     7714
     7715
    76837716(defknown p2-catch-node (t t) t)
    76847717(defun p2-catch-node (block target)
     
    78867919               ((equal (block-name form) '(PROGV))
    78877920                (p2-progv-node form target representation))
     7921               ((equal (block-name form) '(THREADS:SYNCHRONIZED-ON))
     7922                (p2-threads-synchronized-on form target)
     7923                (fix-boxing representation nil))
    78887924               (t
    78897925                (p2-block-node form target representation))))
  • trunk/abcl/src/org/armedbear/lisp/jvm.lisp

    r11990 r12040  
    421421  (let ((name (block-name object)))
    422422    (or (equal name '(CATCH))
    423         (equal name '(UNWIND-PROTECT)))))
     423        (equal name '(UNWIND-PROTECT))
     424        (equal name '(THREADS:SYNCHRONIZED-ON)))))
    424425
    425426
  • trunk/abcl/src/org/armedbear/lisp/precompiler.lisp

    r11996 r12040  
    489489        (cons 'PROGN (mapcar #'precompile1 body)))))
    490490
     491(defun precompile-threads-synchronized-on (form)
     492  (cons 'threads:synchronized-on (mapcar #'precompile1 (cdr form))))
     493
    491494(defun precompile-progv (form)
    492495  (if (< (length form) 3)
     
    994997                  (THE                  precompile-the)
    995998                  (THROW                precompile-cons)
    996                   (TRULY-THE            precompile-truly-the)))
     999                  (TRULY-THE            precompile-truly-the)
     1000
     1001                  (THREADS:SYNCHRONIZED-ON
     1002                                        precompile-threads-synchronized-on)))
    9971003    (install-handler (first pair) (second pair))))
    9981004
Note: See TracChangeset for help on using the changeset viewer.