Napisałem dość prymitywny program testowy (piszę o klasach OpenGL LWJGL z powodów głównie estetycznych i postanowiłem wprowadzić tam wielowątkowość, ponieważ nigdy wcześniej nie napisałem programu współbieżnego). Po zakończeniu programu, zawsze otrzymuję ostrzeżenie: I rzeczywiście pojawia się ostrzeżenie, zanim program przejdzie do funkcji głównej. Przepraszamy za błąd (myślę, że to nie może być mój program w ogóle, ale raczej coś w samej Clojure):Nie można rozwiązać połączenia do invokeStaticMethod?
Reflection warning, NO_SOURCE_PATH:1 - call to invokeStaticMethod can't be resolved.
nie dostanę ostrzeżenia podczas kompilacji choć, co uważam raczej dziwne. W każdym razie, tu jest program:
(ns opengltuts.core
(:import (org.lwjgl.opengl GL11 Display))
(:use opengltuts.opengl)) ;my wrapper
(def world-state (ref {:running true :color [1.0 0.0 0.0 1.0]}))
(defn render-world [state]
(apply glClearColor (:color state))
(glClear GL11/GL_COLOR_BUFFER_BIT)
(Display/update))
(defn render []
(Display/create)
(loop []
(let [world @world-state]
(when (:running world)
(do (render-world world)
(recur)))))
(Display/destroy))
(defn -main []
; without the annotation, I get a warning here too.
(let [render-thread (doto (Thread. ^Runnable render) (.start))]
(Thread/sleep 3000)
(dosync (commute world-state assoc :color [0.0 1.0 0.0 1.0]))
(Thread/sleep 3000)
(dosync (commute world-state assoc :running false))
(.join render-thread)))
To chyba nie jest zbyt idiomatyczne (słyszałem, że w Clojure zwykle nie zaczynaj wątki z new Thread
, ale raczej z agentami czy coś, ale nie w pełni uchwycić, jak to działa), ale myślę, że dla tak krótkiego programu, który nie ma znaczenia.
Jeśli potrzebujesz prostego wątku, możesz użyć 'future' zamiast agenta. tj. '(przyszłość (render))'. Również "Thread/sleep" jest ok, zobacz http://clojuredocs.org/clojure_core/clojure.core/future – noahlz
Czy jesteś pewien, że ostrzeżenie nie pochodzi z 'opengltuts.opengl'? Gdzieś wywołuje się przeciążoną statyczną metodę i nie może ona rozwiązać dokładnego wywołania. Co się dzieje w środowisku wykonawczym, czy generujesz kod w czasie wykonywania? – noahlz
@noahz Nie Nie generuję kodu. A dzieje się tak tylko na końcu programu, kiedy już dawno mam do czynienia z funkcjami OpenGL. Również wykorzystanie przyszłości jest dziwne. Oszczędza mi to trochę kropek, ale teraz potrzebuję tego dziwnego wezwania (shutdown-agentów) na końcu, ponieważ clojure nie może się domyślić, kiedy już czas skończyć. No i oczywiście dereferencja wartości zerowej powodującej efekt uboczny również nie jest odpowiednia dla mnie. Myliłem się z czasem - otrzymuję ostrzeżenie, zanim przejdę do głównej funkcji. – Cubic