at-exit-thread

castironpi at gmail.com castironpi at gmail.com
Sat Mar 1 01:02:32 EST 2008


On Feb 29, 4:34 pm, Preston  Landers <pland... at gmail.com> wrote:
> On Feb 29, 2:12 pm, castiro... at gmail.com wrote:
>
> > If a thread adds an object it creates to a nonlocal
> > collection, such as a class-static set, does it have to maintain a
> > list of all such objects, just to get the right ones destroyed on
> > completion?  
>
> Yes.
>
> > Processes destroy their garbage hassle-free; how can
> > threads?  
>
> If you're asking "is there some automatic way to associate a external
> resource with a thread so that it's deleted when the thread is done"
> then the answer (to the best of my knowledge) is no.  You would have
> to take care of these details yourself once something outside your
> thread got a reference to the resource. If you keep all references to
> the resource inside the thread, then you can use the __del__ method of
> the resource to take any cleanup actions.
>
> Also, processes don't always "destroy their garbage hassle free" if
> you consider inter process communication.  For instance, if you create
> an object in one process then serialize it and pass it to another
> process through e.g. an XMLRPC call, there's no automatic way for the
> other process to be notified that the originating process exited.
> You'd have to build that feature in.  Exact same thing with threads.
>
> > And don't forget Thread.run( self ) in the example, if
> > anyone ever wants to make use of the 'target' keyword.
>
> I don't understand what you're referring to.

In the initial counterexample,

> class MyThread(Thread):
>
>     def run(self):
>         while some_condition:
>              do_something()
>         do_something_after_the_thread_ends()

, MyThread overrides 'run', so target is never called.  It did create
the picture to me though that:

class MemHoldingThread( Thread ):
   def __init__( self, *a, **kwa ):
      Thread.__init__( self, *a, **kwa )
      self.objs= set()
      self._args= ( self, )+ self._args
   def hold( self, obj ):
      self.objs.add( obj )
      return obj
   def run( self ):
      Thread.run( self )
      self._cleanup()
   def _cleanup( self ):
      for obj in self.objs:
         obj.clean()

Then,

def f( thd ):
   resrc= thd.hold( NewResource() )
   infinite_loop( resrc )

MemHoldingThread( target= f )

thd is prepended to f's list of arguments so that it has a handle to
its own thread object, but doesn't need an entire thread class--
middle ground.  Then thd.hold adds any obj created to a thread-local
set (and returns it).  Then, _cleanup iterates over the set, and calls
clean() on its items when f returns.

At this point, I've gotten really really complicated.  Not only have I
still not shown the _at_exit call to MemHoldingThread static member
_clean_all_remaining, but it's only useful if NewResource provides a
list of globals/externals that it "adds itself to", or a clean()
method to do them itself.  But, you do get the benefit of not having
to store each global/external in a Thread subclass object-- it does
that for you-- as well as the benefit of being able to invoke the
behavior without explicit additional subclasses.

thing1= MemHoldingThread( target= thingf ); thing1.start()
daemon1= MemHoldingThread( target= daemonf ); daemon1.start()
server1= MemHoldingThread( target= serverf ); server1.start()

rather than

class Thing( Thread ):... thing1= Thing(); thing1.start()
class Daemon( Thread ):... daemon1= Daemon(); daemon1.start()
class Server( Thread ):... server1= Server(); server1.start()

, which is useful sometimes, if even only a negligible proportion of
them.

<digressions>
(Honestly, if Thread.start() returned self,

class Thing( Thread ):... thing1= Thing().start()

, or Thread( start= True ) launched it, that could go a long way,  --
you just get keyword name collisions with target's parameters pretty
soon.)

What are the disadvantages to specifying an internal storage byte
order for conversion to a string to use mmap with, by the way?

And for all my seniors out there, you may be pleased to learn that I
no longer think that all of my general little 5-liners should go in
the standard library.
</digressions>

> you consider inter process communication.  For instance, if you create
> an object in one process then serialize it and pass it to another
> process through e.g. an XMLRPC call, there's no automatic way for the
> other process to be notified that the originating process exited.

Maybe... but if all else fails you can pass the process ID in on
connection creation, and periodically check if it's still alive.  Do
any Op. Sys.s have a OnProcTerminate( hproc, callback ) API?  Sadly,
stdin IPC is before my time.

Windows actually even has ThreadSuspend and ThreadResume API; if
suspending threads (and raising exceptions in them from others)
threatens state consistency, what are their semantics?



More information about the Python-list mailing list