crategus / cl-cffi-gtk

cl-cffi-gtk is a Lisp binding to the GTK+ 3 library.
http://www.crategus.com/books/cl-cffi-gtk
145 stars 33 forks source link

Is this an example of using g-signal-emit and multithreading correctly? #89

Closed anranyicheng closed 2 years ago

anranyicheng commented 3 years ago

Hi, my environment is emacs26 + slime + sbcl 2.1.2+ubuntu20.04 , Is this an example of using g-signal-emit and multithreading correctly? code: (defun example-emit-test() (within-main-loop (let* ((window (make-instance 'gtk-window :type :toplevel :title "Example emit" :default-width 230 :border-width 12)) (grid (make-instance 'gtk-grid :orientation :vertical :row-spacing 6 :column-homogeneous t)) (button (make-instance 'gtk-button)) (data nil) (sb-thread-tag nil) (count-sb 0) (count-sb-signal 0))

  (g-signal-connect button "clicked"
                    (lambda (widget )
                      (gdk-threads-add-idle
                       (lambda()
                         (setf (gtk-button-label widget)
                               (princ-to-string data))
                         (incf count-sb-signal)
                         (print (list count-sb count-sb-signal
                                      (equal count-sb count-sb-signal)))
                       +g-source-remove+))))

  (g-signal-connect window "destroy"
                    (lambda (widget)
                      (declare (ignore widget))
                      (sb-thread:terminate-thread sb-thread-tag)
                      (leave-gtk-main)))
  (setf sb-thread-tag
        (sb-thread:make-thread (lambda()
                                   (dotimes (i 50000)
                                     (sleep (* 15 (/ 1 1000.0)))
                                     (incf count-sb)
                                     (setf data i)
                                     (gdk-threads-add-idle
                                      (lambda()
                                        (g-signal-emit button "clicked")
                                        +g-source-remove+))))))
  (gtk-container-add grid button)
  (gtk-container-add window grid)
  (gtk-widget-show-all window))))
anranyicheng commented 3 years ago

;; update the code

(defun example-emit-test() (within-main-loop (let* ((window (make-instance 'gtk-window :type :toplevel :title "Example emit" :default-width 230 :border-width 12)) (grid (make-instance 'gtk-grid :orientation :vertical :row-spacing 6 :column-homogeneous t)) (button (make-instance 'gtk-button)) (datas nil) (thread-tag nil) (thread-mutex (sb-thread:make-mutex :name "mutex")) (count-sb 0) (count-sb-signal 0))

  (g-signal-connect button "clicked"
                    (lambda (widget )
                      (sb-thread:with-mutex (thread-mutex)
                        (gdk-threads-add-idle
                         (lambda()
                           (setf (gtk-button-label widget)
                                 (princ-to-string datas))
                           (incf count-sb-signal)
                           ;; (print (list count-sb count-sb-signal
                           ;;             (equal count-sb count-sb-signal)))
                           +g-source-remove+)))))

  (g-signal-connect window "destroy"
                    (lambda (widget)
                      (declare (ignore widget))
                      (when (sb-thread:thread-alive-p thread-tag)
                        (sb-thread:terminate-thread thread-tag))
                      (leave-gtk-main)))
  (setf thread-tag
        (sb-thread:make-thread (lambda()
                                 (dotimes (i 50000)
                                   (sleep 0.001)
                                   (sb-thread:with-mutex (thread-mutex)
                                     (incf count-sb)
                                     (setf datas i)
                                     (gdk-threads-add-idle
                                      (lambda()
                                        (g-signal-emit button "clicked")
                                        +g-source-remove+)))))))

  (gtk-container-add grid button)
  (gtk-container-add window grid)
  (gtk-widget-show-all window))))
Ferada commented 3 years ago

@anranyicheng looks fine, you might want to use bordeaux-threads instead of the SBCL-specific functions (as cl-cffi-gtk does as well), but otherwise it looks fine from the threading perspective. Note that you'd probably not use the signals this way, but I guess it's just an example, isn't it. Also it's probably nicer to have a stop condition in the thread loop rather than outright killing it.