# Collection of code snippets by Arne Vajhøj 
# (from articles on eksperten.dk / vajhoej.dk written sometime between 2004 and now) 
# requires Python >= 3.2
import concurrent.futures
import time

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

# non-OO as that is much simpler
def run(arg):
    d = arg[0]
    # simulate a lot of work that takes 0.1 second
    s = d.s
    time.sleep(0.1)
    d.s = s + "X"
    return d

def test(njobs, nthreads):
    # setup data
    d = []
    for i in range(njobs):
        d.append(Data("X"))
    # process
    t1 = time.time()
    executor = concurrent.futures.ThreadPoolExecutor(nthreads)
    fut = []
    for i in range(njobs):
        fut.append(executor.submit(run, [d[i]]))
    for i in range(njobs):
        d[i] = fut[i].result()
    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" + d[i].s)

if __name__ == '__main__': # necesaary as copies are forked
    test(256, 1)
    test(256, 2)
    test(256, 4)
    test(256, 8)
    test(256, 16)
    test(256, 32)
    test(256, 64)
