Bluish Coder

Programming Languages, Martials Arts and Computers. The Weblog of Chris Double.


Lightweight threads in the browser

I've made some updates to the Scheme in Javascript library. You can run it at the jsscheme page.

I've split out the example scheme source and made it loadable via Ajax. To do this I use jQuery, a very nice Javascript library. I added a Scheme wrapper around the Ajax GET call so you can do code like this:

(ajax-get "example.scm" (lambda (result) (alert result)))

The more interesting change is a simple concurrency library giving lightweight threads that run in the browser. The API loosely follows that of Termite, a concurrent Scheme. It uses '!' for sending a message to a process and '?' to receive.

To use the library click on the 'currency' button. This will load the source via Ajax. Then press 'eval'. Once loaded you can start using it. There are some examples in the concurrency.scm file.

For example, a 'logger' process:

(define logger
   (lambda ()
     (let loop ((msg (?)))
       (if (string? msg)
             (process-msg msg)
             (loop (?)))))
     (process-msg "Logger exiting"))))

This loops waiting for a message in the process queue. When it appears it displays it and then waits for more messages. Any non-string message quits the process. An example of using it:

(define (logger-test)
   (lambda ()
     (! logger "Hello")
     (! logger "World")
     (! logger 'quit))))

I've also done an example of concurrency using Ajax. An 'ajax-process' waits for requests of the form '(FROM URL). When received it will retrieve the URL using Ajax and send the result to the FROM process:

(define ajax-process
   (lambda ()
     (let loop ((msg (?)))
       (let* ((from (car msg))
              (url (cadr msg)))
         (ajax-get url (lambda (result) (! from result))))
       (loop (?))))))

Using it is simple:

(alert (!? ajax-process `(,current-process "example.scm")))

This uses '!?' which sends a message and immediately waits for the result. You don't have to send to the current process. The next example instructs the Ajax process to send it to the log window:

(define (ajax-test2)
   (lambda ()
     (! ajax-process `(,logger "example.scm"))
     (! ajax-process `(,logger "concurrency.scm")))))

All this runs within the browser. Unfortunately it's not fast as it's interpreted. The JIT compiler does not work on Firefox and even if it did, it does not work with continuations which the concurrency system is based on. I'll look into improving this over time.


This site is accessable over tor as hidden service 6vp5u25g4izec5c37wv52skvecikld6kysvsivnl6sdg6q7wy25lixad.onion, or Freenet using key: