aboutsummaryrefslogtreecommitdiff
path: root/guile/starlet/state.scm
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2021-05-10 20:54:53 +0200
committerThomas White <taw@physics.org>2021-05-10 20:56:02 +0200
commit1fa25deedd48440dd17521f5e7d41a3e69bd3743 (patch)
tree6c1a7820c0fcf9c74253d2e3a28c6c8a78e538a5 /guile/starlet/state.scm
parent0acf5d8958fae9ef959b9bae4917c656081189ef (diff)
Run cues as single atomic operations
This avoids a potential situation where one parameter of a fixture is reconfigured before another, which could (in theory) lead to flickering of lights.
Diffstat (limited to 'guile/starlet/state.scm')
-rw-r--r--guile/starlet/state.scm20
1 files changed, 19 insertions, 1 deletions
diff --git a/guile/starlet/state.scm b/guile/starlet/state.scm
index 13888e8..a889d0c 100644
--- a/guile/starlet/state.scm
+++ b/guile/starlet/state.scm
@@ -48,7 +48,8 @@
blackout
sel
selection-hook
- value->number))
+ value->number
+ atomically-overlay-state!))
;; A "state" is an atomically-updating container for an immutable
@@ -231,6 +232,23 @@ pre-existing contents."
(state-for-each at state))
+(define (atomically-overlay-state! state newbits)
+ "Apply 'newbits' within 'state', as a single atomic operation."
+ (let* ((old-ht (atomic-box-ref (get-ht-box state)))
+ (new-ht (copy-hash-table old-ht)))
+ (state-for-each (lambda (fix attr val)
+ (hash-set! new-ht
+ (cons fix attr)
+ val))
+ newbits)
+ (unless (eq? (atomic-box-compare-and-swap!
+ (get-ht-box state)
+ old-ht
+ new-ht)
+ old-ht)
+ (atomically-overlay-state! state newbits)))) ;; Try again
+
+
(define current-state (make-parameter programmer-state))