Re: agents, await and Swing thread
Just a quick thought (and before I've had my coffee no less!), but I think what I'd do is replace the boolean *end-search* with a *search-state* var that could be either :idle, :running or :stopping. Then in search-stops, just set *search-state* to :stopping -- you don't need to actually wait for the agents to finish, you just need to know that the current condition is waiting for the search to end so you don't quit the app or start a new search until the cleanup is finished. Then when you do hit some task that needs to wait until the agents are done, you can go ahead and await the agents (i.e. if you're quitting and it doesn't matter if there's a hang), or spawn a thread that will await the agents before starting the new search. You could also run a cleanup thread that would check the state of your search agents and set the *search-state* from :stopping back to :idle once all the search agents had finished. Mark -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: agents, await and Swing thread
On Sep 6, 5:48 pm, K. kotot...@gmail.com wrote: Hello, I've got a concurrency problem and it's not really clear to me how to solve it. I have a Swing GUI doing a search in background with agents and the results are displayed one after the other, also in background. Here is, largely simplified, how I do it: (defvar- *end-search* (atom false)) ;; this will be called from a Swing listener, when the user clicks on the 'Search' button ;; so this is called from the swing thread (defn on-search-begins [] ;; (reset! *end-search* false) (send *search-agent* do-search)) (defn do-search [state] ;; while (deref *end-search*) is false and while there are results for the search, do (do-swing ;; we are not in a swing thread within the agent, so we need to call do-swing (display-result swingview result) ;; search ends? yes, then (do-swing (display-search-is-ended swingview))) When the user clicks on the 'Stop' button, the following function will be called from the Swing thread: (defn search-stops [] (reset! *end-search* true) ;; NOW we need to wait for the agents to stop (await *search-agent*)) The problem is: the call to await results in a deadlock. I suspect this is because the call to await is made from the Swing thread, and once the value of the *end-search* atom is set to true the agent try to access the Swing thread but can't because the thread is waiting. What solution would you propose to solve this problem? My 2 cents: move the processing of user actions off the Swing thread (the EDT) and leave there only the stuff that interacts with the GUI (which I suppose is what your do-swing already does). Even without a deadlock it's bad practice to make long blocking calls in the EDT because that will freeze the GUI. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: agents, await and Swing thread
Hi, Several questions / thoughts: 2010/9/6 K. kotot...@gmail.com: Hello, I've got a concurrency problem and it's not really clear to me how to solve it. I have a Swing GUI doing a search in background with agents and the results are displayed one after the other, also in background. Here is, largely simplified, how I do it: (defvar- *end-search* (atom false)) ;; this will be called from a Swing listener, when the user clicks on the 'Search' button ;; so this is called from the swing thread (defn on-search-begins [] ;; (reset! *end-search* false) (send *search-agent* do-search)) Mmm, an agent without state always rings a bell in my head. There's a smell of abuse of the agent concept here. Aren't you just using it for its commodity to start a new thread. If so, you could as well just use a future, for example, and then you'll have simpler semantics. Or you could just (Thread/start) your fn (but then you introduce java clearly in the code, so maybe just using a future is the right balance). Agents carry with them a lot of semantics, so readers of you code may have unsatisfied expectations on your usage ... until they get it and think: ok it's just an 'agent abuse'. (defn do-search [state] ;; while (deref *end-search*) is false and while there are results for the search, do (do-swing ;; we are not in a swing thread within the agent, so we need to call do-swing (display-result swingview result) As said by others, I suppose result is computed outside the do-swing form so that the Swing thread is blocked as few as possible ;; search ends? yes, then (do-swing (display-search-is-ended swingview))) When the user clicks on the 'Stop' button, the following function will be called from the Swing thread: (defn search-stops [] (reset! *end-search* true) ;; NOW we need to wait for the agents to stop (await *search-agent*)) It would be interested to know in the first place why you have to add this call to await at all ? Anyway, to just answer your question, maybe your (display-search-is-ended swingview) call could be placed right after the (await) call, but in another thread ? As in (defn search-stops [] (reset! *end-search* true) (future (await *search-agent*) (display-search-is-ended swingview))) But all in all, I'm not sure the overall smells indicate that there must be another way, probably radically differently structured, to do all this. I'm thinking about something with watchers on refs / atoms... -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en