7
votes

Short Question:

Given Clojure's concurrency model, how do I ensure that all LWJGL OpenGL Update functions are called from the same thread?

Long Question

After a long and glorious battle, Using lwjgl in Leiningen/Clojure , I now have LWJGL + Leiningen + Clojure working together.

However, according to LWJGL documentation, it appears that there OpenGL client commands have thread local state -- and if I call OpenGL commands from different threads, Bad Things (TM) can happen.

Thus, my question: what is the correct way, within Clojure, to set up something like Swing Threads (but I can't use Swing Threads / have to setup my own) so that:

(1) there is a single main thread that is in charge of all OpenGL calls

(2) other threads do some type of communication with this main thread to coordinate OpenGL calls

My Background

I'm familiar with threading in C/C++. I'm familiar with Clojure's agent/atom/ref model. However, I'm not familiar with "manual" concurrency/threading in Clojure.

Thanks!

1

1 Answers

5
votes

The usual way I would design this would be just to have a single thread responsible for all rendering. By doing this you avoid the need for other threads to "issue OpenGL calls".

Of course, you still need a way to get information to the rendering thread, but that can be handled with Clojure's standard concurrency techniques. For example, if your world state is immutable you could just use an atom for state updates, and have the rendering thread just perform rendering using the latest world state stored in the atom:

  (def world-state (atom (initial-world-state)))

  ;; in rendering thread
  .....
  (loop []
    (render-world @world-state) ; all OpenGL calls happen in this function!!
    (other-stuff)
    (if (still-running) (recur)))

  ;; in other thread responsible for updating world
  (loop []
    (swap! world-state update-world-function)
    (other-stuff)
    (sleep-if-needed)
    (if (still-running) (recur)))