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.


Reply via email to