Pausing and Unpausing Threads

A

Aaron J. M.

Hello,

This is a question about how to pause and unpause threads (as the
title suggests).

I've created an extension of threading.Thread which I'll call Server.
Server has a collection of Controlers. A Controler has a method
turn(), which lets it do various interesting things. While the
Server is running, it loops through each of its Controlers and calls
their turn() method.

One of these Controlers is a subclass called DirectedControler.
What a DirectedControler is meant to do is wait until it is given an
Action object it can invoke. Actions are basically an implementation
of the Command pattern. Actions are also invalid in certain
circumstances; they return False when executed if they didn't do
anything. Therefore, when a DirectedControler is given a turn, it
waits while:
- It has no Action
- The last Action it was given didn't do anything

Actions are sent to the DirectedControler by a Client that exists in
the main thread.

What I'm trying to figure out is how to make the DirectedControler
pause while it is waiting for a valid Action. So far I just put it
into a loop like this:

def turn(self):
while self.__action is None or not self.__action.execute():
self.__action = None # Throw away invalid actions
pass

self.__action = None # Action was valid. Clear the way for the
# next turn's Action.

Where the Action is set like this (by the Client):

def setAction(self, action):
if self.__action is None:
self.__action = action

I'm worried that this loop may wast some CPU cycles, and wonder if
there's a better way through thread synchronization using such things
as Events or Conditions.

Thank you,

Aaron J. M.
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

I'm worried that this loop may wast some CPU cycles, and wonder if
there's a better way through thread synchronization using such things
as Events or Conditions.

Typically, people are after the Queue module in such cases. Each
DirectedControl(l)er would have an instance of the Queue class,
and clients would put() actions into the queue. The controller would
get() an action from the queue, execute it, get the next action,
and so on. The get() will block when the queue is empty, so you
get synchronization for free. The queue would also accommodate the
case where multiple clients want to direct the same controller
simultaneously, by, well, queuing up the tasks.

HTH,
Martin
 
D

Dennis Lee Bieber

Hello,

This is a question about how to pause and unpause threads (as the
title suggests).

I've created an extension of threading.Thread which I'll call Server.
Server has a collection of Controlers. A Controler has a method
turn(), which lets it do various interesting things. While the
Server is running, it loops through each of its Controlers and calls
their turn() method.

One of these Controlers is a subclass called DirectedControler.
What a DirectedControler is meant to do is wait until it is given an
Action object it can invoke. Actions are basically an implementation
of the Command pattern. Actions are also invalid in certain
circumstances; they return False when executed if they didn't do
anything. Therefore, when a DirectedControler is given a turn, it
waits while:
- It has no Action
- The last Action it was given didn't do anything
By this definition, if there is no "action" supplied, a
"DirectedControler" will result in blocking ALL others (directed or not)
in this "server" (as it blocks the entire server thread).

Is that really the behavior you want?
Actions are sent to the DirectedControler by a Client that exists in
the main thread.

What I'm trying to figure out is how to make the DirectedControler
pause while it is waiting for a valid Action. So far I just put it
into a loop like this:

def turn(self):
while self.__action is None or not self.__action.execute():
self.__action = None # Throw away invalid actions
pass

That "pass" is useless.
self.__action = None # Action was valid. Clear the way for the
# next turn's Action.

Where the Action is set like this (by the Client):

def setAction(self, action):
if self.__action is None:
self.__action = action
Possible race condition -- what happens if "turn()" is just starting
to process the previous "action", so self.__action is not None. The
client code will then skip doing anything. [Also note that if you want
to indicate that an attribute is supposed to be considered private, the
convention is for ONE _, not two -- two _ sets up name mangling in
inheritance trees]

I'd suggest using a Queue PER directed controller. Initialize

self._actions = Queue.Queue()

-=-=-=-=-=-

def turn(self):
while True:
atn = self._actions.get() #blocks until at least one entry
if atn and atn.execute(): #should be in a try/except if
# action has NO execute method
break #did something, so exit while

-=-=-=-=-=-

def setAction(self, action):
self._actions.put(action) #could add code to ensure
#an execute attribute

--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
A

Aaron J. M.

By this definition, if there is no "action" supplied, a
"DirectedControler" will result in blocking ALL others (directed or not)
in this "server" (as it blocks the entire server thread).

Is that really the behavior you want?

For my particular application, yes. This is exactly what I want.
I'd suggest using a Queue PER directed controller. Initialize

self._actions = Queue.Queue()

-=-=-=-=-=-

def turn(self):
while True:
atn = self._actions.get() #blocks until at least one entry
if atn and atn.execute(): #should be in a try/except if
# action has NO execute method
break #did something, so exit while

-=-=-=-=-=-

def setAction(self, action):
self._actions.put(action) #could add code to ensure
#an execute attribute

Thank you very much for your help. :) I'll get to work on this now.

Cheers,

Aaron J. M.
 
A

Aaron J. M.

Uhg, I thought of something I didn't consider before: how to cleanly
end the Server/DirectedControl(l)er process. Assuming that the Client
only sends Actions to the DirectedController while the
DirectedController is in its turn() method (which I would probably
regulate using some flag in DirectedController) the Client will
eventually need a way to order the Server to stop its processing.
Stopping the Server also has to make the DirectedController break out
of its turn method without letting it execute an Action. I don't want
to just kill the Server thread because I may want to do serialization
or other kinds of cleanup.

Have people encountered something like this before?

Thank you,

Aaron J. M.
 
G

Gabriel Genellina

Uhg, I thought of something I didn't consider before: how to cleanly
end the Server/DirectedControl(l)er process.

Use the same Queue; put a special kind of Action, or just a None object,
to tell the thread that there are no more things to process.
From the main thread, you can join() the others, waiting for them to
finish.
 
A

Aaron J. M.

Use the same Queue; put a special kind of Action, or just a None object,
to tell the thread that there are no more things to process.
From the main thread, you can join() the others, waiting for them to
finish.

Ah, thank you very much. :)

- Aaron J. M.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top