.. highlight:: none .. index:: pair: threads; testing .. _design-testthr: Multi-threaded testing ====================== .. mps:prefix:: design.mps.testthr Introduction ------------ :mps:tag:`intro` This is the design of the multi-threaded testing module in the Memory Pool System. :mps:tag:`readership` Any MPS developer. :mps:tag:`overview` The MPS is designed to work in a multi-threaded environment (see design.mps.thread-safety_) and this needs to be tested on all supported platforms. The multi-threaded testing module provides an interface for creating and joining threads, so that multi-threaded test cases are portable to all platforms on which the MPS runs. .. _design.mps.thread-safety: thread-safety.html Requirements ------------ :mps:tag:`req.create` The module must provide an interface for creating threads and running code in them. (Because there is no such interface in the Standard C Library.) :mps:tag:`req.join` The module must provide an interface for joining a running thread: that is, waiting for the thread to finish and collecting a result. (Because we want to be able to test that the MPS behaves correctly when interacting with a finished thread.) :mps:tag:`req.portable` The module must be easily portable to all the platforms on which the MPS runs. :mps:tag:`req.usable` The module must be simple to use, not requiring elaborate setup or tear-down or error handling. (Because we want test cases to be easy to write.) Implementation -------------- :mps:tag:`impl.posix` To meet :mps:ref:`.req.portable` and :mps:ref:`.req.usable`, the module presents an interface that is essentially identical to the POSIX Threads interface [pthreads]_, except for the names. On POSIX platforms the implementation is trivial; on Windows it is necessary to translate the concepts back and forth. :mps:tag:`impl.storage` To meet :mps:ref:`.req.usable`, the module defines the ``testthr_t`` type in the header ``testthr.h`` (even though this requires an ``#if``), so that test cases can easily declare variables and allocate storage for thread identifiers. :mps:tag:`impl.error` To meet :mps:ref:`.req.usable`, the module does not propagate error codes, but calls :c:func:`error()` from the test library if anything goes wrong. There is thus no need for the test cases to check result codes. Interface --------- .. c:type:: testthr_t The type of thread identifiers. .. c:type:: void *(*testthr_routine_t)(void *) The type of a function that can be called when a thread is created. .. c:function:: void testthr_create(testthr_t *thread_o, testthr_routine_t start, void *arg) Create a thread. Store the identifier of the newly created thread in ``*thread_o``, and call :c:func:`start()`, passing ``arg`` as the single parameter. .. c:function:: void testthr_join(testthr_t *thread, void **result_o) Wait for a thread to complete. Suspend execution of the calling thread until the target thread terminates (if necessary), and if ``result_o`` is non-NULL, update ``*result_o`` with the return value of the thread's :c:func:`start()` function. References ---------- .. [pthreads] The Open Group; "The Single UNIX Specification, Version 2---Threads";