20261025

Exercising on a Threadmiλ, multitasking

As I get older, I need to exercise. I decided to use a Threadmiλ.

Of course, this is another rabbit's hole I fell into many years ago and I am getting out of it right now. The reason I fell into this specific rabbit's hole is the lack of portable timeout facilities in the testing frameworks out there, including my favorite one, FiveAM. More on this later.

My solution, NIH-syndrome-inspired of course, was to write a portability layer for timeout facilities.

Which begged the question: why not Bordeaux Threads?

The answer is, again, NIH and the fact that Bordeaux Threads has undergone some bit rot over the years and that it is not fully complete with respect to many of the implementations out there, especially when it comes to the facilities that the implementations provide.

The result is Threadmiλ (or threadmiλ, or ThreadMIL, or threadmilambda...), i.e., a Bordeaux Threads like library, re-done in MILan; the λ is de rigueur.

Threadmiλ

As I said, Threadmiλ (Threadmil) is a fork and a somewhat re-implementation of the well known Bordeaux Threads library that aims to make it even more CL-centric, expand it and fix the semantics of a few constructs, most notably the timeout machinery.

Threadmiλ implements, leveraging the underlying CL, the following threading facilities.

  • Threads
  • Locks
  • Semaphores
  • Condition Variables
  • Timers
  • Mailboxes
  • Barriers
  • Atomics
  • Timeouts

These are the facilities available in most CL, especially Lispworks.

Current Implementation Status

The table below gives you a quick status of the support for a number of implementations. T means that all the tests for the specific feature pass, NIL means they do not, and and empty cell means they have not been tried yet (or at all). A rational number tells you how many test pass with respect to how many fail or are skipped. The test suite uses fiveam.

LW SBCL CMUCL ECL ABCL CCL CLISP ACL
Threads T T T T T T
Locks (1) T 14/17 T T 15/21 14/18
Semaphores T T T T T T
Condition Vars T T T T T T
Timeouts (2) T T T T T T
Timers T T T T T T
Mailboxes T T T T T T
Barriers T T 11/12 T T T
Atomics T T T T T T

Note that the table simply reflects the current compliance with the set of tests. Adding some tests may change the entries in the table. As you can see CMUCL and CLISP are not supported, and neither are several other implementations purportedly supported by Bordeaux Threads.
(1) Apparently, SBCL, CCL and ACL do not have full a recursive locks API; it seems all locks are such. The missing bits are different and this is reflected in the number of tests actually performed. In the future the regular API may be used and the missing tests will just work.
(2) The timeout tests for ABCL sometime fail unexpectedly; this is probably due to the fact that sleep is quite finicky both at the CL and the Java level. Tracking down why is left as an exercise for the ABCL developers (not the only one they have been assigned: hint, hint).

Where You Can Get your Threadmiλ

The main documentation page can be found https://threadmil.common-lisp.dev.
/ The project page is at https://gitlab.common-lisp.net/mantoniotti/threadmilambda

How Did I Get Here?

Before AI stuff I used some testing frameworks to tortur... pardon, evaluate students' projects (yes, I inflict CL on them). Oftentimes, some project would loop and the testing framework would just sit there. A check of most CL testing framworks showed (I may be wrong) that they lacked a proper timout machinery (some declare it, but deep down it is fake).

I thus set out to create a portable with-timeout macro. That was the mistake that led to Threadmiλ.

Now, testing frameworks developers have no more excuses.

Disclaimer

As usual here you have the scariest disclaimer here. The library is bound to have bugs and race conditions.

AI was used only to generate a few of the tests.

Any Help Appreciated

Of course you are free to fork the project subject to the current licensing scheme. However, before you do so, I ask you to consider plain old "cooperation" by asking me to become a developer. It helps keeping the entropy level at an acceptable level.

Of course, in this case, I did not heed my own advice, and yet...


'(cheers)

Marco Antoniotti 2026-10-24

20260524

Getting HEΛP, Finally!

As I wrote in my last blog entry, I went back hacking on HEΛP.

HEΛP is the Common Lisp code documentation tool I started writing many years ago.

Apart from a little necessary Javascript and CSS, HEΛP is a full Common Lisp program, geared towards producing static documentation sites for CL code. I finally got around to modernize it and it is now ready for testing.

Evolution from (X)HTML to HTML5

The original HEΛP release was producing only (X)HTML output, moreover based on FRAMESETs.

Alas, when the first HEΛP release was made, FRAMESETs were falling out of fashion, and they were eventually deprecated with the advent of HTML5. An "upgrade" to HTML5 became then a necessity.

After a very long process, I finally finished the HTML5 port, plus some bells and whistles. All in all, the implementation uses <div ... > sections plus CSS to lay out the display, as I understand it is the proper coding fashion nowadays. The port uses the W3.CSS styles, which facilitated a number of choices. The result is rather pleasing, as far as I am concerned.

Example: Producing the HEΛP documentation

The HEΛP documentation (a form of it) is produced with the following command (hlp is one of the package nicknames):

(hlp:document #P"./" ; Just a "top directory"...
              :documentation-title "HE&Lambda;P"
              :format :html5
              :exclude-directories
              (list "doc/"
                    "js/"
                    "css/"
                    ".git/"
                    "tests/"
                    "tmp/"
                    "tools/"
                    )

              :exclude-files ; I run this from LW.
              (list "impl-dependent/ccl.lisp"
                    "impl-dependent/sbcl.lisp"
                    "utilities/document-helambdap.lisp"
                    "utilities/lambda-list-parsing.lisp"
                    )
              :only-documented t
              :only-exported t
              )

After much printing, the resulting static web pages are deposited in docs/html5/, unless overridden. The system also relies on some defaults which are handled by CLAD library.

Viewing the result.
For the time being, you can find the main page of HEΛP here. Navigating the bar on the left will allow you to see different bits and pieces fo the documentation. You will notice that you have different views of the documentation: a system view and a package view. The system view gives you also a view of the files and folders (modules) it contains.

Documentation strings are mostly left alone.
Unike for Emacs Lisp, there is no real agreement in the CL community about how to format documentation strings (if there is, I do not agree with it by definition - obviously). HEΛP wants to be able to document code that does not adopt any documentation string convention, therefore it treats documentation strings pretty much as they are, only adding some text in the guise of the Hyperspec entries.

Screenshot

Here are a couple of screenshots. Apologies for the bad resolution.

The Main View

The HEΛP Main View

The DIctionary View

The HEΛP Dictionary View

Missing Pieces

There is one thing that is missing from HEΛP: the generation of proper crossreferencing. To do it correctly it will be necessary to somehow make some educated guesses about the content of documentation strings or agreeing on some markup to tag linkable items. Apart from that, at the time of this writing the doc strings are handled as enties in an has table, and that could be improved, as more indexes may be needed.

Of course, a major rewrite may also help, but time is a tyrant.

Any suggestion is welcome.

Try it!

Again, HEΛP is ready for you to try. You can clone the repository from Sourceforge.

... and remember: no Python or Ruby or Shell dependencies: pure CL (plus some Javascript, which is a functional language after all, whose first implementation was done in CL).

Enjoy!


'(cheers)

20260402

An Update on MK-DEFSYSTEM

There are still a few of us (at least two) who are using MK:DEFSYSTEM. The venerable system construction tool has accumulated a lot of ancient cruft, some of which quite convoluted.

Recently I went back to MK:DEFSYSTEM and "cleaned up" some of the code, especially regarding the pathname construction for each component.  I also used some simpler hierarchical tricks using defstruct only.

The result should be more solid and clearer in the steps that comprise some "macro tasks". Of course, a rewrite using CLOS would change the coding style, but the choice has been made to keep the MK:DEFSYSTEM code base quite... retro (and somewhat simple).

Why did I went back to MK:DEFSYSTEM? As usual, it is because of a rabbit-hole I fell into: I will blog about it later on (hint: HEΛP).

MK-DEFSYSTEM quick history as of March 2026

MK-DEFSYSTEM (or MK:DEFSYSTEM, or MAKE:DEFSYSTEM) was originally written by Mark Kantrowitz as part of the original "CMU Lisp Utilities" collection; an early "public" set of Common Lisp code and utilities that, in the writer's opinion form one of the basis of most Common Lisp writing to date.

As stated (by M. Kantrowitz himself) in this file header, the original version of MK-DEFSYSTEM was inspired by the Symbolics DEFSYSTEM (or DEFSYS) tool. Yet, MK-DEFSYSTEM differs significantly from it.

In its original form, MK-DEFSYSTEM was built in the CLtL1 era, accommodated a lot of variance among filesystems and CL implementations and it still bears those idiosycrasies. CLtL2 (1992) first and ANSI (1994) next, started reshaping the code base then.

MK-DEFSYSTEM was originally distributed under a license agreement that made redistribution tricky. In 1999, the writer - that'd be me, Marco Antoniotti - contacted Mark Kantrowitz offering to become a maintainer while reworking the distribution license to hammer some FOSS into it. Mark Kantrowitz graciously agreed and, after that, the writer got literally and physically hugged by a few Common Lisp developers because they could use MK-DEFSYSTEM more freely.

Of course, ASDF came along and it solved the same problems that Symbolics (and Kent Pitman's) DEFSYS and MK-DEFSYSTEM solve, plus much more.

Yet, MK-DEFSYSTEM has some nice features (in the eye of the beholder).

MK-DEFSYSTEM still ships in one file - defsystem.lisp - that you can LOAD in your Common Lisp init file. Of course, a big chunk of its current code base is "backward compatibility" and new ok-we-miss-UIOP-and-or-at-least-CL-FAD functionality, plus an ever growing ongoing commentary like this one.

Given this background, the writer has been maintaining MK-DEFSYSTEM for a long time, and more recently, Madhu has made significant changes (and maintains himself a fork with some bells and whistles of his own) since 2008.

Of course, many other contributors helped over the years, and are acknowledged in the early Change Log and in comments in the code.

In early 2026, the writer cleaned up the code and reworked some of the logic, by factoring out some code from main functions. In particular, the CREATE-COMPONENT-PATHNAMES, GENERATE-COMPONENT-PATHNAMES, COMPONENT-FULL-PATHNAME, COMPONENT-FULL-NAMESTRING interplay is better organized; plus new structures, leveraging DEFSTRUCT :INCLUDE feature have been introduced, rendering the code TYPECASE-able.

MK-DEFSYSTEM is old, but it works. It is quirky but it works (at least for the two or three known users - which, in 2026, is already a big chunk of the Common Lisp users' community). Moreover, it does have, at least in the eye of the beholder, some more user friendly user API, for most use case, especially for plain Common Lisp code.

The current MK-DEFSYSTEM repository is at https://gitlab.common-lisp.net/mantoniotti/mk-defsystem

(*) It is assumed that the reader knows about all the acronyms, tools and systems referred to in the text.


'(cheers)

20251226

Retro (?) Computing in Common Lisp: the CL3270 Library

Come the Winter Holidays and, between too much and a lot of food, I do some hacking and maintainance of my libraries.

Some time ago, I wrote a CL library to set up a server accepting and managing "applications" written for a IBM 3270 terminal.

Why did I do this? Because I like to waste time hacking, and because I got a (insane) fascination with mainframe computing. On top of that, on the Mainframe Enthusiasts Discord channel, Matthew R. Wilson posted a recently updated version of my inspiration, the go3270 GO library.

Of course, I had to fall in the rabbit..., ahem, raise to the occasion, and updated the CL3270 library. This required learing a lot about several things, but rendering the GO code in CL is not difficult, once you undestrand how the GO creators applied Greenspun's Tenth Rule of Programming.

Of course there were some quirks that had to be addressed, but the result is pretty nice.

Screenshots

Here are a couple of screenshots.

"Example 3": The Time Ticker

Yes, it works as advertised.

This is how the server is started from **CL** (Lispworks in this case).

... and this is how the c3270 connects and interacts with the server.

"Example 4": The Mock Database

This example has many panels which fake a database application. The underlying implementation use "transactions", that is, a form of continuations.

Starting the server...

... and two of the screens.

It has been fun developing the library and keeping up with the talented Matthew R. Wilson.

Download the CL3270 library (the development branch is more up to speed) and give it a spin if you like.


'(cheers)

20250721

EMC makes into melpa

Hello

Emacs Make Compile (EMC) made it into MELPA.

You can now install it directly from the Emacs package manager.

Many thanks to the MELPA curators for accomdating an old, annoying, geezer.

Give it a spin; submit bug reports and suggestions.


'(cheers)

20250512

Getting into a rabbit's hole and - maybe - getting out: Emacs Make Compile (EMC)

In the past years I fell form one rabbit's hole into another. For the first time in a rather long time, I feel I am getting out of one.

First of all let me tell you what I produced. I built the "Emacs Make Compile", or "Emacs Master of Ceremonies", package EMC. Soon it will be available in melpa. The EMC package is a wrapper around compile.el that allows you to semi-transparently invoke make or cmake from Emacs. Either on UN*X, MacOS or Windows.

Once you have loaded the emc library in the usual ways, you can just issue the Emacs command emc:run (yes: Common Lisp naming conventions). The command is just the most general one available in EMC; other ones are the more specialized emc:make and emc:cmake. Emacs will then ask you for the necessary bits and pieces to ensure that you can run, say, make. The README file included in the distribution explains what is available in more details.

Where did it all begin?

Why not stick with compile.el? Because it does not have "out-of-the-box" decent defaults under Windows. At least, that was my original excuse.

I fell into this rabbit's hole coming from another one of course.

Some time ago, I started fiddling around with Emacs Dynamic Modules. I wanted to compile them directly from Emacs in order to "simplify" their deployment. Therefore, I set out to write a make function that would hide the compile setup.

Alas, I found out that, because of the necessary setup, invoking the Microsoft Visual Studio toolchain is not easy before you can get to cl and nmake. That was not all that difficult as a problem to solve, but then I made the mistake of learning to cmake. You know; to ensure that the building process was "more portable". The basic machinery for make and nmake worked to also get cmake up and running. But then I made another mistake: I started to want to get EMC to be usable in the "Emacs" way: at a minimum getting interactive commands working. That got me deeper and deeper in the rabbit's hole.

At the bottom of the hole (yep: I got there!)

I found out many things on my way to the bottom. That is, I learned many things about the Emacs Lisp ecosystem and wasted a lot of time in the process. I never was a fast learner. All in all, I think I can now say two things.

  • Making a command, i.e., an interactive function is not trivial, especially if your function has many arguments. Bottom line: your Emacs commands should have *few* arguments. I should have known better.
  • The Emacs widget library is woefully underdocumented (which, of course, brings up the question: why did you want to use it?)

In any case, what I was able to concot is that hitting M-x emc:make does what you expect, assuming you have a Makefile in the directory; if not you will be asked for a "makefile", say stuff.mk to be used as in

make -f stuff.mk
or
nmake /F stuff.mk

Issuing C-u M-x emc:make will ask you for the "makefile", the "source directory", the "build directory", "macros", and "targets".

In what other ways could I have wasted some time? By coming up with a widget-based UI! (See my previous post about DeepSeek and the widget library). The result can be invoked by using the command emc:emc, which pops up the window below.

Getting out of the rabbit hole by popping the stack

I kind of consider EMC finished. I am pleased by the result; it was fun to solve all the problems I encountered, although the code is not exaclty nice or nicely organized. Is EMC useful? Probabiy not so much, but I have the luxury of wasting hacking time. I just hope somebody will like it: please try it out and report bugs and suggestions (the minor mode and associated menu need work for sure, as well as emc:emc).

Having said so, I can now go back to play with Emacs Dynamic Modules, which is where I was coming from. After being satisfied with that, I will be able to climb back up a bit more from the rabbit's hole; that is, I will be able to go back to the magiciel library (which kind of works already). You may ask why I am writing magiciel, but you will have to reach down several levels in the rabbit's hole.

In any case, I finished one thing. It's progress.


'(cheers)

20250424

Emacs Lisp Programming with DeepSeek: A New Widget

The Emacs widget library is useful; alas its guts are ... semi-documented and most of its inner working a bit mysterious. I wanted a column widget where I could insert and remove a few "line-like" widgets. The editable-list widget does not cut it (too many extra things: the INS and DEL buttons) and the group widget is too inflexible.

After too much time trying to understand all the intricacies of the widget library (see my rant in my previous blog post, which perfectly applies in this case) I asked DeepSeek to help me out. The result, the dynamic-group widget (after several iterations and mistakes on part of DeepSeek) is below. It works satisfactorlly, although it could be improved by anybody with a better understanding of the widget library. What is does is to manage a colimn of line-like widgets adding and removing from the end of the :children list. Check the demo-dynamic-group for a test run.

It has been fun. Although I still want a better widget! That's why I am posting this for anybody to pitch in. Any help is welcome.

BTW. There still are some warts in the code. Can you spot them?

;;; -*- Mode: ELisp; lexical-binding: t -*-
;;; emc-dynamic-group.el
;;;
;;; `flycheck-mode' does not like the above.  `flycheck-mode' is wrong.

;;; Code:

(require 'widget)
(require 'wid-edit)


(define-widget 'dynamic-group 'default
  "A container widget that dynamically manages child widgets in a column."
  :format "%v"
  :value ()
  :tag "Dynamic Group"
  :args nil
  
  ;; Core widget methods
  :create (lambda (widget)
            (let ((inhibit-read-only t))
              (widget-put widget :from (point))
              (dolist (child (reverse (widget-get widget :children)))
                (widget-create child))
              (widget-put widget :to (point))))

  :value-get (lambda (widget)
               (mapcar (lambda (child)
                         (widget-apply child :value-get))
                       (widget-get widget :children)))
  
  :value-set (lambda (widget value)
               (widget-put widget :value value))
  
  :value-delete (lambda (widget)
                  (dolist (child (widget-get widget :children))
                    (widget-apply child :value-delete)))
  
  :validate (lambda (widget)
              (let ((children (widget-get widget :children)))
                (catch :invalid
                  (dolist (child children)
                    (when (widget-apply child :validate)
                      (throw :invalid child)))
                  nil)))
  )


(defun dynamic-group-add (widget type &rest args)
  "Add a new widget (of TYPE and ARGS to the WIDGET group."
  (let ((inhibit-read-only t))
    (save-excursion
      (goto-char (widget-get widget :to))
      (let ((child (apply 'widget-create (append (list type) args))))
        (widget-put widget
		    :children (cons child (widget-get widget :children)))
        (widget-put widget
		    :to (point))
        (widget-value-set widget
          (cons (widget-value child) (widget-value widget)))))
    (widget-setup)))

  
(defun dynamic-group-remove (widget)
  "Remove the last widget from the WIDGET group."
  (when-let ((children (widget-get widget :children)))
    (let ((inhibit-read-only t)
          ;; (child (car children))
	  )
      (save-excursion
        (goto-char (widget-get widget :from))
        (delete-region (point) (widget-get widget :to))
        (widget-put widget :children (cdr children))
        (dolist (c (reverse (widget-get widget :children)))
          (widget-create c))
        (widget-put widget :to (point))
        (widget-value-set widget
			  (mapcar 'widget-value
				  (widget-get widget :children)))
        (widget-setup)))))

  
(defun demo-dynamic-group ()
  "Test the dynamic-group widget."
  (interactive)
  (switch-to-buffer "*Dynamic Group Demo*")
  (kill-all-local-variables)
  (let ((inhibit-read-only t))
    (erase-buffer)

    (widget-insert "* Dynamic Group Demo\n\n")

    ;; Now I create the `dynamic-group'.
    
    (let ((group (widget-create 'dynamic-group)))
      (widget-insert "\n")

      ;; The rest are just two buttons testing the widget's behavior,
      ;; invoking`dynamic-group-add' and `dynamic-group-remove'.
      
      (widget-create
       'push-button
       :notify
       (lambda (&rest _)
         (dynamic-group-add group 'string
			    :format "Text: %v\n"
			    :value (format "Item %d"
					   (1+ (length (widget-get group :children))))))
       "(+) Add Field (Click Anywhere)")
      
      (widget-insert " ")
      
      (widget-create
       'push-button
       :notify (lambda (&rest _)
		 (dynamic-group-remove group))
       "(-) Remove Last")
      
      (widget-insert "\n"))

    ;; Wrap everything up using the `widget-keymap' and `widget-setup'
    ;; functions.
    
    (use-local-map widget-keymap)
    (widget-setup)))


(provide 'emc-dynamic-group)


'(cheers)