4
votes

I am trying to add a new slot to the lock class. This is useful because I have a lot of locks in a hierarchy and if I store the parent lock for every lock it becomes easier to detect problems while debugging.

Unfortunately, this apparently can't be done with the ensure-class function. I can add slots to 'process, but not to 'lock, because it is listed as a built-in-class. See my earlier question here for how to do it for 'process: lisp, CLOS: adding a slot to the process class

Do you know how to solve this problem? If it is not possible, the only alternative I can think of is storing the hierarchical relation of locks in a hash-table, but since some of the locks are created at runtime and in different processes, I would have to add yet another lock just to access the hashtable that stores metadata on the locks.

This strikes me as terribly inefficient. Do you have a better idea?

edit: for clarification, I am using Clozure Common Lisp.

2

2 Answers

3
votes

You can specify the metaclass using the :metaclass class option in a defclass form.

CL-USER> (defclass hierarchical-lock (lock)
           ((parent :initarg :parent :reader parent))
           (:metaclass built-in-class))
#<BUILT-IN-CLASS HIERARCHICAL-LOCK>

However, even though you can do that and get the class, I'm not sure how you would go about instantiating it. Trying to use make-instance fails:

CL-USER> (make-instance 'hierarchical-lock)

; There is no applicable method for the generic function:
;   #<STANDARD-GENERIC-FUNCTION MAKE-INSTANCE #x30200002676F>
; when called with arguments:
;   (#<BUILT-IN-CLASS HIERARCHICAL-LOCK>)
;    [Condition of type SIMPLE-ERROR]

make-lock is implemented in l0-aprims.lisp as

(defun make-lock (&optional name)
  "Create and return a lock object, which can be used for synchronization
between threads."
  (%make-lock (%make-recursive-lock-ptr) name))

You can keep following the implementation of %make-lock until you get to the low level implementation details, but it's clear that locks are not obtained the same way that typical CLOS instances are.

In addition to Rainer Joswig's suggestion in a comment on this answer that you let the CCL developers know that you would appreciate locks being CLOS objects, you can always use some aggregation and define your own hierarchical-lock that has slot for its primitive lock and a slot for parent. By the magic of generic functions, you can implement methods on the generic functions that work with locks so that your hierarchical-lock behaves like a built in lock. (This presumes that the lock API is defined in terms of generic functions.)

0
votes

You could use a subclass that has such a slot.

(defclass hierarchical-lock (lock)
  ((parent :initarg :parent :reader parent)))