# alg_ostrich_count.py
#
# Do a multi-threaded operation without any locking!
#
# This is entirely a non-solution. It does not work. It has multiple
# races. There are a number of ways for it to break.
#
# If you tweak the parameters on this, or run it enough times you might
# get a correct result. This does not in any way mean that it's a correct
# algorithm!

# We want all the symbols from sim161
from sim161 import *

NUM_ITERATIONS = 100
NUM_THREADS    = 5

counter = 0
finished_counter = 0

# Don't lock - watch it break!
def do_count( myname ):
    global counter, finished_counter

    print "%s starting" % myname
    
    # Counting loop
    for i in range( 0, NUM_ITERATIONS ):
        # XXX: No lock!
        counter += 1

    # Mark ourself as done
    # XXX: This also has a race - may never quit!
    finished_counter += 1

    print "%s finishing" % myname

    # If we're the last thread to exit, display info
    # XXX: May never run because of races above
    if( finished_counter == NUM_THREADS ):
        print "%d threads * %d iterations = %d" %  \
              ( NUM_THREADS, NUM_ITERATIONS, NUM_THREADS * NUM_ITERATIONS )
        print "We counted %d" % counter
        
        if( counter == NUM_THREADS * NUM_ITERATIONS ):
            print "Correct count!"
        else:
            print "Bogus count!"
            
        exit(0)
    
##
## Main code 
##

def main( args ):

    # Start threads
    for i in range( 0, NUM_THREADS ):
        name = "thread %s" % i
        thread_create( name, do_count, name );

    
