|Think about Loose Coupling|
Thread::Apartment, how do I use main:: subs?by wilsond (Scribe)
|on May 10, 2009 at 22:32 UTC||Need Help??|
wilsond has asked for the
wisdom of the Perl Monks concerning the following question:
I'm using Thread::Apartment to create threads. It's pretty nice since it deals with closures and all that for me.
I need to be able to have a thread make use of subs that are in main:: and in the main thread's context.
For example, one of the things I want to be able to do:
One of my threads runs an XMPP connection. I want to be able to create a new thread (run by Thread::Apartment) on demand from a request coming in on the XMPP connection. I don't want the thread to be a child of the XMPP thread, but of the main thread itself.
I tried passing a CODEREF from main into the thread upon creation, but it kills the XMPP thread when it tries to use that CODEREF. (Thread 1 terminated abnormally: Can't call method "ta_invoke_closure" on an undefined value at Thread/Apartment/Closure.pm line 62, <FH> line 72.) I tried wrapping the CODEREF with T::A::register_closure(), but that didn't help either. I think it's more a problem of my understanding T::A than it is of anything else. I can't figure it out.
The best I came up with (before using T::A) was to have a threads::shared array (to be used as a queue) in main that the threads could write to. The loop in main would check the array/queue and perform actions on it. This feels hackish and doesn't do all of what I'm hoping I could accomplish.
Right now, I have a T::A thread that I use as a controller that keeps track of all of the other T::A threads and passes the T::A::Client ref for other threads to use when they need to communicate with the other threads directly. It doesn't take care of interacting with the main thread, though.
Does anyone have experience using Thread::Apartment and has an idea how to do this? Thanks!
Question Edit: Is there a way to "convert" the main thread into an apartment so I can pass its T::A::Client handle to the other apartments? That seems like it'd do the trick for my purposes. I don't want to have it spawn a new thread for this to happen, just alter the main thread in such a way that it is accessible via T::A::Client.