http://qs1969.pair.com?node_id=478996


in reply to Re: Outside-in objects with Object::LocalVars (threads)
in thread Outside-in objects with Object::LocalVars

Hmmm. That's a big drawback. I'm really not very thread-savvy, so it's not something that was top of mind. Can you help me understand what about it makes it thread-unsafe? My limited understanding of threads was that all data is copied unless explicitly shared -- which I suppose, on reflection, does make me think that using the refaddr of the object as a key to the data is likely a problem when the blessed reference gets cloned into the new thread. (If that's true, I assume that problem affects inside-out objects, as well, then?) Maybe it makes sense to generate a unique ID for each object and store it in a blessed scalar used as the underlying object.

What other things do I need to consider?

Update: After some reading of perlthrtut, threads, threads::shared, Things you need to know before programming Perl ithreads, and Where Wizards Fear to Tread (perl.com), I'm not sure this is a "big" drawback. From what I can tell, the major problem is that the object ID gets lost across the creation of a new thread; that can be fixed by embedding a unique ID as described above. After spawning a thread, each thread is "safe" in that they won't interfere with each other, but it means that changes to object 1 in thread A don't appear in the corresponding object 1 in thread B -- but that's by design in the perl threads approach. To be able to share across the boundary should be theoretically possible by marking the package globals holding data as shared and implementing appropriate locking/semaphores. That complexity would appear to be present in any object framework that tries to synchronize an object across thread boundaries, not just this one. Still, I'll back-burner the idea of implementing a thread-safe version of this somewhere down the line -- at least the safe-across-a-spawn safe, and maybe beyond.

Update2: In response to a post I made elsewhere, BrowserUk pointed out Re: Reliable asynchronous processing that addresses some FUD about threads in perl.

-xdg

Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Replies are listed 'Best First'.
Re^3: Outside-in objects with Object::LocalVars (threads)
by tye (Sage) on Jul 30, 2005 at 00:30 UTC

    "thread safety" is a general property, not something to do with a specific implementation of Perl threads.

    The implementation of Perl threads that you are commenting on is mostly like "forking, but without all of that efficiency", sort of the worst of both worlds (threading and forking). So my comment wasn't to do with how well you could make your stuff work with that implementation of threading.

    And having your object be usable with a threaded Perl so long as you don't share your object(s) between threads just means that that Perl's threading implementation isn't completely broken, not that your object is thread safe.

    Your method isn't thread safe because you can't have two threads using the same method from the same class at the same time on different objects -- where, again, I use the more common definition of "thread" here, that is, "two execution streams that share (almost) all of their virtual memory", not as in "two separate instances of Perl interpreters on related threads, one of which has laboriously and inefficiently made a near-complete copy of the other one".

    But you are correct in that lack of thread safety isn't a horrid problem here, because Perl has yet to have a decent threading model.

    BTW, when I released Data::Diver (just a few days ago), I used a "get last error reason" scheme despite the fact that it isn't thread safe. Normally my modules use objects, to avoid "global" problems such a thread safety and to support user configuration. This particular module didn't have any configurable bits to worry about and I felt using OO would have been much less convenient for most uses of the module. But that meant that my simple way of getting error details wasn't thread-safe. But I didn't want to complicate the important parts of the module to overcome this problem with less-important part of the module, especially since Perl doesn't really have good thread support anyway.

    But I did notice that I was doing something that wasn't thread-safe. It also isn't re-entrant, which becomes a problem if multiple layers of your application use it. I think your use of localized globals for access to member data is re-entrant in the absense of threads, though.

    So, upon reflection, given the current state of Perl, I guess I shouldn't have been surprised that you didn't mention nor worry too much about whether your Perl module was thread-safe (neither did I). Though I was also curious if my impression was correct.

    - tye        

      So apart from the object ID issues, which is valid for the current implementation of Perl ithreads and fairly easily addressed, your point is that it isn't thread-safe in general against some unimplemented, future version of Perl threading that shares virtual memory but whose other properties are as yet undefined? I'd say that's setting the standard a tad high. That said, your general impression might be correct -- and it's certainly led me to have a crash course on threads in Perl, so I appreciate the feedback

      I think the question of whether the "localized globals" approach would work under a shared virtual memory thread depends mostly on the whether the dynamic scoping effects of local are localized to a thread or not. From reading Temporary Values via Local, I would tend to think that might be an important implementation feature -- otherwise, I would think that localizing "magic" variables like $/ and $| wouldn't be thread-safe in your broader definition either.

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.