LispWorks Editor User Guide > 6 Advanced Features > 6.3 Programming the editor > 6.3.3 Buffers

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 status of the lock can be changed to for-modification (see editor:change-buffer-lock-for-modification). If the buffer is read-only, an editor:editor-error occurs if for-modification is t .

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 , unless editor:change-buffer-lock-for-modification is used to change the lock status.

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.

editor:change-buffer-lock-for-modification

Function

editor:change-buffer-lock-for-modification buffer &key check-file-modification force-modification => result

Changes the status of the lock in the buffer buffer to allow modification of the text. buffer must already be locked for non-modification by the current thread (that is, it must be dynamically within a editor:with-buffer-locked or editor:with-point-locked form with for-modification nil ).

buffer

An editor buffer.

check-file-modification

A boolean.

force-modification

A boolean.

result

:buffer-not-locked , :buffer-out-of-date or :buffer-not-writable .

If check-file-modification is non-nil, the same test as described for editor:with-buffer-locked is performed, and if the file has been modified then :buffer-out-of-date is returned without changing anything (it does not prompt the user to re-read the file).

The default value of check-file-modification is t .

force-modification controls what happens if the buffer is read-only. If force-modification is nil , the function returns :buffer-not-writable and does nothing. If it is non-nil, the status is changed. The buffer remains read-only.

result is nil if the status of the locking was changed to for-modification , or if the status of the buffer lock was already for-modification . Otherwise, result is a keyword indicating why the status could not be changed. When result is non-nil, the status of the locking remains unchanged.

The returned value can be be one of:

:buffer-not-locked

The buffer is not locked by the current thread.

:buffer-not-writable

The buffer is not writable, and force-modification is nil .

:buffer-out-of-date

The file that is associated with the buffer was modified after it was read into the editor, the buffer is not modified, and check-file-modification is non-nil.


LispWorks Editor User Guide (Unix version) - 22 Dec 2009

NextPrevUpTopContentsIndex