0

I have the following scenario (for reference, I want to implement the UCI chess engine protocol):

I need to perform a calculation for some time x (possibly infinite). When the time is up, I want to know the current state (intermediate result) of the calculation. Additionally, I want to have some kind of stop command, which interrupts the calculation and returns the current state. Preferably, I would like to send a signal to the calculation that it should come to an end as soon as possible, instead of directly interrupting it. Moreover, the main tread should never block, but always take user input (from the command line). This user input should be processed without affecting the calculation, except when the stop signal described above is triggered.

How do I implement this in Python?

Since the main thread should listen for user input independently of the calculation, I think that the calculation should run in a separate process. One idea of implementing a timer and stop signal would be to split the calculation into parts that execute very quickly and check if it should stop in between.

timer = start_timer()
while True:
    current_result = do_next_calculation_step()
    if stop_signal_recieved or timer.time_is_up():
        break
return current_result

However, this appears quite inflexible, as it can be difficult to define do_next_calculation_step in such a way that its execution time is short.

mexx
  • 53
  • 5

1 Answers1

0

I am not sure if you are asking for Threading advice or how to build a chunked chess algorithm. If it is the former, here is an example of calculating primes in a separate thread.

def calculate_prime_after(n):
    if n == 1:
        return 2
    else:
        n = n + 1
        while True:
            for i in range(2, n):
                if n % i == 0:
                    break
            else:
                return n
            n += 1

primes = [2]
stop_calculation = False

def calculate_primes():
    print(f"Calculating primes starting with {primes[-1]}...")
    while not stop_calculation:
        primes.append(calculate_prime_after(primes[-1]))
    print(f"Calculated up to {primes[-1]}")


import threading
t = threading.Thread(target=calculate_primes)
t.start()

The work will continue until another thread (e.g. your main thread with the user interaction) will set the variable stop_calculation to True. Then, it is good form to call t.join() to wait until the thread stopped and then read the results.

# in another thread
stop_calculation = True
t.join()
print(f"Calculated up to {primes[-1]}")

But, you can also read the latest result even while the thread is still running since list append and read are thread-safe operations.

If you actually want to kill the worker without its cooperation (and losing any interim results), then you should probably use a multiprocessing.Process, but that doesn't provide such simple interaction by variables to signal the worker or read results.

Daniel Schneider
  • 1,797
  • 7
  • 20