# Collection of code snippets by Arne Vajhøj 
# (from articles on eksperten.dk / vajhoej.dk written sometime between 2004 and now) 
import threading
import time

class Data(object):
    def __init__(self, _s):
        self.s = _s

class Processor(threading.Thread):
    def __init__(self, _d):
        super(Processor, self).__init__()
        self.d = _d
    def run(self):
        # simulate a lot of work that takes 0.1 second
        s = self.d.s
        time.sleep(0.1)
        self.d.s = s + "X"

def test(njobs, nthreads):
    # setup data
    d = []
    for i in range(njobs):
        d.append(Data("X"))
    # process
    t1 = time.time()
    k = 0
    for i in range(njobs / nthreads): # // in Python 3.x
        # create threads
        t = []
        for j in range(nthreads):
            t.append(Processor(d[k]))
            k = k + 1
        # start threads
        for j in range(nthreads):
            t[j].start()
        # wait for threads to complete
        for j in range(nthreads):
            t[j].join()
    t2 = time.time()
    print("%d jobs executing in %d threads : %.1f seconds" % (njobs, nthreads, (t2 - t1)))
    # check data
    for i in range(njobs):
        if d[i].s != "XX":
            print("Ooops")

test(256, 1)
test(256, 2)
test(256, 4)
test(256, 8)
test(256, 16)
test(256, 32)
test(256, 64)
