All Manuals > LispWorks® User Guide and Reference Manual > 37 The HCL Package

with-ensuring-gethash Macro


A thread-safe way to get a value from a hash-table, adding a value if the key is not present. Allows a complicated form to construct the new value.




with-ensuring-gethash key hash-table &key constructor constructor-form in-lock-constructor in-lock-constructor-form => result

A Lisp object.
A function designator for a function of no arguments, or nil.
A Lisp form, or nil.
A function designator for a function of one argument, or nil.
A Lisp form, or nil.
A Lisp object.

The macro with-ensuring-gethash gets the value for the key key from the hash table hash-table, and if this fails constructs a new value, puts it in the table and returns it. with-ensuring-gethash does this in a thread-safe way, which means that all threads calling it with the same key and hash-table return the same value (as long as nothing removes it from the table).

Only one of constructor-form or constructor can be non-nil. When key is not found, constructor-form or constructor is used to construct the new value. If constructor is non-nil, it is called without arguments. If constructor-form is non-nil, it is executed. If both are nil, the new value is nil unless in-lock-constructor or in-lock-constructor-form construct it. The call to constructor or execution of constructor-form is done without any lock. The result may be discarded if, by the time it returned, there is a match for key in the table.

Only one of in-lock-constructor or in-lock-constructor-form can be non-nil, which is used when key is not found after constructing the new value. If in-lock-constructor-form is non-nil, it is executed and the result is the actual value to use (the result of the construction by constructor-form or constructor is ignored). If in-lock-constructor is non-nil, it is called with the result of the construction by constructor-form or constructor, and the result is used as the new value. In either case, the call or execution is done with hash-table locked, and the result is guaranteed to be put in hash-table and returned. If both in-lock-constructor and in-lock-constructor-form are nil, the result of the construction is used.

  1. When both constructor-form and in-lock-constructor-form are nil, gethash-ensuring is probably simpler and better.
  2. In most situations, doing all the construction out of the lock is better than doing anything inside the lock. It means that sometimes the work that was done in the constructions is wasted because another thread put the value in the table, but that overhead is normally less significant than the overhead of holding the lock for longer, with the associated potential deadlocks.
See also

19.5 Modifying a hash table with multiprocessing

LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:35