;;;;
;;;; threads2.stk       -- A simple thread example
;;;;
;;;; Copyright © 2010-2020 Erick Gallesio - Polytech'Nice-Sophia <eg@unice.fr>
;;;;
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation; either version 2 of the License, or
;;;; (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
;;;; USA.
;;;;
;;;;           Author: Erick Gallesio [eg@unice.fr]
;;;;    Creation date:  1-Aug-2010 18:45 (eg)
;;;;

(when (eq? (%thread-system) 'none)
  (eprintf "Your system does not support threads. Sorry.\n")
  (exit 1))

(define *global-count* 0)
(define *global-mutex* (make-mutex) )   ; used to ensure that each thread
                                        ; alternates correctly
(define (pretty n)
  (cond
    ((< n 10)  (format "  ~a" n))
    ((< n 100) (format " ~a" n))
    (else      (format "~a" n))))


(define (thread-func)
  (let ((name (thread-name (current-thread)))
        (max  50))
    (dotimes (i max)
      (mutex-lock! *global-mutex*)
      (set! *global-count* (+ *global-count* 1))
      (printf "[in ~A: i=~a count=~a]" name (pretty i) (pretty *global-count*))
      (when (= i (- max 1)) (printf " ** Terminated **"))
      (newline)
      (mutex-unlock! *global-mutex*)
      ;; sleep a little to give the oppotunity to anotherthread to grab the mutex
      (sleep 1))))


(define (main argv)
  (let ((thread1 (make-thread thread-func "A"))
        (thread2 (make-thread thread-func "B"))
        (thread3 (make-thread thread-func "C")))
    ; start the threads
    (thread-start! thread1) (thread-start! thread2) (thread-start! thread3)
    ;; Wait the threads finish
    (thread-join! thread1) (thread-join! thread2) (thread-join! thread3)
    ;; Ok all the threads are terminated
    (printf "All the threads are dead. Exit\n")
    0))

