




 
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 (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 (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
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
).
An editor buffer.
: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:
The buffer is not locked by the current thread.
The buffer is not writable, and 
force-modification
 is 
nil
.
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.