CallWrapper snippet

"""
i have sturctured my network system to update the simulation with every call.  But when i came to reloading the simulation i wanted to do one sim step per frame. (so that i can update the laoding bar and not have the game just hang) But then i accidently got calls from the server that were out of order because it was still executing old calls that it got during loading.

This is a way to syncronize access to some object easely.  It works 
great as long as object does not return any thing.

* bonus points if some one figures out how to remove the def _() hack.
    

"""


class CallWrapper:
    """ 
        wraps a calls to a class so that 
        they can be collected and executed 
        later.
        
        it only works if the calss does not return
        any thing usefull.  
    """
    def __init__(self,a):
        """ pass an instance of a class you want to wrap """
        self.cls = a
        self.q = []
        for e in dir(a):
            if len(e) > 0 and e[0] != "_" :
                fun = getattr(a,e)
                if type(fun) == type(self.__init__):
                    def _():
                        name = e
                        def add(*args, **kargs):
                            self.q.append((name,args,kargs))
                        setattr(self,name,add)
                    _()

    def _process(self):
        """ 
            process all messages collected 
        """
        for name,args,kargs in self.q:
            getattr(self.cls,name)(*args,**kargs)
        self.q = []

    def _process_step(self):
        """ 
            process first message in q collected 
            return true if there are more messages
            else returns false when all messages are 
            processed
        """
        if self.q:
            name,args,kargs = self.q.pop(0)
            getattr(self.cls,name)(*args,**kargs)
            return True
        else:
            return False

#------------------------------------------------------------

# basic class
class B:
    def do(self,arg):
        print arg
    def spam(self):
        pass
    def foo(self,u,n):
        print "f"+u*n
# create class
b = B()
# wrap the instance
cw = CallWrapper(b)

# call this wrapper just like you would 
# the original, just dont expect it to return any thing
for i in range(10):
    cw.do("message #"+str(i))
# proess the commands
cw._process()

# another way to use it is:
# again fill it up with calls
for i in range(10):
    cw.do("message #"+str(i))
    cw.foo("u",i)
# process one call at a time
while cw._process_step():
    # do some thing like render a frame maybe?
    pass