Multithreaded Telnet sessions
Pierre-Frédéric Caillaud
peufeu at free.fr
Wed Jun 30 12:39:02 EDT 2004
I like single-threaded asynchronous network stuff, but programming state
machines is a pain.
Here is a guess at how to do it with pseudo coroutines implemented by
hacking with yield.
If your stuff can be implemented asynchronously (use module asynchat) you
can easily have hundreds of simultaneous connections.
# fast single-threaded queue
class stQueue( object ):
class QueueEmptyError( KeyError ):
pass
def __init__(self):
self._in = 0;
self._q = {}
def put(self, obj):
self._q[self._in] = obj
self._in += 1
def get(self):
if self._q: return self._q.pop( self._in - len(self._q) )
else: raise self.QueueEmptyError
def qsize(self):
return len( self._q )
def __nonzero__(self):
return bool(self._q)
# receiver class, could be a socket to send data
class stReceiver( object ):
def __init__(self,name):
self.name = name
def process( self, data ):
print self.name, ':', data
# stupid coroutines implemented with yield
class asyncSync( object ):
def __init__( self, receiver ):
self.inqueue = stQueue()
self.receiver = receiver
# we expect messages where
# message=0 print "hello"
# message=1 get another message and print it
# message=2 get an integer N, get N messages, print them
# message=3 die
def run(self):
while 1:
while not self.inqueue: # try to get a message
yield None # come back here newt time if no message
msg = self.inqueue.get()
if msg==0:
self.receiver.process( '(0) hello' )
elif msg==1:
while not self.inqueue:
yield None
self.receiver.process( "(1) print a message : %s" % self.inqueue.get()
)
elif msg==2:
while not self.inqueue:
yield None
nmessages = self.inqueue.get()
self.receiver.process( "(2) waiting for %d messages" % nmessages )
while self.inqueue.qsize() < nmessages:
yield None
for i in range(nmessages):
self.receiver.process( "(2) print a message (%d/%d) : %s" %
(i,nmessages,self.inqueue.get()) )
elif msg==3:
break
a = asyncSync( stReceiver( 'thread a' ))
ar = a.run()
ma = iter([ 0, 1, 'yikes', 2, 3, 'i', 'am', 'here', 2, 4, 'i', 'am',
'still', 'here', 0, 3 ])
print ar.next()
a.inqueue.put( ma.next() ) # these lines send a message to the object a
print ar.next() # these trigger some processing in a.run
a.inqueue.put( ma.next() )
print ar.next()
a.inqueue.put( ma.next() ) # these lines are interleaved in random order
just to show it works
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
print ar.next()
print ar.next()
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
print ar.next()
a.inqueue.put( ma.next() )
a.inqueue.put( ma.next() )
print ar.next()
a.inqueue.put( ma.next() )
print "We should crash here"
print ar.next()
More information about the Python-list
mailing list