thread problem

Greg Wilson gvwilson at nevex.com
Mon Feb 28 21:47:21 CET 2000


I'm trying to implement futures in Python using threads.  When a future is
created, it (internally) spawns a thread to calculate its value.  When
another thread tries to get the future's value (by calling the future
object as if it were a function), the read blocks until the value is
available.

My implementation is included below.  The problem is that I'm setting
'self.result' in the child thread, but when the __call()__ returns, the
value has gone back to 'None'.  There's nothing in the docs about objects
being cloned during thread creation --- I'd be grateful if anyone could tell
me what's up.

Thanks,
Greg

-----------------------

#!/usr/bin/python

from thread import *
import time

"""Simple future class for Python"""

class Future:

    # Create the future.
    def __init__(self):

        # Setup code executed in creator's thread.
        # Important that lock is locked before thread spawned.
        self.result = None
        self.lock   = allocate_lock()
        self.lock.acquire()
        start_new_thread(Future._run, (self,))

    # Run the thread evaluator.
    def _run(self):

        # Do the work defined by the derived class.
        print `get_ident()` + \
              " about to self.evaluate()"
        self.result = self.evaluate()
        print `get_ident()` + \
              " returned from self.evaluate()" + \
              " releasing lock" + \
              " result is " + \
              `self.result`

        # Report.
        self.lock.release()
        print `get_ident()` + \
              " released lock" + \
              " result is " + \
              `self.result`

    # Fetch the future's value.
    def __call__(self):

        print `get_ident()` + \
              " in __call__()" + \
              " lock state is " + \
              `self.lock.locked()`

        # If the lock is still held...
        if self.lock.locked():

            # ...wait for evaluation to complete...
            self.lock.acquire()

            # ...then signal to others that the value is available
            self.lock.release()

        # Result must have been calculated by here.
        print `get_ident()` + \
              " returning self.result == " + \
              `self.result`
        return self.result

    # Default version of 'evaluate()' does nothing
    def evaluate(self):
        pass

# Derive a future class that sleeps for a while, then returns a constant
class FutureTest(Future):

    # Create the future
    def __init__(self, constant):
        self.constant = constant
        Future.__init__(self)

    # Calculate a value
    def evaluate(self):
        print `get_ident()` + \
              " in derived evaluate()" + \
              " constant is " + \
              `self.constant` + \
              " and result before call is " + \
              `self.result`
        print `get_ident()` + \
              " passed sleep()" + \
              " setting result in derived evaluate()"
        self.result = self.constant
        print `get_ident()` + \
              " self.result is now " + \
              `self.result`

# Test
if __name__ == "__main__":

    # simple test function
    print "\n\n" + `get_ident()` + ": creating future"
    f = FutureTest(2)
    print `get_ident()` + ": fetching value"
    val = f()
    print `get_ident()` + ": value is " + `val` + "\n\n"






More information about the Python-list mailing list