McCLIM 0.9.9 "Ostara" release
Written by Daniel Kochmański on 2025-03-11 15:00
Table of Contents
Dear All,
After a year of development it is time to make a release. The codename of this version is "Ostara", after the second of the eight annual pagan holidays celebrating the arrival of spring. Ostara was a Germanic goddess representing rebirth and is the equivalent of Easter.
In this release we mainly focus on robustness with numerous bugs fixed and a few features implemented. Most notably McCLIM streams are now thread-safe to write to and to draw on. Here is the list of committers and their number of commits since the last release:
Daniel Kochmański (502), Charlie McMackin (15), Andrea Demichele (2), John Carroll (1), José M. Á. Ronquillo Rivera (1) and Robert Brown (1).
This is not an exhaustive list of contributors, as it does not list people who reported issues, updated the wiki, or performed other non-coding tasks. Thank you! Moreover I'd like to thank people who donate money to my Patreon page, your continuous support means a lot to me.
Changes
For a detailed list of changes, consult the NEWS file or the git log directly. Below is a high-level overview of these changes.
More strict processing of geometry changes, repaints and recording
This is the least visible change because it pertains to how we process updates
to states of CLIM stream panes. Previously when the program added new output,
the pane was resized immediately, followed by scrolling and repainting. That was
clearly suboptimal, especially when there is a lot of changes done in a short
period of time. Instead, we now batch these changes and execute them when
STREAM-FINISH-OUTPUT
is called. That greatly improves performance and saves
visual glitches for certain scenarios.
Dynamic slots for medium state and the current text line
To enable concurrent drawing threads, we needed to ensure that there are no races regarding drawing options (like the drawing ink or the text style). To do that, CLIM stream panes have a slot that contains an instance of a class that has dynamic slots (for how this work see my blog post). This allows for drawing and writing text to streams concurrently from multiple threads. For example:
In this demo we have seven concurrent threads:
- two threads print 1000 lines with prefixes "XXX" and "YYY"
- four threads drawing dots in different colors
- one thread monitors the current progress of printing lines
Note that we may also scroll the output while these threads are still running and modifying the sheet. The cursor is not corrupted and the output proceeds without glitches.
Thread-safe output history and drawing context
Modifications to the output record history and writing pixels on a buffer are
mutually exclusive operations protected with locks. For forward compatibility,
all repaint requests by the program should be issued with DISPATCH-REPAINT
.
Moreover the user program should not directly use operators that change the
output recording state of the stream.
Notice how multiple threads are modifying the sheet geometry and the cursor position. The output record history is a bottleneck because each thread, after drawing, needs to take the lock and update the record. This is suboptimal, but enables us to quickly write throwaway code like this:
(in-package "CLIM-USER")
(defparameter *stream* (open-window-stream :width 800 :height 600))
(defparameter *stop* t)
(defun woosh (id ink)
(setf *stop* nil)
(with-drawing-options (*stream* :ink ink)
(loop while (null *stop*) do
(updating-output (*stream* :unique-id id :fixed-position t)
(format *stream* "Time: ~a~%" (get-internal-real-time)))
(sleep 1/30))))
(bt:make-thread (lambda () (woosh :thread-1 +dark-red+)))
(bt:make-thread (lambda () (woosh :thread-2 +dark-blue+)))
and in my opinion it is great for prototyping, because you can add additional elements while the program is running without invoking arcane protocols.
Refactored text renderer for performance and alternative text directions
The text renderer has been refactored to achieve better performance and exploit optimization opportunities when they are presented. For example a different code path is executed when the text is not translucent.
That said, the most notable change with the text renderer is the ability to change the line and the page directions:
These changes apply to DRAW-TEXT. Line-oriented integration with CLIM streams that allows mixing the text that has different directions is not yet implemented, but we can already mix text and graphics, and the latter will be correctly wrapped along the text when necessary.
New demos
I wrote new demos that may be started from the system clim-examples
:
- incremental redisplay: demonstrates how to work with output record caches
- animation with pulse: an animation with a timer synchronizing redisplay
- concurrent drawing: a demo where we can spin any number of drawing threads
- concurrent writing: a stress test for concurrent writing lines to a stream
- concurrent griding: a stress test with concurrent drawing with many records
Future changes
The repaint queue
The thread-safety of CLIM streams is factored out from a branch repaint-queue
.
This branch works, but it still has various regressions that need to be
addressed before merging. The results are very promising and its effect
compounds with thread-safety, because drawing locks the output history far less
often, while recording is rather cheap.
Input editing streams rewrite
This work is mostly done but it needs more testing and there are a few bugs that
need to be addressed before merging. This change involves also better command
completions that include a fuzzy completer, and makes text editing much easier.
If you want to see the current state of it check out input-editing
branch.
SDL2 backend and keyboard layouts
I didn't work on either of these tasks since the last release, but I plan to
finish them after merging branches repaint-queue
and input-editing
. After
finishing SDL2 branch and keyboard layouts I want to make the next release.
Closing remarks
McCLIM improves on a daily basis, and this trend continues. I'm very happy that I've been able to make a timely release unlike the last one. Fixing numerous issues further accelerates other improvements. From my subjective perspective the software is much more resilient than a year ago.
You may grab the latest release from here: https://codeberg.org/McCLIM/McCLIM/releases/tag/0.9.9-ostara.
Best regards,
Daniel Kochmański