Pausing and Unpausing Threads

Discussion in 'Python' started by Aaron J. M., Aug 12, 2007.

  1. Aaron J. M.

    Aaron J. M. Guest

    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.
     
    Aaron J. M., Aug 12, 2007
    #1
    1. Advertising

  2. > 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
     
    =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=, Aug 12, 2007
    #2
    1. Advertising

  3. On Sat, 11 Aug 2007 18:46:16 -0700, "Aaron J. M."
    <> declaimed the following in comp.lang.python:

    > 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

    HTTP://wlfraed.home.netcom.com/
    (Bestiaria Support Staff: )
    HTTP://www.bestiaria.com/
     
    Dennis Lee Bieber, Aug 12, 2007
    #3
  4. Aaron J. M.

    Aaron J. M. Guest

    On Aug 12, 3:55 pm, Dennis Lee Bieber <> wrote:
    > 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.
     
    Aaron J. M., Aug 12, 2007
    #4
  5. Aaron J. M.

    Aaron J. M. Guest

    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.
     
    Aaron J. M., Aug 13, 2007
    #5
  6. En Sun, 12 Aug 2007 21:45:47 -0300, Aaron J. M. <>
    escribi�:

    > 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.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Aug 13, 2007
    #6
  7. Aaron J. M.

    Aaron J. M. Guest

    On Aug 13, 2:31 am, "Gabriel Genellina" <>
    wrote:
    > 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.
     
    Aaron J. M., Aug 13, 2007
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bryan R. Meyer

    Pausing Threads From Events

    Bryan R. Meyer, Apr 27, 2004, in forum: Java
    Replies:
    16
    Views:
    1,507
    NOBODY
    Apr 30, 2004
  2. C-man
    Replies:
    2
    Views:
    5,336
  3. Sharp

    Pausing in Java

    Sharp, Jan 28, 2005, in forum: Java
    Replies:
    4
    Views:
    4,188
    Tony Morris
    Jan 28, 2005
  4. Simon John
    Replies:
    12
    Views:
    655
    Simon John
    Feb 21, 2005
  5. Lucress Carol

    Pausing and continuing MFC Thread

    Lucress Carol, Sep 16, 2008, in forum: C++
    Replies:
    3
    Views:
    389
    terminator
    Sep 16, 2008
Loading...

Share This Page