# Select.py
# Andrew Francis
# December 18th, 2009
#
# This is an initial version of the Select function for Stackless.py
# The object of this version is to get Select to work and learn
# I am new to stackless.py

def select(list):
    result = None
    ready = []
    source = getcurrent()

    # is there a channel that will not block? If so, put it on the
    # ready list
    for channel, operation, value in list:
        if (channel.balance > 0 and operation == RECEIVE) or \
           (channel.balance < 0 and operation == SEND): \
              ready.append((channel,operation, value))

    """
     if there are ready channels, randomly select one
     and return from select(). In the Pike paper this is done to 
     guard against 'chatty' processes. Is this really necessary
     in the Stackless world given the difference in schedulers?
    """
    
    l = len(ready)
    if l != 0:
       unblockedChannel, operation, value = ready[random.randint(0, l - 1)]
       result = unblockedChannel._channel_action(value, operation)
    else:
      
       # for some reason, channel action does this instead of using a boolean?
       source.blocked = operation

       for channel, operation, value in list:
           channel.queue.append(source)
           channel.balance += operation
           source.selectedChannels[channel] = (operation, value)
               
       _scheduler_remove(source)

       schedule()

       #lets be safe for now
       result = source.tempval

       unblockedChannel = source.selected
       source.selected = None
       source.blocked = False
       del(source.selectedChannels[unblockedChannel])

       # now remove self from all the other channels, ouch
       for channel, (operation, value) in source.selectedChannels.items():
           channel.balance -= operation
           channel.queue.remove(source)

    return unblockedChannel, result