473,695 Members | 1,716 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

pre-PEP: Standard Microthreading Pattern

I've been hacking away on this PEP for a while, and there has been some
related discussion on python-dev that went into the PEP:

http://mail.python.org/pipermail/pyt...ry/070921.html
http://mail.python.org/pipermail/pyt...ry/071155.html
http://mail.python.org/pipermail/pyt...ry/071181.html

I'd love to have feedback on this PEP:
- from a user's perspective (would you want to write microthreaded code?)
- from an implementer's perspective (and note that I have a reference
implementation that's just getting packaged up right now).
- from a technical perspective (efficiency, compatibility, etc.)
- regarding the two unresolved issues in the text

And now, without further ado:

PEP: XXX
Title: Standard Microthreading Pattern
Version: $Revision$
Last-Modified: $Date$
Author: Dustin J. Mitchell <du****@cs.uchi cago.edu>
Status: Draft
Type: Informational
Content-Type: text/x-rst
Created: 17-Feb-2007
Post-History:
Abstract
========

The extended support for generators introduced in PEP 342 [2]_
facilitated a natural way of writing generators that cooperatively
yield control to other functions, allowing multitasking within
a single OS thread. Such multitasking requires a supporting
environment (usually in the form of a scheduler), and several such
implementations are in active use. Each has slightly different
structural requirements for the task-implementing code.

This PEP proposes a single, consistent pattern for such code.
This consistency will enable microthreaded code to run in a variety
of environments, just as threaded code can currently run atop a
variety of OS-level threading libraries. Compliant libraries,
e.g., a microthreaded urllib, could then be developed, providing
batteries-included functionality for microthreaded software.
Definitions
===========

Within this PEP, "microthreading " is defined as interleaving
the execution of multiple independent codepaths by cooperatively
yielding control periodically in each codepath; a "microthrea d",
then, is one such codepath. This technique and variations on it
have also been referred to as "weightless threads", "tasklets", and
"greenlets" . It is a specilization of the more general event-based
multitasking model.

Microthreads are conceptually distinct from coroutines. A coroutine
can schedule a specific coroutine to be executed when it yields
control, even passing a value to that coroutine. Microthreads,
however, simply yield to facilitate multitasking, with no knowledge
or control of the next codepath to be executed.

This PEP addresses two audiences: authors of microthreaded code
(users) and designers of microthreaded environments (implementation s).

Motivation
==========

Application developers usually adopt an event-based architecture in
order to exploit asynchronous IO facilities. Asynchronous IO is
ideal when the overhead of an OS-level thread for each concurrent
IO operation is too high.

An event-based architecture is also useful when an application must
perform lightweight multitasking -- for example, an email client
must both wait for user input and monitor mailboxes for new mail.
Implementing this sort of multitasking using threads requires careful
use of synchronization primitives throughout the application to
ensure correctness. Using common event-based techniques requires
storing state on the heap and implementing callbacks for all state
transitions, which can quickly become complex.

A microthreaded architecture brings the best of both worlds: it
allows users to store state in local varables, just as they would
in a threaded implementation, while avoiding the need for complex
synchronization primitives. An email client, for example, can
implement the complex state of an IMAP client in a natural fashion,
and reflect that state using natural Python data structures with no
need for locking.

Several well-developed implementations of cooperative multitasking
are currently available, some of which implement microthreading.
However, each implementation approaches the subject differently,
and it is virtually impossible to share code between implementations .

This PEP is intended to bring some measure of consistency to
microthreaded code, to facilitate development of libraries and
implementation-agnostic code repositories to support microthreaded
development.
Rationale
=========

Since the introduction of generators in PEP 255 [3]_ and their
extension to support coroutines in PEP 342 [2]_, generators have been
used to implement various forms of microthreading [1]_:

- Example 3 in PEP 342 implements a simple trampoline scheduler.

- `Kiwi tasklets`_ (formerly GTasklets) use pre-PEP 342 generators
along with an explicit post-yield function call to retrieve any
incoming value or exception.

- `Twisted Python`_ includes an ``inlineCallbac ks`` decorator
[#inlineCallback s]_ which allows a generator to yield ``Deferred``
objects; callback results are then re-injected with ``send()``,
while errbacks result in a ``throw()``.

- `Kamaelia`_ includes Axon, a library supporting microprocesses which
multitask by yielding frequently, and interact through a
well-developed IPC mechanism.

- David Mertz's "Charming Python: Implementing "weightless threads"
with Python generators" [#Mertz]_ includes a basic microthreading
scheduler and suggests directions for improvement.

- An ASPN recipe by Maciej Obarski [#Obarski]_ gives a simple
scheduler for task objects represnted by generators.

Each of these implementations have specific requirements of the
microthreaded code. The requirements differ enough that code written
for one environment will generally not function properly in another.

A common pattern for all microthreaded code will allow users to write
microthreaded code that will be portable to multiple microthreading
implementations . This will include libraries, which can then be
shared more broadly.

The specification in this PEP specifically avoids reference
to any symbols not included in the built-in namespace, so
environment-agnostic microthreaded code need not import any
environment-specific modules.
Implementation Specification
=============== =============

An implementation is responsible for executing a body of code written
by its users according to the microthreading pattern.

Like a standard python thread, execution of a microthread begins with
a call to a single function, and ends when that function completes.
The function may call other functions, and so on; the entire control
flow constitutes a microthread. Completely unrelated control flows
may be occurring simultaneously in other microthreads.

Within a microthreading implementation, all microthreads operate
within a single OS-level thread, so at most one microthread is
executing at any point. The implementation must not switch between
microthreads except at times specified by the user.

A microthreaded function is written as a generator function, with
the points at which other microthreads may be executed indicated
by ``yield``. Normal (non-generator) functions thus cannot be
interrupted.

While a microthreaded function is executing, its execution is
represented by a generator. The implementation is responsible for
ensuring that this generator has its ``next``, ``send``, and ``throw``
methods called appropriately. Specifically, it must call ``next`` to
initiate processing, and ``step`` to execute each subsequent segment.
At the completion of each segment, if the return value of ``next``,
``send``, or ``throw`` is not one of the special values described
below, then that value must be supplied to the generator via ``send``
when it is next scheduled.

When the generator is complete, it will raise a ``StopIteration ``
exception, which the implementation must catch and handle by either
resuming execution of the calling function (see `Nested Function
Calls`, below) or terminating the microthread. Other exceptions
must be handled as described in the `Exceptions` section, below.
Nested Function Calls
---------------------

When a microthreaded function yields a generator, then it is invoking
another microthreaded function, the execution of which is represented
by the yielded generator. Execution of the current function must be
suspended until the new function has been executed to completion.
Any return value from the new function must be supplied to the
calling function via its generator's ``send`` method.

Although the underlying implementation may vary, the effect is of
a stack of generators within each microthread, with the topmost
generator representing the state of the currently executing
microthreaded function, and the remaining generators suspended
awaiting its completion.
Return Values
-------------

Microthreaded functions return values to their callers by raising
a ``StopIteration `` exception containing the return value in
``args[0]``. Implementations must catch this exception and handle it
appropriately by supplying the return value to the next generator on
the stack via ``send``, or if there is no next generator, terminating
the microthread.
Exceptions
----------

When a generator raises an exception, that exception must
be propagated to the next generator on the stack via ``throw``.
If there is no next generator, then the implementation may display
a traceback to the user or take other appropriate action.

Implementations may adjust tracebacks to remove implementation-related
frames, but must not alter the exception itself.
Special Values
--------------

Implementations may attach special significance to other yielded
values or raised exceptions, but these values and exceptions must
be unique objects which could not be produced by code written
with no knowledge of the implementation. Specifically, no special
significance may be attached to any of the built-in Python types or
types used in the standard library. Rather, an implementation should
attach meaning to classes and objects local to the implementation' s
namespace.
Thread Manipulation
-------------------

Implementations are responsible for providing any appropriate
functionality for manipulating microthreads. This PEP does not
place any restrictions on such functionality.
Pattern Specification
=============== ======

This section specifies the microthreading pattern from the perspective
of a user. In general, microthreaded code should closely resemble
ordinary threaded code, with the addition of ``yield`` keywords at
strategic locations.

- Microthreaded functions are written as generator functions. Their
execution will not be interrupted except at statements including
the ``yield`` keyword. The value of a ``yield`` expression is
the value of its argument, unless the argument is one of the
special values discussed in this section.

- A microthreaded function can call another microthreaded function by
yielding the generator resulting from calling the microthreaded
function. The value of the ``yield`` expression is the return
value of the called function.

- A microthreaded function can "return" a value by raising
``StopIteration `` with that value as an argument::

raise StopIteration(4 2)

- An exception raised in a microthreaded function will propagate
to its callers just as in a standard function. Uncaught exceptions
will be handled in an implementation-dependent fashion.

- Functions for thread manipulation are not specified in this PEP,
and are implementation-dependent.
Example
-------

This trivial example highlights each of the aspects of the
multithreaded pattern::

def fibonacci(n):
latest, i = (1, 1), 2
if n < 1:
raise ValueError # raise exception
while i < n:
latest = (latest[1], latest[0] + latest[1])
yield # cooperative yield
raise StopIteration(l atest[1]) # return value

def fibsquared(n):
try:
fibn = (yield fibonacci(n)) ** 2 # function call
except ValueError: # catch exception
print "Sorry, cannot calculate fibsquared of", n
else:
print "fibsquared of", n, "is", fibn
Backwards Compatibility
=============== ========

As this is an informational PEP, no backward compatibility problems
will arise from its adoption. In most cases, this PEP specifies
a superset of the functionality of existing microthreading
enviroments, so existing microthreaded code will continue to run
without modification.

One exception to this rule is Kamaelia's Axon, which specifies
that generators which yield a false value will be terminated.
That situation is not compatible with this PEP, which directs that
such a value should be returned from the yield at the next execution
of the microthread.

The specification of Kiwi tasklets requires that generators
implementing tasklets call ``tasklet.get_e vent()`` after most yields.
This is not necessary under the specification in this PEP, and the
``get_event()`` function can simply be stubbed out to ensure backward
compatibility.
Unresolved Issues
=============== ==

Return Values
-------------

Currently, a ``return`` statement with a value in a generator is
a syntax error. The Python community should consider supporting
the behavior described above in the Python compiler. Specifically,
the compiler would treat::

return foo

in a generator as equivalent to::

raise StopIteration(f oo)

This change raises no backward-compatibility issues (as the former
expression is not currently legal), but may introduce some surprising
behavior as a function could then continue executing after a return
statement::

try:
return 10
except StopIteration:
print "I'm still here!"
Non-Microthreaded Generators
----------------------------

Functions which return "normal" generators may confuse a
microthreading implementation if those generators are accidentally
yielded. Consider::

def get_constants(d ict):
return ( k for k in dict.iterkeys() if k[0] in string.uppercas e )

def examine_module( mod):
d = mod.__dict__
constants = yield get_constants(d )

this example will fail, because the implementation will treat the
generator expresion in ``get_constants `` as a microthreaded function,
calling its ``send`` method until it is exhaustd, then assigning
``None`` to ``constants`` in ``examine_modul e``.

The problem only occurs when such a generator is yielded: the
snippet above will operate correctly if ``yield`` is removed from the
last line. Thus users can avoid the problem by exercising caution
in selecting the values that are yielded.
References
==========

... [1] Stackless is not included in this list because, while it does
implement a microthreaded environment, it does so without the use
of generators and (as of this writing) requires a modified Python
binary.

... [2] PEP 342, "Coroutines via Enhanced Generators", van Rossum, Eby
(http://www.python.org/peps/pep-0342)

... [3] PEP 355, "Simple Generators", Schemenauer, Peters, Hetland
(http://www.python.org/peps/pep-0342)

... _Kiwi tasklets:
http://www.async.com.br/projects/kiw...i.tasklet.html

... _Twisted Python: http://twistedmatrix.com/

... [#inlineCallback s]
http://twistedmatrix.com/documents/c...net.defer.html

... _Kamaelia: http://kamaelia.sourceforge.net/

... [#Mertz] "Charming Python: Implementing 'weightless threads' with
Python generators," Mertz,
(http://www-128.ibm.com/developerwork.../l-pythrd.html)

... [#Obarski] "simple, cooperative multitasking using generators,"
Obarski,
http://aspn.activestate.com/ASPN/Coo.../Recipe/466008
Copyright
=========

This document has been placed in the public domain.


...
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
coding: utf-8
End:
May 1 '07 #1
4 1666
On May 1, 3:58 pm, dus...@v.igoro. us wrote:
I've been hacking away on this PEP for a while, and there has been some
related discussion on python-dev that went into the PEP:

http://mail.python.org/pipermail/pyt...ry/070921.html
http://mail.python.org/pipermail/pyt...ry/071155.html
http://mail.python.org/pipermail/pyt...ry/071181.html

I'd love to have feedback on this PEP:
- from a user's perspective (would you want to write microthreaded code?)
- from an implementer's perspective (and note that I have a reference
implementation that's just getting packaged up right now).
- from a technical perspective (efficiency, compatibility, etc.)
- regarding the two unresolved issues in the text

And now, without further ado:

PEP: XXX
Title: Standard Microthreading Pattern
Version: $Revision$
Last-Modified: $Date$
Author: Dustin J. Mitchell <dus...@cs.uchi cago.edu>
Status: Draft
Type: Informational
Content-Type: text/x-rst
Created: 17-Feb-2007
Post-History:

Abstract
========

The extended support for generators introduced in PEP 342 [2]_
facilitated a natural way of writing generators that cooperatively
yield control to other functions, allowing multitasking within
a single OS thread. Such multitasking requires a supporting
environment (usually in the form of a scheduler), and several such
implementations are in active use. Each has slightly different
structural requirements for the task-implementing code.

This PEP proposes a single, consistent pattern for such code.
This consistency will enable microthreaded code to run in a variety
of environments, just as threaded code can currently run atop a
variety of OS-level threading libraries. Compliant libraries,
e.g., a microthreaded urllib, could then be developed, providing
batteries-included functionality for microthreaded software.

Definitions
===========

Within this PEP, "microthreading " is defined as interleaving
the execution of multiple independent codepaths by cooperatively
yielding control periodically in each codepath; a "microthrea d",
then, is one such codepath. This technique and variations on it
have also been referred to as "weightless threads", "tasklets", and
"greenlets" . It is a specilization of the more general event-based
multitasking model.

Microthreads are conceptually distinct from coroutines. A coroutine
can schedule a specific coroutine to be executed when it yields
control, even passing a value to that coroutine. Microthreads,
however, simply yield to facilitate multitasking, with no knowledge
or control of the next codepath to be executed.

This PEP addresses two audiences: authors of microthreaded code
(users) and designers of microthreaded environments (implementation s).

Motivation
==========

Application developers usually adopt an event-based architecture in
order to exploit asynchronous IO facilities. Asynchronous IO is
ideal when the overhead of an OS-level thread for each concurrent
IO operation is too high.

An event-based architecture is also useful when an application must
perform lightweight multitasking -- for example, an email client
must both wait for user input and monitor mailboxes for new mail.
Implementing this sort of multitasking using threads requires careful
use of synchronization primitives throughout the application to
ensure correctness. Using common event-based techniques requires
storing state on the heap and implementing callbacks for all state
transitions, which can quickly become complex.

A microthreaded architecture brings the best of both worlds: it
allows users to store state in local varables, just as they would
in a threaded implementation, while avoiding the need for complex
synchronization primitives. An email client, for example, can
implement the complex state of an IMAP client in a natural fashion,
and reflect that state using natural Python data structures with no
need for locking.

Several well-developed implementations of cooperative multitasking
are currently available, some of which implement microthreading.
However, each implementation approaches the subject differently,
and it is virtually impossible to share code between implementations .

This PEP is intended to bring some measure of consistency to
microthreaded code, to facilitate development of libraries and
implementation-agnostic code repositories to support microthreaded
development.

Rationale
=========

Since the introduction of generators in PEP 255 [3]_ and their
extension to support coroutines in PEP 342 [2]_, generators have been
used to implement various forms of microthreading [1]_:

- Example 3 in PEP 342 implements a simple trampoline scheduler.

- `Kiwi tasklets`_ (formerly GTasklets) use pre-PEP 342 generators
along with an explicit post-yield function call to retrieve any
incoming value or exception.

- `Twisted Python`_ includes an ``inlineCallbac ks`` decorator
[#inlineCallback s]_ which allows a generator to yield ``Deferred``
objects; callback results are then re-injected with ``send()``,
while errbacks result in a ``throw()``.

- `Kamaelia`_ includes Axon, a library supporting microprocesses which
multitask by yielding frequently, and interact through a
well-developed IPC mechanism.

- David Mertz's "Charming Python: Implementing "weightless threads"
with Python generators" [#Mertz]_ includes a basic microthreading
scheduler and suggests directions for improvement.

- An ASPN recipe by Maciej Obarski [#Obarski]_ gives a simple
scheduler for task objects represnted by generators.

Each of these implementations have specific requirements of the
microthreaded code. The requirements differ enough that code written
for one environment will generally not function properly in another.

A common pattern for all microthreaded code will allow users to write
microthreaded code that will be portable to multiple microthreading
implementations . This will include libraries, which can then be
shared more broadly.

The specification in this PEP specifically avoids reference
to any symbols not included in the built-in namespace, so
environment-agnostic microthreaded code need not import any
environment-specific modules.

Implementation Specification
=============== =============

An implementation is responsible for executing a body of code written
by its users according to the microthreading pattern.

Like a standard python thread, execution of a microthread begins with
a call to a single function, and ends when that function completes.
The function may call other functions, and so on; the entire control
flow constitutes a microthread. Completely unrelated control flows
may be occurring simultaneously in other microthreads.

Within a microthreading implementation, all microthreads operate
within a single OS-level thread, so at most one microthread is
executing at any point. The implementation must not switch between
microthreads except at times specified by the user.

A microthreaded function is written as a generator function, with
the points at which other microthreads may be executed indicated
by ``yield``. Normal (non-generator) functions thus cannot be
interrupted.

While a microthreaded function is executing, its execution is
represented by a generator. The implementation is responsible for
ensuring that this generator has its ``next``, ``send``, and ``throw``
methods called appropriately. Specifically, it must call ``next`` to
initiate processing, and ``step`` to execute each subsequent segment.
At the completion of each segment, if the return value of ``next``,
``send``, or ``throw`` is not one of the special values described
below, then that value must be supplied to the generator via ``send``
when it is next scheduled.

When the generator is complete, it will raise a ``StopIteration ``
exception, which the implementation must catch and handle by either
resuming execution of the calling function (see `Nested Function
Calls`, below) or terminating the microthread. Other exceptions
must be handled as described in the `Exceptions` section, below.

Nested Function Calls
---------------------

When a microthreaded function yields a generator, then it is invoking
another microthreaded function, the execution of which is represented
by the yielded generator. Execution of the current function must be
suspended until the new function has been executed to completion.
Any return value from the new function must be supplied to the
calling function via its generator's ``send`` method.

Although the underlying implementation may vary, the effect is of
a stack of generators within each microthread, with the topmost
generator representing the state of the currently executing
microthreaded function, and the remaining generators suspended
awaiting its completion.

Return Values
-------------

Microthreaded functions return values to their callers by raising
a ``StopIteration `` exception containing the return value in
``args[0]``. Implementations must catch this exception and handle it
appropriately by supplying the return value to the next generator on
the stack via ``send``, or if there is no next generator, terminating
the microthread.

Exceptions
----------

When a generator raises an exception, that exception must
be propagated to the next generator on the stack via ``throw``.
If there is no next generator, then the implementation may display
a traceback to the user or take other appropriate action.

Implementations may adjust tracebacks to remove implementation-related
frames, but must not alter the exception itself.

Special Values
--------------

Implementations may attach special significance to other yielded
values or raised exceptions, but these values and exceptions must
be unique objects which could not be produced by code written
with no knowledge of the implementation. Specifically, no special
significance may be attached to any of the built-in Python types or
types used in the standard library. Rather, an implementation should
attach meaning to classes and objects local to the implementation' s
namespace.

Thread Manipulation
-------------------

Implementations are responsible for providing any appropriate
functionality for manipulating microthreads. This PEP does not
place any restrictions on such functionality.

Pattern Specification
=============== ======

This section specifies the microthreading pattern from the perspective
of a user. In general, microthreaded code should closely resemble
ordinary threaded code, with the addition of ``yield`` keywords at
strategic locations.

- Microthreaded functions are written as generator functions. Their
execution will not be interrupted except at statements including
the ``yield`` keyword. The value of a ``yield`` expression is
the value of its argument, unless the argument is one of the
special values discussed in this section.

- A microthreaded function can call another microthreaded function by
yielding the generator resulting from calling the microthreaded
function. The value of the ``yield`` expression is the return
value of the called function.

- A microthreaded function can "return" a value by raising
``StopIteration `` with that value as an argument::

raise StopIteration(4 2)

- An exception raised in a microthreaded function will propagate
to its callers just as in a standard function. Uncaught exceptions
will be handled in an implementation-dependent fashion.

- Functions for thread manipulation are not specified in this PEP,
and are implementation-dependent.

Example
-------

This trivial example highlights each of the aspects of the
multithreaded pattern::

def fibonacci(n):
latest, i = (1, 1), 2
if n < 1:
raise ValueError # raise exception
while i < n:
latest = (latest[1], latest[0] + latest[1])
yield # cooperative yield
raise StopIteration(l atest[1]) # return value

def fibsquared(n):
try:
fibn = (yield fibonacci(n)) ** 2 # function call
except ValueError: # catch exception
print "Sorry, cannot calculate fibsquared of", n
else:
print "fibsquared of", n, "is", fibn

Backwards Compatibility
=============== ========

As this is an informational PEP, no backward compatibility problems
will arise from its adoption. In most cases, this PEP specifies
a superset of the functionality of existing microthreading
enviroments, so existing microthreaded code will continue to run
without modification.

One exception to this rule is Kamaelia's Axon, which specifies
that generators which yield a false value will be terminated.
That situation is not compatible with this PEP, which directs that
such a value should be returned from the yield at the next execution
of the microthread.

The specification of Kiwi tasklets requires that generators
implementing tasklets call ``tasklet.get_e vent()`` after most yields.
This is not necessary under the specification in this PEP, and the
``get_event()`` function can simply be stubbed out to ensure backward
compatibility.

Unresolved Issues
=============== ==

Return Values
-------------

Currently, a ``return`` statement with a value in a generator is
a syntax error. The Python community should consider supporting
the behavior described above in the Python compiler. Specifically,
the compiler would treat::

return foo

in a generator as equivalent to::

raise StopIteration(f oo)

This change raises no backward-compatibility issues (as the former
expression is not currently legal), but may introduce some surprising
behavior as a function could then continue executing after a return
statement::

try:
return 10
except StopIteration:
print "I'm still here!"

Non-Microthreaded Generators
----------------------------

Functions which return "normal" generators may confuse a
microthreading implementation if those generators are accidentally
yielded. Consider::

def get_constants(d ict):
return ( k for k in dict.iterkeys() if k[0] in string.uppercas e )

def examine_module( mod):
d = mod.__dict__
constants = yield get_constants(d )

this example will fail, because the implementation will treat the
generator expresion in ``get_constants `` as a microthreaded function,
calling its ``send`` method until it is exhaustd, then assigning
``None`` to ``constants`` in ``examine_modul e``.

The problem only occurs when such a generator is yielded: the
snippet above will operate correctly if ``yield`` is removed from the
last line. Thus users can avoid the problem by exercising caution
in selecting the values that are yielded.

References
==========

.. [1] Stackless is not included in this list because, while it does
implement a microthreaded environment, it does so without the use
of generators and (as of this writing) requires a modified Python
binary.

.. [2] PEP 342, "Coroutines via Enhanced Generators", van Rossum, Eby
(http://www.python.org/peps/pep-0342)

.. [3] PEP 355, "Simple Generators", Schemenauer, Peters, Hetland
(http://www.python.org/peps/pep-0342)

.. _Kiwi tasklets:
http://www.async.com.br/projects/kiw...i.tasklet.html

.. _Twisted Python:http://twistedmatrix.com/

.. [#inlineCallback s]
http://twistedmatrix.com/documents/c...internet.defer...

.. _Kamaelia:http://kamaelia.sourceforge.net/

.. [#Mertz] "Charming Python: Implementing 'weightless threads' with
Python generators," Mertz,
(http://www-128.ibm.com/developerwork.../l-pythrd.html)

.. [#Obarski] "simple, cooperative multitasking using generators,"
Obarski,
http://aspn.activestate.com/ASPN/Coo.../Recipe/466008

Copyright
=========

This document has been placed in the public domain.

..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
coding: utf-8
End:
Simpy also seems to be part of this landscape, albeit in the guise of
a discrete event simulator. The Simpy engine manages Processes that
share Resources. Processes synchronize among each other by yielding
one of various values to the scheduler, which it uses to determine
when to call back to the Process. Forgive me, Simpy-ers if I have
butchered this description, my experience with Simpy is a few years
old now.

The interesting thing here is that Simpy processes do not simply yield
in order to pass control on "to whoever's next" - the value returned
with the yield dictates how the Process gets rescheduled at some time
in the future ("future" being either realtime or simulated time - a
discrete event simulator can simply advance from scheduled event to
scheduled event, without having to actually wait for the intervening
time to elapse).

-- Paul

May 1 '07 #2
On May 1, 10:58 pm, dus...@v.igoro. us wrote:
def fibonacci(n):
latest, i = (1, 1), 2
if n < 1:
raise ValueError # raise exception
while i < n:
latest = (latest[1], latest[0] + latest[1])
yield # cooperative yield
raise StopIteration(l atest[1]) # return value
There is an infinite loop here!
def fibsquared(n):
try:
fibn = (yield fibonacci(n)) ** 2 # function call
except ValueError: # catch exception
print "Sorry, cannot calculate fibsquared of", n
else:
print "fibsquared of", n, "is", fibn
It is not clear to me if you mean here

F(yield <genobj>)

as a a shortcut for

for el in <genobj>: yield F(el)

In other words, is ``fibsquared(n) .next()`` should return a value or a
generator object??

BTW, in spite of having a great tradition, the Fibonacci example sucks
as a motivation
for microthreading programming. You could show a simple state machine
instead.

Michele Simionato

May 2 '07 #3
du****@v.igoro. us wrote:
PEP: XXX
Title: Standard Microthreading Pattern
You've reinvented Modula processes.

Except that Wirth did it better in Modula I.

John Nagle
May 2 '07 #4
On Tue, May 01, 2007 at 10:28:08PM -0700, Michele Simionato wrote:
while i < n:
latest = (latest[1], latest[0] + latest[1])
yield # cooperative yield
There is an infinite loop here!
Whoops. To much editing, not enough actual running of example code :)
BTW, in spite of having a great tradition, the Fibonacci example sucks
as a motivation for microthreading programming. You could show a simple
state machine instead.
You're absolutely right, and among good company in pointing it out.
Thank you for the suggestion of an alternative!

Dustin
May 2 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
10212
by: Headless | last post by:
I've marked up song lyrics with the <pre> tag because it seems the most appropriate type of markup for the type of data. This results in inefficient use of horizontal space due to UA's default rendering of <pre> in a fixed width font. To change that I'd have to specify a proportional font family, thereby falling into the size pitfall that is associated with any sort of author specified font family: a) If I specify a sans serif font...
7
18530
by: Alan Illeman | last post by:
How do I set several different properties for PRE in a CSS stylesheet, rather than resorting to this: <BODY> <PRE STYLE="font-family:monospace; font-size:0.95em; width:40%; border:red 2px solid; color:red;
2
2785
by: Buck Turgidson | last post by:
I want to have a css with 2 PRE styles, one bold with large font, and another non-bold and smaller font. I am new to CSS (and not exactly an expert in HTML, for that matter). Is there a way to do this in CSS? <STYLE TYPE="text/css"> pre{ font-size:xx-large;
5
718
by: Michael Shell | last post by:
Greetings, Consider the XHTML document attached at the end of this post. When viewed under Firefox 1.0.5 on Linux, highlighting and pasting (into a text editor) the <pre> tag listing will preserve formatting (white space and line feeds). However, this is not true when doing the same with the <code> tag listing (it will all be pasted on one line with multiple successive spaces treated as a single space) despite the fact that...
8
3778
by: Jarno Suni not | last post by:
It seems to be invalid in HTML 4.01, but valid in XHTML 1.0. Why is there the difference? Can that pose a problem when such a XHTML document is served as text/html?
7
2741
by: Rocky Moore | last post by:
I have a web site called HintsAndTips.com. On this site people post tips using a very simply webform with a multi line TextBox for inputing the tip text. This text is encode to HTML so that no tags will remain making the page safe (I have to convert the linefeeds to <BR>s because the Server.EncodeHTML does not do that it seems). The problem is that users can use a special tag when editing the top to specify an area of the tip that will...
9
5540
by: Eric Lindsay | last post by:
I can't figure how to best display little snippets of shell script using <pre>. I just got around to organising to bulk validate some of my web pages, and one of the problems occurs with Bash shell pieces like this: <pre><code> #!/bin/sh ftp -i -n ftp.server.com&lt; &lt;EOF user username password epsv4 cd /
23
3625
by: Xah Lee | last post by:
The Concepts and Confusions of Pre-fix, In-fix, Post-fix and Fully Functional Notations Xah Lee, 2006-03-15 Let me summarize: The LISP notation, is a functional notation, and is not a so-called pre-fix notation or algebraic notation. Algebraic notations have the concept of operators, meaning, symbols placed around arguments. In algebraic in-fix notation, different
14
3626
by: Schraalhans Keukenmeester | last post by:
I am building a default sheet for my linux-related pages. Since many linux users still rely on/prefer viewing textmode and unstyled content I try to stick to the correct html tags to pertain good readibility on browsers w/o css-support. For important notes, warnings etc I use the <pre> tag, which shows in a neat bordered box when viewed with css, and depending on its class a clarifying background-image is shown. I would like the...
0
8562
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8820
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7655
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6488
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5837
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4339
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4575
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2265
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
1971
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.