User`s guide
Developing an Application [3]
The actual sequence of lines is random because the different iterations are all
executed in parallel. However, for a sequence of calls such as the following:
#pragma mta assert parallel
for (i = 0; i < n; i++)
{
fprintf(f,"this is ");
fprintf(f,"iteration %d\n", i);
}
The output may look like the following, because only the individual calls to
fprintf are atomic:
this is iteration i
this is this is iteration k
iteration j
Example 4. Calling standard I/O functions from parallel code
To avoid the previous problem, you can combine the two calls to fprintf or add
some sort of explicit synchronization. For example:
sync int flag$ = 1;
#pragma mta assert parallel
for (i = 0; i < n; i++)
{
int j = flag$; // lock
fprintf(f,"this is ");
fprintf(f,"iteration %d\n", i);
flag$ = j; // unlock
}
The previous code manipulates the sync variable flag$ to create an atomic section
that contains two calls to fprintf. The actual value loaded from and stored to
flag$ is not important because the code uses flag$ as a lock.
Example 5. Calling record-oriented I/O functions from parallel code
For record-oriented I/O, such as that which occurs when using a combination of
fseek together with fread or fwrite, you can use explicit synchronization to
ensure correct behavior, such as in the following code example:
sync int flag$ = 1;
#pragma mta assert parallel
for (i = 0; i < n; i++)
{
Buf buffer;
int j = flag$; // lock
fseek(f, i*sizeof(Buf), SEEK_SET);
fread(buffer, sizeof(Buf), 1, f);
flag$ = j; // unlock
// Work with buffer
}
S–2479–20 37