On 2023-06-19 16:20, Andrew Tropin wrote: > * module/ice-9/atomic.scm (atomic-box-update!): New variable. > --- > I was implementing some concurrent code and started to use (ice-9 > atomic), when found out that there is no procedure for updating the > value of the atom using another function. > > IMHO, atomic-box-update! fits well FP paradigm (which is widely used > across guile-based projects) in general and this module in particular > and should be provided out of the box. Made a draft implementation. > LMKWYT. > > module/ice-9/atomic.scm | 14 +++++++++++++- > 1 file changed, 13 insertions(+), 1 deletion(-) > > diff --git a/module/ice-9/atomic.scm b/module/ice-9/atomic.scm > index 2a8af901d..6bfa2e8ee 100644 > --- a/module/ice-9/atomic.scm > +++ b/module/ice-9/atomic.scm > @@ -25,7 +25,8 @@ > atomic-box-ref > atomic-box-set! > atomic-box-swap! > - atomic-box-compare-and-swap!)) > + atomic-box-compare-and-swap! > + atomic-box-update!)) > > (eval-when (expand load eval) > (load-extension (string-append "libguile-" (effective-version)) > @@ -36,3 +37,14 @@ > (add-interesting-primitive! 'atomic-box-set!) > (add-interesting-primitive! 'atomic-box-swap!) > (add-interesting-primitive! 'atomic-box-compare-and-swap!)) > + > +(define (atomic-box-update! box proc . proc-args) > + "Atomically updates value of BOX to (APPLY PROC BOX-VALUE PROC-ARGS), > +returns new value. PROC may be called multiple times, and thus PROC > +should be free of side effects." > + (let loop () > + (let* ((old-value (atomic-box-ref box)) > + (new-value (apply proc old-value proc-args))) > + (if (eq? old-value (atomic-box-compare-and-swap! box old-value new-value)) > + new-value > + (loop))))) Found one more example of the usage of this pattern in fibers library. Those lines by Christine Lemmer-Webber: https://github.com/wingo/fibers/blob/581319ff13b97f2bb51dff713524aad696c5d52b/fibers/counter.scm#L37 -- Best regards, Andrew Tropin