NextPrevUpTopContentsIndex

6.3.3.1 Buffer locking

Each buffer contains a lock that is used to prevent more than one thread from modifying the text, text properties or points within the buffer simultaneously. All of the exported editor functions (editor:insert-string, editor:move-point etc) claim this lock implicitly and are therefore atomic with respect to other such functions.

In situations where you want to make several changes as one atomic operation, use one of the macros editor:with-buffer-locked or editor:with-point-locked to lock the buffer for the duration of the operation. For example, if you want to delete the next character and replace it by a space:

(editor:with-buffer-locked ((editor:current-buffer))
  (editor:delete-next-character-command nil)
  (editor:insert-character (editor:current-point)
                           #\Space))

In addition, you sometimes want to examine the text in a buffer without changing it, but ensure that no other thread can modify it in the meantime. This can be achieved by locking the buffer using editor:with-buffer-locked or editor:with-point-locked and passing the for-modification argument as nil . For example, if you are computing the beginning and end of some portion of the text in a buffer and then performing some operation on that text, you may want to lock the buffer to ensure that no other threads can modify the text while your are processing it.

editor:with-buffer-locked

Macro

editor:with-buffer-locked (buffer
                           &key for-modification
                                check-file-modification
                                block-interrupts
)
  &body body
 => values

Evaluates body while holding the lock in buffer . At most one thread can lock a buffer at a time and the macro waits until it can claim the lock.

If for-modification is non- nil (the default), the contents of buffer can be modified by body . If for-modification is nil , the contents of buffer cannot be modified until body returns and trying to do so from within body will signal an error. If the buffer is read-only and for-modification is non- nil , then an editor:editor-error is signalled

The macro editor:with-buffer-locked can be used recursively, but if the outermost use passed nil as the value of for-modification , then inner uses cannot pass non- nil as the value of for-modification .

If check-file-modification is non- nil (the default) and the buffer is associated with a file and has not already been modified, then the modification time of the file is compared to the time that the file was last read. If the file is newer than the buffer, then the user is asked if they want to re-read the file into the buffer, and if they do then the file is re-read and the operations aborts. Otherwise, there is no check for the file being newer than the buffer.

If block-interrupts is non- nil , the body is evaluated with interrupts blocked. This is useful if the buffer may be modified by an interrupt function, or some interrupt function may end up waiting for another thread that may wait for the buffer lock, which would cause a deadlock. The default is not to block interrupts.

Note that using a non- nil value for block-interrupts is not the same as using the without-interrupts or without-preemption macros. It just stops the current thread from calling interrupt functions, so other threads might run while the body is being evaluated.

The values returned are those of body .

editor:with-point-locked

Macro

editor:with-point-locked (point
                          &key for-modification
                               check-file-modification
                               block-interrupts
                               errorp
)
  &body body
  =>  values

Evaluates body while holding the lock in the buffer that is associated with point . In addition, the macro checks that point is valid and this check is atomic with respect to calls to the function editor:delete-point. The values of for-modification , check-file-modification and block-interrupts have the same meanings as for editor:with-buffer-locked.

The value of errorp determines the behavior when point is not valid. If errorp is non- nil , an error is signaled, otherwise nil is returned without evaluating body . The point may be invalid because it does not reference any buffer (that is, it has been deleted), or because its buffer was changed by another thread while the current thread was attempting to lock the buffer.

The values returned are those of body , or nil when errorp is nil and point is not valid.


LispWorks Editor User Guide (Macintosh version) - 14 Mar 2008

NextPrevUpTopContentsIndex