#!/usr/bin/env python
#
#
#
import os
import sys
import string
import types
import whrandom

import coro

class object_queue:

  def __init__ (self):
    # object queue
    self._queue = []
    self._c = coro.coroutine_cond()
    
  def __len__ (self):
    return len(self._queue)

  def push (self, q):
    # place data in the queue, and wake up a consumer
    self._queue.append(q)
    self._c.wake_one()
      
  def pop (self):
    # if there is nothing in the queue, wait to be awoken
    while not len(self._queue):
      self._c.wait()

    item = self._queue[0]
    del self._queue[0]
    
    return item

class critical_section:

  def __init__(self):

    self._lock  = 0
    self._error = 0
    self._c     = coro.coroutine_cond()

    return None

  def get_lock(self):

    while self._lock and not self._error:
      self._c.wait()

    if not self._error:
      self._lock = 1

    return self._error

  def release_lock(self):

    self._lock = 0
    self._c.wake_one()

    return None

  def error(self):

    self._lock  = 0
    self._error = 1
    self._c.wake_all()

    return None

class conditional_id:

  def __init__(self):

    self.__wait_map = {}
    self.__map_cond = coro.coroutine_cond()
     
  def wait(self, id):

    self.__wait_map[id] = coro.current_thread().thread_id()
    self.__map_cond.wait()

    return None
  
  def wake(self, id):

    if self.__wait_map.has_key(id):
      self.__map_cond.wake(self.__wait_map[id])
      del self.__wait_map[id]

    return None

  def wake_one(self):

    if len(self.__wait_map):
      id = whrandom.choice(self.__wait_map.keys())
      self.wake(id)

    return None

  def wake_all(self):

    self.__wait_map = {}
    self.__map_cond.wake_all()

    return None
