Skip to content

paulzhol/libtask9

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

libtask9

This is a fairly straightforward port of Russ Cox' libthread C library from Plan 9 from User Space (aka plan9port) to CPython. It depends on the greenlet module.

Procs

Operating system threads created by the Python threading module.

Tasks

User-space scheduled coroutines (libthread calls them threads, I've renamed them to tasks to avoid confusion with the Python threading module) implemented using the greenlet module.

They are cooperatively switched by their respective Proc and are bound only to that Proc's execution thread.

Channels

A scheduling and synchronization mechanism, used to coordinate tasks in the same Proc or among different Procs.

plan9port libthread Documentation

Example

bind() a socket and wait at most 10 seconds for a client to connect

import sys
import traceback
import socket
from functools import partial
from libtask9 import new_task, init_timers, curtask, IOProc, Channel, alt, alt_recv
from libtask9 import sleep, after, Second

def ticker():
    while True:
        print 'tick from {}'.format(curtask())
        sleep(2*Second)

def accept_task(s, io, reply_chan):
    try:
        client, addr = io.iocall(s.accept)
    except socket.error:
        traceback.print_exc()
        reply_chan.send((None, None))
        return

    print 'got a connection from: {}'.format(addr)
    reply_chan.send((client, addr))

def iotest(args):
    io = IOProc('io1')
    io.start()
    new_task(ticker)

    # bind a socket and listen
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('0.0.0.0', 8080))
    s.listen(1)

    print 'waiting 10 seconds for io to complete'
    client_ch = Channel(1)
    new_task(partial(accept_task, s, io, client_ch))

    idx, result = alt(
        alt_recv(client_ch),
        alt_recv(after(10*Second)),
        canblock=True
    )

    if idx == 0:
        client, _ = result
        io.iocall(partial(client.send, 'hello!\n'))
        io.iocall(client.close)
    elif idx == 1:
        print 'timeout, forcing close on listener'
        s.shutdown(socket.SHUT_RDWR)
        s.close()
        # allow the iocall a chance to complete before we call io.stop()
        client_ch.recv()

    io.stop()

def main(args):
    new_task(None).switchtask()
    init_timers()
    iotest(args)
    print 'exiting'
    raise SystemExit(0)

if __name__ == '__main__':
    import logging; logging.basicConfig(); logging.getLogger().setLevel('DEBUG')
    main(sys.argv)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published