These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			257 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Synchronization metaclass.
 | 
						|
 | 
						|
This metaclass  makes it possible to declare synchronized methods.
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
import thread
 | 
						|
 | 
						|
# First we need to define a reentrant lock.
 | 
						|
# This is generally useful and should probably be in a standard Python
 | 
						|
# library module.  For now, we in-line it.
 | 
						|
 | 
						|
class Lock:
 | 
						|
 | 
						|
    """Reentrant lock.
 | 
						|
 | 
						|
    This is a mutex-like object which can be acquired by the same
 | 
						|
    thread more than once.  It keeps a reference count of the number
 | 
						|
    of times it has been acquired by the same thread.  Each acquire()
 | 
						|
    call must be matched by a release() call and only the last
 | 
						|
    release() call actually releases the lock for acquisition by
 | 
						|
    another thread.
 | 
						|
 | 
						|
    The implementation uses two locks internally:
 | 
						|
 | 
						|
    __mutex is a short term lock used to protect the instance variables
 | 
						|
    __wait is the lock for which other threads wait
 | 
						|
 | 
						|
    A thread intending to acquire both locks should acquire __wait
 | 
						|
    first.
 | 
						|
 | 
						|
   The implementation uses two other instance variables, protected by
 | 
						|
   locking __mutex:
 | 
						|
 | 
						|
    __tid is the thread ID of the thread that currently has the lock
 | 
						|
    __count is the number of times the current thread has acquired it
 | 
						|
 | 
						|
    When the lock is released, __tid is None and __count is zero.
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        """Constructor.  Initialize all instance variables."""
 | 
						|
        self.__mutex = thread.allocate_lock()
 | 
						|
        self.__wait = thread.allocate_lock()
 | 
						|
        self.__tid = None
 | 
						|
        self.__count = 0
 | 
						|
 | 
						|
    def acquire(self, flag=1):
 | 
						|
        """Acquire the lock.
 | 
						|
 | 
						|
        If the optional flag argument is false, returns immediately
 | 
						|
        when it cannot acquire the __wait lock without blocking (it
 | 
						|
        may still block for a little while in order to acquire the
 | 
						|
        __mutex lock).
 | 
						|
 | 
						|
        The return value is only relevant when the flag argument is
 | 
						|
        false; it is 1 if the lock is acquired, 0 if not.
 | 
						|
 | 
						|
        """
 | 
						|
        self.__mutex.acquire()
 | 
						|
        try:
 | 
						|
            if self.__tid == thread.get_ident():
 | 
						|
                self.__count = self.__count + 1
 | 
						|
                return 1
 | 
						|
        finally:
 | 
						|
            self.__mutex.release()
 | 
						|
        locked = self.__wait.acquire(flag)
 | 
						|
        if not flag and not locked:
 | 
						|
            return 0
 | 
						|
        try:
 | 
						|
            self.__mutex.acquire()
 | 
						|
            assert self.__tid == None
 | 
						|
            assert self.__count == 0
 | 
						|
            self.__tid = thread.get_ident()
 | 
						|
            self.__count = 1
 | 
						|
            return 1
 | 
						|
        finally:
 | 
						|
            self.__mutex.release()
 | 
						|
 | 
						|
    def release(self):
 | 
						|
        """Release the lock.
 | 
						|
 | 
						|
        If this thread doesn't currently have the lock, an assertion
 | 
						|
        error is raised.
 | 
						|
 | 
						|
        Only allow another thread to acquire the lock when the count
 | 
						|
        reaches zero after decrementing it.
 | 
						|
 | 
						|
        """
 | 
						|
        self.__mutex.acquire()
 | 
						|
        try:
 | 
						|
            assert self.__tid == thread.get_ident()
 | 
						|
            assert self.__count > 0
 | 
						|
            self.__count = self.__count - 1
 | 
						|
            if self.__count == 0:
 | 
						|
                self.__tid = None
 | 
						|
                self.__wait.release()
 | 
						|
        finally:
 | 
						|
            self.__mutex.release()
 | 
						|
 | 
						|
 | 
						|
def _testLock():
 | 
						|
 | 
						|
    done = []
 | 
						|
 | 
						|
    def f2(lock, done=done):
 | 
						|
        lock.acquire()
 | 
						|
        print "f2 running in thread %d\n" % thread.get_ident(),
 | 
						|
        lock.release()
 | 
						|
        done.append(1)
 | 
						|
 | 
						|
    def f1(lock, f2=f2, done=done):
 | 
						|
        lock.acquire()
 | 
						|
        print "f1 running in thread %d\n" % thread.get_ident(),
 | 
						|
        try:
 | 
						|
            f2(lock)
 | 
						|
        finally:
 | 
						|
            lock.release()
 | 
						|
        done.append(1)
 | 
						|
 | 
						|
    lock = Lock()
 | 
						|
    lock.acquire()
 | 
						|
    f1(lock)                            # Adds 2 to done
 | 
						|
    lock.release()
 | 
						|
 | 
						|
    lock.acquire()
 | 
						|
 | 
						|
    thread.start_new_thread(f1, (lock,)) # Adds 2
 | 
						|
    thread.start_new_thread(f1, (lock, f1)) # Adds 3
 | 
						|
    thread.start_new_thread(f2, (lock,)) # Adds 1
 | 
						|
    thread.start_new_thread(f2, (lock,)) # Adds 1
 | 
						|
 | 
						|
    lock.release()
 | 
						|
    import time
 | 
						|
    while len(done) < 9:
 | 
						|
        print len(done)
 | 
						|
        time.sleep(0.001)
 | 
						|
    print len(done)
 | 
						|
 | 
						|
 | 
						|
# Now, the Locking metaclass is a piece of cake.
 | 
						|
# As an example feature, methods whose name begins with exactly one
 | 
						|
# underscore are not synchronized.
 | 
						|
 | 
						|
from Meta import MetaClass, MetaHelper, MetaMethodWrapper
 | 
						|
 | 
						|
class LockingMethodWrapper(MetaMethodWrapper):
 | 
						|
    def __call__(self, *args, **kw):
 | 
						|
        if self.__name__[:1] == '_' and self.__name__[1:] != '_':
 | 
						|
            return apply(self.func, (self.inst,) + args, kw)
 | 
						|
        self.inst.__lock__.acquire()
 | 
						|
        try:
 | 
						|
            return apply(self.func, (self.inst,) + args, kw)
 | 
						|
        finally:
 | 
						|
            self.inst.__lock__.release()
 | 
						|
 | 
						|
class LockingHelper(MetaHelper):
 | 
						|
    __methodwrapper__ = LockingMethodWrapper
 | 
						|
    def __helperinit__(self, formalclass):
 | 
						|
        MetaHelper.__helperinit__(self, formalclass)
 | 
						|
        self.__lock__ = Lock()
 | 
						|
 | 
						|
class LockingMetaClass(MetaClass):
 | 
						|
    __helper__ = LockingHelper
 | 
						|
 | 
						|
Locking = LockingMetaClass('Locking', (), {})
 | 
						|
 | 
						|
def _test():
 | 
						|
    # For kicks, take away the Locking base class and see it die
 | 
						|
    class Buffer(Locking):
 | 
						|
        def __init__(self, initialsize):
 | 
						|
            assert initialsize > 0
 | 
						|
            self.size = initialsize
 | 
						|
            self.buffer = [None]*self.size
 | 
						|
            self.first = self.last = 0
 | 
						|
        def put(self, item):
 | 
						|
            # Do we need to grow the buffer?
 | 
						|
            if (self.last+1) % self.size != self.first:
 | 
						|
                # Insert the new item
 | 
						|
                self.buffer[self.last] = item
 | 
						|
                self.last = (self.last+1) % self.size
 | 
						|
                return
 | 
						|
            # Double the buffer size
 | 
						|
            # First normalize it so that first==0 and last==size-1
 | 
						|
            print "buffer =", self.buffer
 | 
						|
            print "first = %d, last = %d, size = %d" % (
 | 
						|
                self.first, self.last, self.size)
 | 
						|
            if self.first <= self.last:
 | 
						|
                temp = self.buffer[self.first:self.last]
 | 
						|
            else:
 | 
						|
                temp = self.buffer[self.first:] + self.buffer[:self.last]
 | 
						|
            print "temp =", temp
 | 
						|
            self.buffer = temp + [None]*(self.size+1)
 | 
						|
            self.first = 0
 | 
						|
            self.last = self.size-1
 | 
						|
            self.size = self.size*2
 | 
						|
            print "Buffer size doubled to", self.size
 | 
						|
            print "new buffer =", self.buffer
 | 
						|
            print "first = %d, last = %d, size = %d" % (
 | 
						|
                self.first, self.last, self.size)
 | 
						|
            self.put(item)              # Recursive call to test the locking
 | 
						|
        def get(self):
 | 
						|
            # Is the buffer empty?
 | 
						|
            if self.first == self.last:
 | 
						|
                raise EOFError          # Avoid defining a new exception
 | 
						|
            item = self.buffer[self.first]
 | 
						|
            self.first = (self.first+1) % self.size
 | 
						|
            return item
 | 
						|
 | 
						|
    def producer(buffer, wait, n=1000):
 | 
						|
        import time
 | 
						|
        i = 0
 | 
						|
        while i < n:
 | 
						|
            print "put", i
 | 
						|
            buffer.put(i)
 | 
						|
            i = i+1
 | 
						|
        print "Producer: done producing", n, "items"
 | 
						|
        wait.release()
 | 
						|
 | 
						|
    def consumer(buffer, wait, n=1000):
 | 
						|
        import time
 | 
						|
        i = 0
 | 
						|
        tout = 0.001
 | 
						|
        while i < n:
 | 
						|
            try:
 | 
						|
                x = buffer.get()
 | 
						|
                if x != i:
 | 
						|
                    raise AssertionError, \
 | 
						|
                          "get() returned %s, expected %s" % (x, i)
 | 
						|
                print "got", i
 | 
						|
                i = i+1
 | 
						|
                tout = 0.001
 | 
						|
            except EOFError:
 | 
						|
                time.sleep(tout)
 | 
						|
                tout = tout*2
 | 
						|
        print "Consumer: done consuming", n, "items"
 | 
						|
        wait.release()
 | 
						|
 | 
						|
    pwait = thread.allocate_lock()
 | 
						|
    pwait.acquire()
 | 
						|
    cwait = thread.allocate_lock()
 | 
						|
    cwait.acquire()
 | 
						|
    buffer = Buffer(1)
 | 
						|
    n = 1000
 | 
						|
    thread.start_new_thread(consumer, (buffer, cwait, n))
 | 
						|
    thread.start_new_thread(producer, (buffer, pwait, n))
 | 
						|
    pwait.acquire()
 | 
						|
    print "Producer done"
 | 
						|
    cwait.acquire()
 | 
						|
    print "All done"
 | 
						|
    print "buffer size ==", len(buffer.buffer)
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    _testLock()
 | 
						|
    _test()
 |