impl-genera.lisp - clic - Clic is an command line interactive client for gopher written in Common LISP (HTM) git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/ (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (DIR) README (DIR) LICENSE --- impl-genera.lisp (4041B) --- 1 ;;;; -*- Mode: LISP; Syntax: Ansi-Common-Lisp; Package: BORDEAUX-THREADS; Base: 10; -*- 2 3 #| 4 Distributed under the MIT license (see LICENSE file) 5 |# 6 7 (in-package #:bordeaux-threads) 8 9 (deftype thread () 10 'process:process) 11 12 ;;; Thread Creation 13 14 (defun %make-thread (function name) 15 (process:process-run-function name function)) 16 17 (defun current-thread () 18 scl:*current-process*) 19 20 (defun threadp (object) 21 (process:process-p object)) 22 23 (defun thread-name (thread) 24 (process:process-name thread)) 25 26 ;;; Resource contention: locks and recursive locks 27 28 (defstruct (lock (:constructor make-lock-internal)) 29 lock 30 lock-argument) 31 32 (defun make-lock (&optional name) 33 (let ((lock (process:make-lock (or name "Anonymous lock")))) 34 (make-lock-internal :lock lock 35 :lock-argument nil))) 36 37 (defun acquire-lock (lock &optional (wait-p t)) 38 (check-type lock lock) 39 (setf (lock-lock-argument lock) (process:make-lock-argument (lock-lock lock))) 40 (if wait-p 41 (process:lock (lock-lock lock) (lock-lock-argument lock)) 42 (process:with-no-other-processes 43 (when (process:lock-lockable-p (lock-lock lock)) 44 (process:lock (lock-lock lock) (lock-lock-argument lock)))))) 45 46 (defun release-lock (lock) 47 (check-type lock lock) 48 (process:unlock (lock-lock lock) (scl:shiftf (lock-lock-argument lock) nil))) 49 50 (defmacro with-lock-held ((place) &body body) 51 `(process:with-lock ((lock-lock ,place)) 52 ,@body)) 53 54 (defstruct (recursive-lock (:constructor make-recursive-lock-internal)) 55 lock 56 lock-arguments) 57 58 (defun make-recursive-lock (&optional name) 59 (make-recursive-lock-internal :lock (process:make-lock (or name "Anonymous recursive lock") 60 :recursive t) 61 :lock-arguments nil)) 62 63 (defun acquire-recursive-lock (lock) 64 (check-type lock recursive-lock) 65 (process:lock (recursive-lock-lock lock) 66 (car (push (process:make-lock-argument (recursive-lock-lock lock)) 67 (recursive-lock-lock-arguments lock))))) 68 69 (defun release-recursive-lock (lock) 70 (check-type lock recursive-lock) 71 (process:unlock (recursive-lock-lock lock) (pop (recursive-lock-lock-arguments lock)))) 72 73 (defmacro with-recursive-lock-held ((place) &body body) 74 `(process:with-lock ((recursive-lock-lock ,place)) 75 ,@body)) 76 77 ;;; Resource contention: condition variables 78 79 (eval-when (:compile-toplevel :load-toplevel :execute) 80 (defstruct (condition-variable (:constructor %make-condition-variable)) 81 name 82 (waiters nil)) 83 ) 84 85 (defun make-condition-variable (&key name) 86 (%make-condition-variable :name name)) 87 88 (defun condition-wait (condition-variable lock) 89 (check-type condition-variable condition-variable) 90 (check-type lock lock) 91 (process:with-no-other-processes 92 (let ((waiter (cons scl:*current-process* nil))) 93 (process:atomic-updatef (condition-variable-waiters condition-variable) 94 #'(lambda (waiters) 95 (append waiters (scl:ncons waiter)))) 96 (process:without-lock ((lock-lock lock)) 97 (process:process-block (format nil "Waiting~@[ on ~A~]" 98 (condition-variable-name condition-variable)) 99 #'(lambda (waiter) 100 (not (null (cdr waiter)))) 101 waiter))))) 102 103 (defun condition-notify (condition-variable) 104 (check-type condition-variable condition-variable) 105 (let ((waiter (process:atomic-pop (condition-variable-waiters condition-variable)))) 106 (when waiter 107 (setf (cdr waiter) t) 108 (process:wakeup (car waiter)))) 109 (values)) 110 111 (defun thread-yield () 112 (scl:process-allow-schedule)) 113 114 ;;; Introspection/debugging 115 116 (defun all-threads () 117 process:*all-processes*) 118 119 (defun interrupt-thread (thread function &rest args) 120 (declare (dynamic-extent args)) 121 (apply #'process:process-interrupt thread function args)) 122 123 (defun destroy-thread (thread) 124 (signal-error-if-current-thread thread) 125 (process:process-kill thread :without-aborts :force)) 126 127 (defun thread-alive-p (thread) 128 (process:process-active-p thread)) 129 130 (defun join-thread (thread) 131 (process:process-wait (format nil "Join ~S" thread) 132 #'(lambda (thread) 133 (not (process:process-active-p thread))) 134 thread)) 135 136 (mark-supported)