Hack: 'virtual threads' in Common Lisp

2025-01-18

https://gitlab.com/bolsen80/vthreads

I was at a talk at javaBin in Bergen about Java Virtual Threads. (This is the only group I consistently go through since moving to Bergen in 2021.) The talk was about the new virtual threads in Java (https://openjdk.org/jeps/444). I don't know much about it, but I had the right enough idea before the talk proceeded. I imagined the data structures being used; they end up looking like a simple OS scheduler.

Threads are not cheap to setup, but lambdas are. If I have 1 thread doing scheduling and other worker threads finding what to do, it could just run through a load of threads rather quickly. There is no pre-emption in my rough back-of-the-napkin idea, since that would probably involve some form of continuations (which I know Paul Graham says he mimics in his book "On Lisp", but free in Schemes.)

So, the API would be called like this:

(defun test-a-few (vt-num osthr-num)
  (setq *should-stop* nil)
  (let ((out *standard-output*))
    (dotimes (i vt-num)
      (let ((vt-name (format out "test_~a" i)))
        (register-virtual-thread
         (make-a-thread vt-name (lambda () (format out "Thread prints: ~s~%" vt-name))))
        )))

  (make-os-threads osthr-num)
  (setq *should-stop* t))

(test-a-few 200 5)

In the example, it will schedule 200 vthreads on 5 OS threads. A supervisor thread will loop through the vthreads and just assign each thread a task and then wait for new tasks to run. Each worker would look each time for it's own assignments, and when it finds a fresh one, it will run it and proceed to the next one.

Right now, the implementation is dumb and I didn't write some stuff. Threads will busy wait here, consuming their core. Second, I just don't clean out the vthread list; since lists behave like linked lists, performance degradation would eventually occur if the list is big enough. BUT, this is a hack and it's just a way to learn CL, so .. :D

Tip!

(pushnew #P"/path/to/projects" ql:*local-project-directories*) in your .sbclrc file.

Your ASDF projects can then be quickloaded ...

(ql:quickload :vthreads)

In: lisp