Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] - نسخه متنی

David Ascher, Alex Martelli, Anna Ravenscroft

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید


Recipe 9.6. Coordinating Threads by Simple Message Passing


Credit: Michael Hobbs


Problem


You
want to write a multithreaded application, using, as the
synchronization and communication primitive, a simple yet powerful
message-passing paradigm.


Solution


The candygram module
lets you use concurrent programming semantics that are essentially
equivalent to those of the Erlang language. To use
candygram, you start by defining appropriate
classes, such as the following one, to model your
threads' functionality:

import candygram as cg
class ExampleThread(object):
""A thread-class with just a single counter value and a stop flag.""
def _ _init_ _(self):
"" Initialize the counter to 0, the running-flag to True. ""
self.val = 0
self.running = True
def increment(self):
"" Increment the counter by one. ""
self.val += 1
def sendVal(self, msg):
"" Send current value of counter to requesting thread. ""
req = msg[0]
req.send((cg.self( ), self.val))
def setStop(self):
"" Set the running-flag to False. ""
self.running = False
def run(self):
"" The entry point of the thread. ""
# Register the handler functions for various messages:
r = cg.Receiver( )
r.addHandler('increment', self.increment)
r.addHandler((cg.Process, 'value'), self.sendVal, cg.Message)
r.addHandler('stop', self.setStop)
# Keep handling new messages until a stop has been requested
while self.running:
r.receive( )

To start a thread running this code under
candygram, use:

counter = cg.spawn(ExampleThread( ).run)

To handle the counter tHRead's
responses, you need another Receiver object, with
the proper handler registered:

response = cg.Receiver( )
response.addHandler((counter, int), lambda msg: msg[1], cg.Message)

And here is an example of how you might use these
counter and response objects:

# Tell thread to increment twice
counter.send('increment')
counter.send('increment')
# Request the thread's current value, then print the thread's response
counter.send((cg.self( ), 'value'))
print response.receive( )
# Tell thread to increment one more time
counter.send('increment')
# Again, request the thread's current value,
then print the thread's response
counter.send((cg.self( ), 'value'))
print response.receive( )
# Tell the thread to stop running
counter.send('stop')


Discussion


With the candygram module (http://candygram.sourceforge.net), Python
developers can send and receive messages between threads using
semantics nearly identical to those introduced in the Erlang language
(http://www.erlang.org). Erlang
is widely respected for its elegant built-in facilities for
concurrent programming.


Erlang's approach is
simple and yet powerful. To communicate with another thread, simply
send a message to it. You do not need to worry about locks,
semaphores, mutexes, and other such primitives, to share information
among concurrent tasks. Developers of multitasking software mostly
use message passing only to implement a producer/consumer model. When
you combine message passing with the flexibility of a
Receiver object, however, it becomes much more
powerful. For example, by using timeouts and message patterns, a
thread may easily handle its messages as a state machine, or as a
priority queue.

For those who wish to become more familiar with Erlang, http://www.erlang.org/download/erlang-book-part1.pdf
(Concurrent Programming in Erlang) provides a
very complete introduction. In particular, the
candygram module implements all of the functions
described in Chapter 5 and sections 7.2, 7.3,
and 7.5 of that book.

This recipe offers a very elementary demonstration of how messages
are passed between threads using candygram. When
you run this recipe as a script, the print
statements will output the values 2 and then
3.

It's important to understand how the
candygram.Receiver class works. The
addHandler method requires at least two
parameters: the first is a message pattern and the second is a
handler function. The Receiver.receive method
invokes a registered handler function, and returns that
function's result, whenever it finds a message that
matches the associated pattern. Any parameters optionally passed to
addHandler beyond the first two get passed as
parameters to the handler function when the
Receiver calls it. If a parameter is the
candygram.Message constant, then
receive replaces that parameter with the matching
message when it calls the handler function.

This recipe's code contains four different message
patterns: 'increment',
(cg.Process, 'value'),
'stop', and (counter, int). The
'increment' and 'stop' patterns
are simple patterns that match any message that consists solely of
the strings 'increment' and
'stop', respectively. The (cg.Process,
'value')
pattern matches any message that is a tuple with
two items, where the first item isinstance of
cg.Process and the second item is the string
value. Lastly, the (counter,
int)
pattern matches any message that is a tuple with two
items where the first item is the counter
object and the second element is an integer.

You can find more information about the Candygram package at
http://candygram.sourceforge.net.
At that URL, you can find all details on how to specify message
patterns, how to set a timeout for the
Receiver.receive method, and how to monitor the
running status of spawned threads.


See Also


Concurrent Programming in Erlang at
http://www.erlang.org/download/erlang-book-part1.pdf;
the candygram home page at http://candygram.sourceforge.net.

/ 394