#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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 compat, inspect, time

def synchronized(meth):
  args, vargs, kwargs, defs = inspect.getargspec(meth)
  scope = {}
  scope["meth"] = meth
  exec """
def %s%s:
  %s
  %s._lock.acquire()
  try:
    return meth%s
  finally:
    %s._lock.release()
""" % (meth.__name__, inspect.formatargspec(args, vargs, kwargs, defs),
       repr(inspect.getdoc(meth)), args[0],
       inspect.formatargspec(args, vargs, kwargs, defs,
                             formatvalue=lambda x: ""),
       args[0]) in scope
  return scope[meth.__name__]

class Waiter(object):

  def __init__(self, condition):
    self.condition = condition

  def wait(self, predicate, timeout=None):
    passed = 0
    start = time.time()
    while not predicate():
      if timeout is None:
        # XXX: this timed wait thing is not necessary for the fast
        # condition from this module, only for the condition impl from
        # the threading module

        # using the timed wait prevents keyboard interrupts from being
        # blocked while waiting
        self.condition.wait(3)
      elif passed < timeout:
        self.condition.wait(timeout - passed)
      else:
        return bool(predicate())
      passed = time.time() - start
    return True

  def notify(self):
    self.condition.notify()

  def notifyAll(self):
    self.condition.notifyAll()

class Condition:

  def __init__(self, lock):
    self.lock = lock
    self.waiters = []
    self.waiting = []

  def notify(self):
    assert self.lock._is_owned()
    if self.waiting:
      self.waiting[0].wakeup()

  def notifyAll(self):
    assert self.lock._is_owned()
    for w in self.waiting:
      w.wakeup()

  def wait(self, timeout=None):
    assert self.lock._is_owned()
    if not self.waiters:
      self.waiters.append(compat.selectable_waiter())
    sw = self.waiters.pop(0)
    self.waiting.append(sw)
    try:
      st = self.lock._release_save()
      sw.wait(timeout)
    finally:
      self.lock._acquire_restore(st)
      self.waiting.remove(sw)
      self.waiters.append(sw)

  def gc(self):
    assert self.lock._is_owned()
    while self.waiters:
      sw = self.waiters.pop(0)
      sw.close()
