# Copyright 2011 James McCauley
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pox.lib.recoco as recoco
import pox.lib.revent as revent
import threading

class ReventWaiter (revent.EventMixin):
  def __init__ (self):
    self.waitEvents = set()
    revent.EventMixin.__init__(self)
    self._events = recoco.deque()
    self._task = None
    self._scheduler = None
    self._wakeLock = threading.Lock()
    self._wakeable = False

  def registerForEvent (self, eventType, once=False, weak=False, priority=None):
    return self.addListener(eventType, self._eventHandler, once, weak, priority)

  def _eventHandler (self, *args, **kw):
    self._events.append((args, kw))
    self._check()

  def _check (self):
    if len(self._events) > 0:
      if self._task != None and self._scheduler != None:
        self._wakeLock.acquire()
        if self._wakeable:
          self._wakeable = False
          self._wakeLock.release()
          self._scheduler.schedule(self._task)
        else:
          self._wakeLock.release()

  def _reset (self):
    self._wakeLock.acquire()
    self._wakeable = True
    self._wakeLock.release()

  def getEvent (self):
    try:
      return self._events.popleft()
    except:
      return None

class WaitOnEvents (recoco.BlockingOperation):
  def __init__ (self, eventWaiter):
    self._waiter = eventWaiter

  def execute (self, task, scheduler):
    #Next two should go into reset()?
    task.rv = self._waiter
    self._waiter._task = task
    self._waiter._scheduler = scheduler
    self._waiter._reset()
    self._waiter._check()

@@ -653,16 +653,46 @@
 hreading
+%0Afrom functools import partial
 %0A%0Aclass 
@@ -984,24 +984,30 @@
 ForEvent
+ByName
  (self, 
 eventTyp
@@ -998,26 +998,375 @@
  (self, 
-eventType,
+source, eventName,%0A                              once=False, weak=False, priority=None):%0A    return source.addListenerByName(eventName,%0A                                    partial(self._eventHandler, source),%0A                                    once=once, weak=weak, priority=priority)%0A%0A  def registerForEvent (self, source, eventType,%0A                       
  once=Fa
@@ -1410,19 +1410,21 @@
 return s
-elf
+ource
 .addList
@@ -1442,41 +1442,137 @@
 ype,
- self._eventHandler, 
+%0A                              partial(self._eventHandler, source),%0A                              once=
 once, 
+weak=
 weak, 
+priority=
 prio
@@ -1604,16 +1604,21 @@
 r (self,
+ src,
  *args, 
@@ -1649,16 +1649,21 @@
 append((
+src, 
 args, kw
@@ -2222,16 +2222,380 @@
 n None%0A%0A
+  def getEvents (self):%0A    r = %5B%5D%0A    while True:%0A      try:%0A        r.append(self._events.popleft())%0A      except:%0A        break%0A    return r%0A%0A  def waitAll (self):%0A    def cb (task):%0A      return self.getEvents()%0A    return WaitOnEvents(self, rf=cb)%0A%0A  def waitOne (self):%0A    def cb (task):%0A      return self.getEvent()%0A    return WaitOnEvents(self, rf=cb)%0A%0A%0A%0A
 class Wa
@@ -2666,16 +2666,25 @@
 ntWaiter
+, rf=None
 ):%0A    s
@@ -2708,16 +2708,85 @@
 ntWaiter
+%0A    self._rf = rf%0A%0A  def _default_rf (self):%0A    return self._waiter
 %0A%0A  def 
@@ -2866,17 +2866,17 @@
   task.r
-v
+f
  = self.
@@ -2876,22 +2876,52 @@
 = self._
-waiter
+rf if self._rf else self._default_rf
 %0A    sel

Improve API