aboutsummaryrefslogtreecommitdiffstats
path: root/src/wait-group.lisp
blob: 954f622ceffda29f4ab530aadc6bf4e1b538d56c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
;;;; Wait group provides a way to block waiting for jobs to finish.

;;; Copyright (c) 2021  Teddy Wing
;;;
;;; This Source Code Form is subject to the terms of the Mozilla Public
;;; License, v. 2.0. If a copy of the MPL was not distributed with this
;;; file, You can obtain one at https://mozilla.org/MPL/2.0/.

;;; Example:
;;;
;;; The following initialises a WebSocket client, sends a message, and waits
;;; for a response.
;;;
;;; (defvar *client* (wsd:make-client "ws://localhost:5555/"))
;;; (defvar *wg* (wait-group:make-wait-group))
;;;
;;; (wsd:start-connection *client*)
;;;
;;; (wsd:on :message *client* #'(lambda (message)
;;;                               (format t "Received: ~a~%" message)
;;;                               (wait-group:done *wg*))
;;;
;;; (wsd:send *client* "Sending")
;;; (wait-group:add *wg*)
;;;
;;; (wait-group:wait *wg*)
;;;
;;; (wsd:close-connection *client*)

(in-package :wait-group)

(defclass wait-group ()
  ((counter
     :initform 0
     :accessor counter
     :documentation "Count of jobs to wait for."))

  (:documentation "Block waiting for jobs to finish."))

(defmethod print-object ((object wait-group) stream)
  (print-unreadable-object (object stream :type t)
    (with-slots (counter) object
      (format stream ":counter ~s" counter))))

(defun make-wait-group ()
  "Make a wait-group instance."
  (make-instance 'wait-group))

(defgeneric add (wait-group &optional amount)
  (:documentation "Track a new job in the group."))

(defmethod add ((wait-group wait-group) &optional (amount 1))
  (incf (counter wait-group) amount))

(defgeneric done (wait-group)
  (:documentation "Stop tracking a job in the group."))

(defmethod done ((wait-group wait-group))
  (decf (counter wait-group)))

(defgeneric wait (wait-group)
  (:documentation "Block waiting for tracked jobs to finish."))

(defmethod wait ((wait-group wait-group))
  (loop until (<= (counter wait-group) 0)))