(in-package :bordeaux-threads-2) (defmacro while-loop (test &body body) `(loop :while ,test :do ,@body)) ;;;;https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock#Using_a_condition_variable_and_a_mutex ;;;;implementation of a read-writer-lock using a conditional variable and a mutex (defclass reader-writer-lock () ((condition-var :accessor condition-var :initform (make-condition-variable)) (g-lock :accessor g-lock :type lock :initform (make-lock)) (readers-active :accessor readers-active :type integer :initform 0) (writers-waiting :accessor writers-waiting :type integer :initform 0) (active-writer-p :accessor active-writer-p :type boolean :initform nil))) (defun begin-read (reader-writer-lock) (with-accessors ((g g-lock) (ww writers-waiting) (c-var condition-var) (ra readers-active)) reader-writer-lock (with-lock-held (g) (while-loop (> ww 0) (condition-wait c-var *g*)) (incf ra)))) (defun end-read (reader-writer-lock) (with-accessors ((g g-lock) (c-var condition-var) (ra readers-active)) reader-writer-lock (with-lock-held (g) (decf ra) (when (zerop ra) (condition-notify c-var))))) (defun begin-write (reader-writer-lock) (with-accessors ((g g-lock) (ww writers-waiting) (c-var condition-var) (aw active-writer-p)) reader-writer-lock (with-lock-held (g) (incf ww) (while-loop (or (> ww 0) aw) (condition-notify c-var)) (decf ww) (setf aw t)))) (defun end-write (reader-writer-lock) (with-accessors ((g g-lock) (c-var condition-var) (aw active-writer-p)) reader-writer-lock (with-lock-held (g) (setf aw nil) (condition-notify c-var)))) (defmacro read-with-rw-lock ((lock) &body body) `(progn (begin-read ,lock) ,@body (end-read ,lock))) (defmacro write-with-rw-lock ((lock) &body body) `(progn (begin-write ,lock) ,@body (end-write ,lock)))