Pthreads suggests that all library functions should document whether or not they are async-cancel safe. However if the description of a function does not specifically say it is async-cancel safe you should always assume that it is not. The consequences of asynchronous cancellation in a function that is not async-cancel safe can be severe. And worse, the effects are sensitive to timing — so a function that appears to be async-cancel safe during experimentation may in fact cause all sorts of problems later when it ends up being canceled in a slightly different place.
The following program, cancel_async.c, shows the use of asynchronous cancellation in a compute-bound loop. Use of asynchronous cancellation makes this
loop "more responsive" than the deferred cancellation loop in cancel.c. However, the program would become unreliable if any function calls were made within the loop, whereas the deferred cancellation version would continue to function correctly. In most cases, synchronous cancellation is preferable.
24-28 To keep the thread running awhile with something more interesting than an empty loop, cancel_async.c uses a simple matrix multiply nested loop. The matrixa and matrixb arrays are initialized with, respectively, their major or minor array index.
34-36 The cancellation type is changed to PTHREAD_CANCEL_ASYNCHRONOUS, allowing asynchronous cancellation within the matrix multiply loops.
39-44 The thread repeats the matrix multiply until canceled, on each iteration replacing the first source array (matrixa) with the result of the previous multiplication (matrixc).
66-74 Once again, on a Solaris system, set the thread concurrency level to 2, allowing the main thread and thread_routine to run concurrently on a uniprocessor. The program will hang without this step, since user mode threads are not timesliced on Solaris.
■ cancel_async.c
1 #include
2 #include "errors.h" 3
4 #define SIZE 10 /* array size */
5
6 static int matrixa[SIZE][SIZE];
7 static int matrixb[SIZE][SIZE];
8 static int matrixc[SIZE][SIZE]; 9
10 /*
11 * Loop until canceled. The thread can be canceled at any
12 * point within the inner loop, where asynchronous cancellation
13 * is enabled. The loop multiplies the two matrices matrixa
14 * and matrixb.
15 */
16 void *thread_routine (void *arg)
17 {
18 int cancel_type, status;
19 int i, j, k, value = 1;
20
21 /*
22 * Initialize the matrices to something arbitrary.
23 */
24 for (i = 0; i < SIZE; i++)
25 for (j = 0; j < SIZE; j++) {
26 matrixa[i][j] = i;
27 matrixb[i][j] = j;
28 }
29
30 while (1) {
31 /*
32 * Compute the matrix product of matrixa and matrixb.
33 */
34 status = pthread_setcanceltype (
35 PTHREAD_CANCEL_ASYNCHRONOUS,
36 &cancel_type);
37 if (status != 0)
38 err_abort (status, "Set cancel type");
39 for (i = 0; i < SIZE; i++)
40 for (j = 0; j < SIZE; j++) {
41 matrixc[i][j] = 0;
42 for (k = 0; k < SIZE; k++)
43 matrixc[i][j] += matrixa[i][k] * matrixb[k][j];
44 }
45 status = pthread_setcanceltype (
46 cancel_type,
47 &cancel_type);
48 if (status != 0)
49 err_abort (status, "Set cancel type");
50
51 /*
52 * Copy the result (matrixc) into matrixa to start again
53 */
54 for (i = 0; i < SIZE; i++)
55 for (j = 0; j < SIZE; j++)
56 matrixa[i][j] = matrixc[i][j];
57 }
58 }
59
60 int main (int argc, char *argv[])
61 {
62 pthread_t thread_id;
63 void *result;
64 int status; 65
66 #ifdef sun
67 /*
68 * On Solaris 2.5, threads are not timesliced. To ensure