Accessing outlets from a created thread.
I have an mxj object with four outlets "mxj main". One of the outlets is connected to thispatcher so I can create objects and number boxes etc...
Within the main code I just access the outlet with;
outlet(2, new Atom[]{Atom.newAtom("example")});
As part of the project, I need to create new threads to deal with handling methods in the background. The problem I face now is that if I want to send info to "thispatcher" from an outlet from the thread, the thread doesn't have access to the outlet. Using outlet(2, new Atom[]{etc...... doesn't output anything to that outlet.
Is there something i'm overlooking or is this even possible??
Well, outputting into the max patch from another thread is not permitted, but I had thought that outlet would defer to the main thread if called from something other than the main or the timer thread, but perhaps not.
Try using outletHigh() instead. It doesn't have all the nice overloaded calls, but it should work for you, sending the output in the timer thread. If you want it to output in the main thread, you'll need to use some other form of communication (e.g. MaxQelem, or MaxSystem.defer), to call outlet() from the main thread.
-Joshua
Sorry to intrude here but i'm also interested to know what th epreferred method is, i can't tell from the docs.
calling outlet() from a user created thread IS always deferred to the low priority thread for me.
on p. 42 of the pdf there is example showing outletBang being called from a user thread.
But under threading concerns p.60:
"Finally, if you are writing an object in Java or C which creates and uses threads other than the low priority and high priority threads in Max, you may not make outlet calls in the additional threads your object has created. The only safe threads to output data through a Max patcher network are the low priority queue and high priority scheduler threads. The Max Java API will automatically detect when attempting to output into a patcher network from an unsafe thread and generate an event to be executed by the low priority queue when using the outlet() method, and generate an event to be executed by the high priority scheduler when using the outletHigh() method."
So, should we just rely on these unsafe calls being caught or should we use something like defer() or schedule() to create an event which will output in the low or high threads?
thanks
jan
outlet() should defer, I believe. If somone can provide an example, we can investigate further.
funkymunky
i attach an example -the threadtest example from the docs. it calls outlet() from a user created thread. The output goes to an instance of WhichThread and shows the outlet call is deferred to the main thread.
Joshua
just to make clear - for me everything is working as expected, my question was only whether or not this is the preferred way.
Glad to hear. Yes. This is the preferred way and should be relied upon. The report at the beginning of this thread made me think there was a problem with the implementation. Sound like there isn't. Thanks for verifying. Let us know if you experience any problems.
This is quite strange, when I run the sample patch from jan.jdo it works correctly. I hadn't noticed page 42 from the pdf. The only difference I have in my program is that my threads are in a separate class (I don't think this should matter). I ended up changing the program by referencing the main thread and then calling a method in the main thread and passing it values to send to the outlet. Its a bit of hassle but it worked. Im going to rewrite the code now though and try the outletHigh() method. I can upload my code but it might need a bit of explaining.
I tried it there but it doesn't seem to work. Would it matter if i'm using runnable instead of thread? I use this because I have extends MaxObject implements Runnable. If I had extends Threads, I can't use outletHigh() or outlet() as they are defined within MaxObjects? These are my thoughts on it but Im only programming in Java a few months.
Well, if I understand what you are saying, even if you subclass MaxObject in this way, it will not reference the actual MaxObject which maps to the one in the patcher. So your approach will not work. Even though the methods for outlet() will be present, it doesn't know about the actual outlets. This explains why it wasn't working for you.
What I would suggest you do if you need a separate class, is pass your main MaxObject into your new class's constructor, store it in the new class and reference it that way.
So something like:
new Foo(this);
Foo(MaxObject x) {
..
mymaxobj = x;
..
}
Side note:
Be careful with this, as depending on if you store a pointer to your instance of your new class inside your MaxObject class, you could create a circular reference that may prevent the objects from being garbage collected. You can handle this either by setting local variables to null in the _notified_deleted() method, or some other way.
Actually, I guess this might not be as much of a problem if it's not reachable from the root. Search on "circular" in the following link:
What I have done in this situation is to create static methods in my main MaxObject class that call outlet() directly. I then can call these methods from my separate Thread class - I've never had a problem with this, as it appears to defer properly.
That might be an issue with multiple instances of mxj loading the same class. I'm not sure, but as long as it works for your purposes...
Im basically doing what Jesse talked about. I might try change it as I think it might make things easier down the line. Ill give it a go and see how I get on. Cheers