On Tue, Apr 9, 2013 at 12:41 PM, Timothy Washington <twash...@gmail.com>wrote:
> Hi all, > > I have a polyglot project, comprising of a little Java and mostly Clojure > code. The Java class is a concrete callback for an external library. There > will be sub-second firing of that callback, and event map objects will get > pushed onto a list. > > From Clojure, I need to access that list in the callback. The problem is > that, in Clojure, we have STM (like refs) that can control access to the > data. If that data member is in Java, how can I control the access? From > Clojure, I could potentially access and flush the list, while the Java > callback is writing to it. > > Is there a better strategy here? Can Java access a STM ref in Clojure? How > might that work? > If you control the Java code, you may be able to use Clojure's STM from inside it. You would wrap the state in a ref and call methods on the ref object from Java. You'd also want to set up a transaction by calling clojure.lang.LockingTransaction.runInTransaction (func), where func implements IFn and the zero-argument invoke method is implemented to do the transaction. Alternatively, and maybe simpler, the Java callback could just .invoke a function you've defined in Clojure and whose Var you've previously (during initialization) accessed on the Java side to get at the function object and store a reference to it into a static variable. The bulk of the callback can then be handled inside of the Clojure function, in Clojure code, where you can just write (dosync (alter foo ... )) You might consider going still further and using gen-class, proxy, reify, or deftype to generate the Java class, with method bodies written in Clojure. You can use proxy, reify, or deftype to implement Java interfaces, but you'd need gen-class if you needed to extend a concrete class defined by the external library. Proxy is commonly used to implement Swing listeners in Clojure code that I've seen, which sounds like a very similar situation to yours. (User pushes a button, ActionListener is invoked and uses a transaction to update the model.) Finally, though it's trickier to do it right, you could give up Clojure's concurrency constructs and rely on Java's. Have the callback synchronize on a Java object with the state in it (synchronized (theObject) { theObject.mutatingMethod(args); }), and use (locking the-object (.mutatingMethod the-object args)) when you want to mutate it from Clojure, and (locking the-object (do-something-with (.getFoo the-object))) when you want to read it without it possibly being mutated at the same time by another thread. -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.