# chapter=3 variant=concurrent 
def make_mutex():
    cell = llist(False)
    def the_mutex(m):
        return ((the_mutex("acquire")  # retry
                 if test_and_set(cell)
                 else True)
                if m == "acquire"
                else clear(cell) if m == "release"
                else error("unknown request -- mutex", m))
    return the_mutex

def clear(cell):
    set_head(cell, False)
def make_serializer():
    mutex = make_mutex()
    def serializer(f):
        def serialized_f():
            mutex("acquire")
            val = f()
            mutex("release")
            return val
        return serialized_f
    return serializer
def make_account(balance):
    def withdraw(amount):
        nonlocal balance
        if balance > amount:
            balance = balance - amount
            return balance
        else:
            return "Insufficient funds"
    def deposit(amount):
        nonlocal balance
        balance = balance + amount
        return balance
    protect = make_serializer()
    def dispatch(m):
        return (protect(withdraw) if m == "withdraw"
                else protect(deposit) if m == "deposit"
                else protect(lambda: balance)() if m == "balance"  # serialized
                else error("unknown request -- make_account", m))
    return dispatch

my_account = make_account(100)

def t1():
    display(my_account("balance"), "T1 balance")
    my_account("withdraw")(50)
    display(my_account("balance"), "T1 balance")
    my_account("deposit")(100)

def t2():
    display(my_account("balance"), "T2 balance")
    my_account("withdraw")(50)
    display(my_account("balance"), "T2 balance")
    my_account("deposit")(100)

print(concurrent_execute(t1, t2))
