points by DonHopkins 7 years ago

ITS had "Core Link Interrupts" for sending messages between processes and implementing cool features like "EVAL-IN-OTHER-LISP":

https://web.archive.org/web/20110720170137/http://www.sigfs....

3.4.3 The CLA, CLI, CLO and CLU Devices

These symbolic devices enable arbitrary pairs of procedures to talk to each other as buffered input-output devices. Each file on any of these "core link" devices represents a 200 word area, most of which is buffer, which may be simultaneously open for reading, writing, both or neither. The files are identified by two regular file names and a system name [Sec 2.2, 2.2.3]. Only one procedure at a time may have a core link open to write or read on one channel. All standard modes are available.

The CLO (Core Link Open) device may be used to open any core link file and (whether reading or writing) will create one if none exists with the name used. The CLU (Core Link Use) device is identical except that an .OPEN on it will fail if the referenced file does not already exist.

Core link "files" have some peculiar properties. When writing a core link, a procedure will hang if the buffer is full and will write an end-of-file mark outside of the data stream when it closes the channel it has the file open on. However, opening and writing again the same file name essentially pushes a new block of data into the pipeline to be removed by a reading procedure. A procedure reading a core link can not read past an end-of-file and must close and reopen the file if it suspects that there is more to follow. If a reading procedure closes a core link before encountering an end-of-file, remaining information until the end-of-file is ignored. Core link "files" cease to exist only if empty and open for neither reading nor writing or not empty and not open for from two to four minutes. In the later case they are expunged by the system job [Sec 6.5] to unclutter the system.

The CLI (Core Link Interrupt) device may only be opened to write. The two file names specified should be the UNAME and JNAME [Sec 5.1] of a procedure in the system with the CLI interrupt [Sec 4.2] enabled. If ther is no existing core link with the file names and system name used, the .OPEN will succeed in creating a link and interrupting the specified procedure. In addition ITS inserts in the created link two words of information as the start of the first file. These are the UNAME and JNAME of the .OPEN'ing procedure.

The CLA (Core Link Answer) device is to be used in response to a CLI interrupt. It may only be opened for reading and scans through all existing links for one with file names the same as the UNAME and JNAME [Sec 5.1] of the procedure doing the CLA open. If one is found not already open for reading, the .OPEN succeeds.

https://www.reddit.com/r/programming/comments/t4rre/common_l...

http://www.maclisp.info/pitmanual/system.html

The following is some sample code (complete with documentation) that I found in my notes and thought might be helpful:

    ;;; Notes about CLI interrupts:
    ;;;
    ;;; A CLI interrupt is what happens when another job sends to yours. It is
    ;;; normally the case that other jobs will send directly to a user's HACTRN.
    ;;; If, however, Lisp is interrupted by a CLI message, it can elect to handle
    ;;; handle the interrupt in an arbitrary way.
    ;;;
    ;;; To define a handler, two things must be done:
    ;;;  [1] Place the name of the handler function (function of one arg)
    ;;;  in the variable CLI-MESSAGE.
    ;;;  [2] Enable CLI handling with (SSTATUS CLI T)
    ;;;
    ;;; The handler should take a single argument which it probably should ignore
    ;;; since I have no idea what it is likely to be.
    ;;;
    ;;; The handler should open the file "CLA:" in (CLA BLOCK) mode and immediately
    ;;; discard the first 8 characters which will be garbage.
    ;;;
    ;;; The remainder of the stream, until a control-C or an eof, will be the text
    ;;; of the message sent. It may be read with TYI, READ, etc. and handled 
    ;;; however.

    (eval-when (eval compile)
      (cond ((not (get 'iota 'version))
             (load "liblsp;iota"))))

    (defun handle-cli-msg (ignore)
      (iota ((stream '((cla)) '(cla block)))
        (do ((i 0 (1+ i))) ((= i 8)) (tyi stream))
        (do ((c (tyi stream -1) (tyi stream -1)))
            ((or (= c -1) (= c 3)))
          (format t "~&~3,'0O ~@:C~%" c c)))) ;print out chars seen

    (setq cli-message 'handle-cli-msg)

    (sstatus cli t)

    ; --------

    (defun eval-cli-msg (ignore) ;alternate handler
      (iota ((stream '((cla)) '(block cla)))
        (do ((i 0 (1+ i))) ((= i 8)) (tyi stream))
        (do ((f (read stream nil) (read stream nil)))
            ((null f))
          (errset (eval f) nil)))) ;Quietly evaluate forms...

    ;; Assumes the other lisp will have EVAL-CLI-MSG as value of CLI-MESSAGE

    (defun eval-in-other-lisp (uname jname s-expression)
      (iota ((stream `((cli) ,uname ,jname) '(out ascii block)))
        (print s-expression stream)))
    SYS-DEATH Value NIL
pvg 7 years ago

Hah. One could probably make a decent (with [in]conclusiveness to taste) Worse is Better case study out of this.