|Version 1 (modified by rme, 6 years ago) (diff)|
As a debugging aid, many lisp objects can be watched so that a condition will be signaled when the object is about to be written to.
WATCH &optional object [function]
The WATCH function arranges for the specified object to be monitored for writes. This is done via the system's memory-management hardware, so read-only access to the object runs at full speed.
When any write to the object is attempted, the condition WRITE-TO-WATCHED-OBJECT will be signaled.
WATCH knows about a few complicated objects (hash tables, fancy arrays, CLOS standard instances), and gives them special treatment:
hash tables: the underlying hash table vector will be watched
arrays: the underlying data vector will be watched
standard instances: the slot vector will be watched
If you don't want WATCH to do this for you, call PRIMITIVE-WATCH instead.
WATCH can monitor cons cells, but in order to watch a chain of cons cells, they have to be watched individually. Each cons cell will take up its own virtual memory page, so it's only really feasible to watch short lists.
When called with no arguments, WATCH returns a list of objects currently being watched. These objects will always be the underlying data vectors, and not complicated user-level objects like hash tables, etc.
UNWATCH object [function]
The UNWATCH function ensures that the specified object is in normal, non-monitored memory. If the object is not currently being watched, UNWATCH does nothing and returns NIL. Otherwise, the newly unwatched object is returned.
A note on thread-safety: avoid unwatching an object when a WRITE-TO-WATCHED-OBJECT condition might be being handled in some other thread. The lisp tries to detect when it would be unsafe to unwatch an object; UNWATCH will return NIL and not unwatch the object in such a case. Nevertheless, there may be subtle race conditions lurking here.
WATCHED-OBJECT-AND-LOCATION condition [function]
When passed a WRITE-TO-WATCHED-OBJECT condition, this function returns, as multiple values, the "user-level" object that is the destination of the write and the "location" (index, key, or slot name) of the write within the object, if that can be determined.
This condition is signaled when a watched object is written to. There are two slots of interest: the "object" slot and the "location" slot.
The object slot is the "user-level" object that was written. That is, if the user did (watch some-hash-table), then the object slot will contain some-hash-table, even though the actual object that was written to is the underlying hash-table-vector.
The contents of the location slot differs according to what is in the object slot. In the case of arrays, it will be the row-major index of the element that was about to be written. For hash tables, location will contain the hash table key, or #<Unbound> if the key can't be determined (as might happen if you are adding a new key-value pair to the hash table). For CLOS objects, location will contain the slot name. If object is a cons cell, location will be either the actual car or cdr of the cons cell, depending on which half of the cons cell was written to. If location is NIL, the location could not be determined.