clj-con

2021-08-07

Implements Clojure-styled concurrency operations such as `future` and `promise`.

Upstream URL

github.com/dtenny/clj-con

Author

Dave Tenny

License

MIT
README

About

clj-con defines a set of concurrency operations modeled after their Clojure counterparts. Sample operators include future, promise, deref, deliver, and atom. See the exported symbols in package.lisp for the full list.

Or, if you're familiar with the Clojure Cheatsheet, the project implements the following:

Cheatsheet Screenshot

along with promise and deliver.

Usage

If you didn't get this via quickload from the quickload repo (because it isn't there yet), add it to your ~/quicklisp/localprojects/ directory, update/wipe the system-index.txt file accordingly, and then you can quickload it.

;; See 'local-projects' note in preceding paragraph            
(ql:quickload :clj-con) ; to use the code

or

;; To run the test (again, see 'local-projects' note)
(ql:quickload :clj-con-test)
(clj-con-test:run-tests)

Implementation Status

The current implementation was tested on sbcl and abcl successfully (with 20 iterations of run-tests on each, because, you know, threads and all).

The definitions are meant to be portable and are implemented entirely on Bordeaux Threads, but for those same reasons they aren't terribly efficient (as BT has no condition variable broadcast, no compare-and-set, and so on). At some point I could see adding some optimized conditional compilations.

Differences from Clojure

reset-vals! and swap-vals! return vectors in Clojure but return multiple values here. I couldn't see the point of returning vectors when CL has no destructuring bind (outside of LOOP?) that works on vectors. At least you can use multiple-value-bind if you want.

atom package conflict

If you're going to (use :clj-con), note that atom requires a (:shadowing-import-from #:clj-con #:atom). I'm open to better ways to do this, I'm not much practiced in the arts of Common Lisp packages.

Use of interrupt-thread by future-cancel

The Java Virtual Machine's threading tools are really a marvelous thing. If you've been in that ecosystem a long time, going back to pthreads with some of its limitations (or lisp oddities built on them), will feel fragile, and reading the various SBCL source comments on interrupt-thread doesn't do much to prevent that feeling.

As this implementation is more a trial balloon than anything else, have a care about repeatedly interrupting threads or using complicated mission critical handlers in the threads unless you have taken to heart the use of WITHOUT-INTERRUPTS and other implementation dependent things. I didn't hit any problems with my simple tests but that isn't saying much.

Non-Goals

There is no attempt here to bring clojure syntax or persistent data structures to Common Lisp. Fortunately neither of those things is particularly prevalent in Clojure's concurrency operator model, at least not in the clojure.core namespace.

Some enterprising person might want to make a readtable that maps @ to deref, assuming it doesn't conflict with ,@, but that hasn't been done here so you'll just have to call deref.

Blocking Queues?

If you're missing clojure.core.async and want some blocking queues for producer/consumer situations, take a look at the lparallel.queue package (ql:quickload :lparallel). Unlike clojure.core.async it has a peek operator which I find useful when I need to speculatively try something on a queue element without losing FIFO ordering.

Feedback welcome

(reverse "moc.liamg@ynnet.evad")

Dependencies (2)

  • bordeaux-threads
  • fiveam

Dependents (0)

    • GitHub
    • Quicklisp