trivial-monitored-thread

2019-03-07

Trivial Monitored Thread Manual

[in package TRIVIAL-MONITORED-THREAD]

pipeline status Quicklisp

Description

Every modern application relies on threading, but keeping a eye on every thread is cumbersome and error prone. Trivial Monitored Thread offers a very simple (aka trivial) way of spawning threads and being informed when one any of them crash and die.

Installing trivial-monitored-thread

This project is available in the latest QuickLisp distribution, so installing it is reduced to calling:

(ql:quickload :trivial-monitored-thread)

Working Example

The following code demonstrates the use-case for this library.

Note: The sequence '=>' indicates the result from evaluating the previous expression.

(trivial-monitored-thread:start-thread-monitor)

(trivial-monitored-thread:register-on-dead-thread 
  #'(lambda (thread-id thread-args restart-counter max-restarts will-restart-p)
      (declare (ignore thread-args restart-counter max-restarts will-restart-p))
      (log:warn "Thread ~a just died" thread-id)))

(trivial-monitored-thread:make-monitored-thread (:name "Heartbeat-Monitoring-Thread" :sleep-duration 1 :max-restarts 5)
            (sleep 15))
=> 1

;; After some seconds:
=> Thread 1 just died


;; Other examples
(setf *listener-thread-id*
      (trivial-monitored-thread:make-monitored-thread (:name "Listener-Thread" :sleep-duration 0.01 :max-restarts 5)
    (multiple-value-bind (data length remote-host remove-port)
        (usocket:socket-receive *udp-socket* *message-buffer* 2048)
      (receive-message data
               length
               (if (integerp remote-host)
                   (usocket:integer-to-octet-buffer remote-host (make-array 4) 4)
                   remote-host)
               remove-port))))

(setf *heartbeat-monitoring-thread-id*
      (trivial-monitored-thread:make-monitored-thread (:name "Heartbeat-Monitoring-Thread" :sleep-duration 5 :max-restarts 5)
    (update-device-heartbeat-status)))

Exported Symbols

  • [function] START-THREAD-MONITOR

    Initialize the underlying engine for monitoring threads.
    This function MUST be called before any other function from this namespace, except register-on-dead-thread.

  • [function] STOP-THREAD-MONITOR &KEY (KILL-ALL NIL)

    Stops the thread monitor. Any thread that is not also stopped by (:kill-all t) will continue unmonitored with potentially unpredictable consequences.
    kill-all - stop all monitored threads before exiting. Might kill threads that take too long (> 3 seconds) to finish.

  • [function] REGISTER-ON-DEAD-THREAD FN

    Set the function fn to be called when a monitored thread dies. The function must implement following lambda-list: (thread-id thread-args restart-counter max-restarts will-restart-p).

  • [macro] MAKE-MONITORED-THREAD (&KEY NAME SLEEP-DURATION (MAX-RESTARTS) ARGS THREAD-INITIALIZATION THREAD-CLEANUP RESTART-INITIALIZATION RESTART-CLEANUP) &BODY BODY

    Define and register a new monitored thread. The body of the thread will be executed in a loop. The thread will be started immediately.
    name - A identifies string for the thread
    sleep-duration - Define the time duration to yield between iterations (this will be cut to a maximum of 1 second)
    max-restarts - Number of times this thread should be restarted
    args - freely definable payload to be carried to the 'on-dead-thread' function
    thread-initialization - Code to be executed once before first thread start
    thread-cleanup - Code to be executed after last thread stop
    restart-initialization - Code to be executed before each thread restart
    restart-cleanup - Code to be executed after last thread restart
    body - Code to be executed repeatedly (this must not block)

  • [function] STOP-THREAD THREAD-ID

    Given the valid id of a monitored thread request it to shutdown.
    thread-id - The id of the monitored thread

  • [function] JOIN-THREAD THREAD-ID

    Given the valid id of a monitored thread wait until it finishes.
    thread-id - The id of the monitored thread

License Information

This library is released under the MIT License. Please refer to the LICENSE to get the full licensing text.

Contributing to this project

Please refer to the CONTRIBUTING document for more information.