Example #1
0
def FairSelect(*guards):
    """ 
    It sorts the list of guards in order based on the history for
    the chosen guards in this FairSelect located at a specific line in a specific process.

    Internally it invokes a priority select on the new order of guards.
    
    Timer and Skip guards are placed with lowest priority, since it does make sence to make them
    fair.
    """
    alt_key = str(current_process_id()) + '_' + str(inspect.currentframe().f_back.f_lineno)
    A = AltHistory()
    H = A.get_history(alt_key)

    L = []
    L_last = []
    for item in guards:
        try:
            chan_name = item.g[0].channel.name
            if H.has_key(chan_name):
                L.append((H[chan_name], item.g))
            else:
                L.append((0, item.g))
        except AttributeError:
            try:
                L_last.append(item.g)
            except AttributeError:
                raise Exception('Can not use ' + str(item) + ' as guard. Only use *Guard types for AltSelect')
    L.sort()
    L = [x[1] for x in L] + L_last

    if pycsp.current.trace:
        import pycsp.common.trace as trace
        a = trace.Alternation(L)
        a.set_execute_frame(-3)
    else:
        a = Alternation(L)
        a.set_execute_frame(-2)

    result =  a.execute()
    try:
        chan_name = result[0].channel.name
        A.update_history(alt_key, chan_name)
    except:
        # Can not record skip og timer guard.
        pass
    return result
Example #2
0
def AltSelect(*guards):
    """
    AltSelect is a wrapper to Alternation with a much more intuitive
    interface. 
    It performs a prioritized choice from a list of guard objects and
    returns a tuple with the selected channel end and the read msg if
    there is one, otherwise None.

    >>> from __init__ import *

    >>> C = Channel()
    >>> cin = C.reader()

    >>> ch_end, msg = AltSelect(InputGuard(cin), SkipGuard())

    >>> if ch_end == cin:
    ...     print msg
    ... else:
    ...     print msg == None
    True


    AltSelect supports skip, timeout, input and output guards.

    >>> @choice 
    ... def callback(type, channel_input = None):
    ...    print type, channel_input

    >>> A, B = Channel('A'), Channel('B')
    >>> cin, cout = A.reader(), B.writer()
    >>> g1 = InputGuard(cin, action=callback('input'))
    >>> g2 = OutputGuard(cout, msg=[range(10),range(100)], action=callback('output'))
    >>> g3 = TimeoutGuard(seconds=0.1, action=callback('timeout'))
    
    >>> _ = AltSelect(g1, g2, g3)
    timeout None
    

    Note that AltSelect always performs the guard that was chosen,
    i.e. channel input or output is executed within the AltSelect so
    even the empty choice with an AltSelect or where
    the results are simply ignored, still performs the guarded input or
    output.

    >>> L = []

    >>> @choice 
    ... def action(channel_input):
    ...     L.append(channel_input)

    >>> @process
    ... def P1(cout, n=5):
    ...     for i in range(n):
    ...         cout(i)
    
    >>> @process
    ... def P2(cin1, cin2, n=10):
    ...     for i in range(n):
    ...         _ = AltSelect( InputGuard(cin1, action=action()), InputGuard(cin2, action=action()) )
                
    >>> C1, C2 = Channel(), Channel()
    >>> Parallel(P1(C1.writer()), P1(C2.writer()), P2(C1.reader(), C2.reader()))

    >>> len(L)
    10

    >>> L.sort()
    >>> L
    [0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
    """
    L = []
    # Build guard list
    for item in guards:
        try:
            L.append(item.g)
        except AttributeError:
            raise Exception('Cannot use ' + str(item) + ' as guard. Only use *Guard types for AltSelect')

    if pycsp.current.trace:
        import pycsp.common.trace as trace
        a = trace.Alternation(L)
        a.set_execute_frame(-3)
    else:
        a = Alternation(L)
        a.set_execute_frame(-2)

    return a.execute()