среда, 24 августа 2011 г.

Пакет cl-event-callback

       Оформил код в виде пакета. Но пока есть минус - так как использую потоки sbcl, то он работает только под ним, поэтому собираюсь перевести с sbcl-threads на bordeaux-threads.  Ссылка на проект: github.

Пакет обработки событий на lisp

     Мне понадобился модуль, поддерживающий обработку событий, но я ничего не нашел(возможно плохо искал). Поэтому решил написать пакет, решающий эту задачу, исходники которого находятся на github
     Итак, реализация  похожа на сигнал-слотовую модель(например, как в Qt), то есть при определенном событии происходит подписанное на него действие. Пока реализовано:
  1. Три состояние события - событие произошло(:trig),  сброс в исходное состояние (:not-trig) и выполнение подписанного  на событие действия один раз (:trig-stop)  
  2. Добавление/удаление именованного события и его обработчика
  3. Запуск и останов событийной модели
  4. Автоматическое и ручное управление состояниями события

Пример использования:
1. Автоматическое управление


(in-package #:cl-event-callback)

;Объявим переменную, при изменении которой будет присходить событие
(defparameter *a* 1)

; Данная функция будет выполняться при получении события
(defun test () (print "test"))

;Создаем именнованное событие. В данном случае, если *a* больше 3, то 
;будет вызываться функция test.
(defun new-event ()
       (connect '(test) 'test-event '(> *a* 3)))

;Функция для изменения состояния переменной *a*
(defun event-change (var)
       (setq *a* var))

;Удаляем именнованое событие
(defun del-test-event ()
       (disconnect 'test-event))

(defun main ()
       (new-event)		; <- Создаем событие
       (thread-run-callbacks)   ; <- Отслеживаем изменения состояния
       (event-change 5)         ; <- Изменяем переменную *a*, чем вызываем событие
       (sleep 3)
       (event-change 1)         ; <- Возвращаем состояние *a*
       (del-test-event)         ; <- Удаляем событие
       (thread-stop-callbacks))

2. Ручное управление


(in-package #:cl-event-callback)

;Объявим функции для тестов
(defun test1 () (print "test1"))

(defun test2 () (print "test2"))

;Создадим события
(defun create-events()
       (connect '(test1) 'test-one)
       (connect '(test2) 'test-two))

;Функция удаления событий
(defun delete-events ()
       (disconnect 'test-one)
       (disconnect 'test-two))


(defun main ()
       (create-events)			     ; <- Создаем события
       (thread-run-callbacks)                ; <- Отслеживаем изменения сотояния событий
       (set-event-state 'test-one :trig)     ; <- Вызываем событие вручную
       (set-event-state 'test-two :trig-stop); <- Функция, подписанная на это событие вызовется один раз, после чего состояние события переведется в :not-trig
       (sleep 2)
       (set-event-state 'test-one :not-trig) ; <- Это событие переводим в состояние :not-trig
       (delete-events)
       (thread-stop-callbacks))
На текущий момент необходимо доделать следующее:
  • Оформить код в виде пакета
  • Добавить потоко-безопасность