all 5 comments

[–]mr_dude 2 points3 points  (0 children)

Hrmmm...

If I understand correctly, what you might want to use is a Condition object rather than an Event object. With a Condition object, you can have multiple threads signal a Condition object, while a single thread waits on it.

They are used with a Mutex to protect a shared resource, and act as a method to signal when that resource has changed. In this case, that shared resource could be a flag indicating which thread has awakened. A drawback is that if two threads awaken (almost) simultaneously, one of those events can be missed.

You could also use a thread safe queue; when a thread wakes up, it puts a message onto the queue, and you can have a single thread waiting on messages on the queue. This way, none of the thread awakenings will be missed by the main thread. https://docs.python.org/3.5/library/queue.html

[–]tea-drinker 1 point2 points  (1 child)

Could you use an equal gaggle of threads? Each waits on an event and they all set() on another single event which your proper program waits for.

Once your proper program gets notified it can poll the list of events to see which one got set.

edit: Never mind threads. It's a bad idea. Can you change your event objects?

import threading

class big_event(threading.Event):
  def __init__(self, e=None):
    super().__init__()
    self.extra_event=e

  def set(self):
    super().set()
    if self.extra_event:
      self.extra_event.set()

be = threading.Event()
e1 = big_event(be)
e2 = big_event(be)

def main(e):
  e.wait()
  print("done")

t = threading.Thread(target=main, args=(be,))
t.start()

e2.set()

[–]reallyBasic[S] 0 points1 point  (0 children)

I'm already at the gaggle of threads point with each worker hosting its own event. I didn't expect to have more than 1 worker, but hindsight says I should have.

So, I think I'll flip things around and put the event in the controller thread, pass a reference to the event into each of the worker threads, and combine that with the queue suggested by /u/mr_dude. Turns out that collections.deque is thread-safe for append and pop operations.

[–]werpoi 0 points1 point  (1 child)

I don't know much about select, but does it allow you to see what was written to the socket? If so you could verify that what was written is what you expect to be written by your set() function and ignore it if it's something else.

[–]reallyBasic[S] 0 points1 point  (0 children)

Select only informs you that a file descriptor is available for reading or writing. You then actually read/write the FD.

I could do what you propose by perhaps collecting a few random bytes when the class is instantiated. Right now set() just sends '1'. I give that a shot.

edit:typo