Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

simple, unthreaded multitasking with a Maya twist

License

NotificationsYou must be signed in to change notification settings

theodox/mTasks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

simple, unthreaded multitasking with a Maya twist

This module provides a limited form of coroutine based multi-tasking.

It's not intended as a substitute for 'real' threads, but it does allow you to create the illusion of multiple, simultaneous processes without crossing thread boundaries. This is particularly important in Maya, where only the main thread is allowed to touch the contents of the Maya scene or the GUI. It can also be useful in other applications where you'd like concurrent behavior without worrying about the memory-security issues associated with multiple threads. For Maya programming it allows a degree of interacivity which is otherwise complicated hard to create with scriptJobs or threads andexecuteDeferred() -- and it also makes it easy to avoid the kinds of baffling behaviors and random crashes that are so common when trying to work with threads.

Basics

The way it works is quite simple. Everything you want to run 'simultaneously' is a a function which uses Python's built-inyield keyword to release control.mTasks keeps a list of your functions and loops through the list, running each until it his a yield and then switching to the next. Here's a basic example:

def hello():    print "hello"    yield    def world():    print "world"    yield    def exclaim():    print "!"    yield    spawn(hello)spawn(world)spawn(exclaim)run()# hello# world# !

If you just usedyield in place ofreturn, this would be the same as collecting the functions in a and running them in turn. Howeveryielddoes not have to end a function. So you could rewrite the previous example like this:

def hello():    print "hello"    yield    print "word"    yield    print "!"    yield    spawn(hello)run()# hello# world# !

Any number of functions containing yields can run at the saem time, and their results will be interleaved:

def numbers():    for n in range (10):        print "number: ", n        yield        def letters():    for a in 'abcdefghijklmnopqrstuvwxyz':        print "letter: ", a        yield        spawn(numbers)spawn(letters)run()# number: 1# letter: a# number: 2# letter: b# and so... until numbers runs out, but letters keeps going:# letter: l# letter: m# letter: n

Running tasks

All of the tasks are owned by thescheduler module. The scheduler will step through each task in turn, executing until it finds ayield or the task terminates. The scheduler'stick() methods fires the next function/yield step -- in Maya the tick is usually hooked up to a Maya scriptJob that advances it on every Maya idle event. In a non-Maya context you can set the schedulder to run until all tasks are exhausted with therun() method. You generallydon't want to callrun() in Maya because it will act like a blocking function call until all of the queued tasks are done.

Monitoring and killing tasks

You can find all of the running tasks withlist_jobs(). Each job is assigned an integer id when spawned. It can be killed using thekill() command.

print list_jobs()# {1 : <sometask@1>, 8: <__wrapped__@8> }kill (8)

Scheduling

Thespawn function adds a callable to the mTasks system, starting it immediately (seetick(), below). You can also queue up functions to to run when other functions complete by usingdefer_spawn() -- which creates a task without running it -- andjoin(), which like a traditional thread join, waits for one task to finish before starting another. For example:

def hello():    print "hello"    yield    print "word"    yield    print "!"    yield    def goodbye():    print "goodby cruel world"    yield    h = spawn(hello)g = defer_spawn(goodbye)join(h, g)run()# hello# world# !# goodbye cruel world

A task can join any number of other tasks and will only execute after they have all completed.

It's often useful to defer an action for a set amount of time. In traditional threaded programming you would usetime.sleep() to pause a thread. However youdon't want to do that in anmTask, since the entire system is running in the main thread! Instead you can use aDelayTimer or anAwaitTimer to defer execution by just yielding until its time to run:

from mTasks.timers import DelayTimerdef wait_five_seconds():    delay = DelayTimer(5)    while delay:        yield    print "5 seconds have elapsed!"

TheAwaitTimer works the same way except you pass it an absolute time to begin, instead of a relative time.

There are convenience functions to add a delay or wait to a regular function:

delay(your_function, 5)  #add a 5 second delay to your_functionawait(your_function, 1483185599)  # wait until midnight on new years eve 2016

This idea was pioneered byDavid Beazley.

About

simple, unthreaded multitasking with a Maya twist

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp