# Tasks

**Definition**:

* Task construct defines a section of code.
* Inside a parallel region, a thread encountering a task construct will package up the task for execution.
* Some thread in the parallel region will execute the task at some point in the future.

```c
#pragma omp task [clauses]
structured-block
```

**Data Sharing**:

* The default for tasks is usually `FIRSTPRIVATE`, because the task may not be executed until later (and variables may have gone out of scope).
* Variables that are shared in all constructs starting from the innermost enclosing parallel construct are shared.

```c
#pragma omp parallel shared(A) private(B)
{
    ...
    #pragma omp task
    {
        int C;
        compute(A, B, C); // A is shared, B is firstprivate, C is private
    }
}
```

* Getting data attribute scoping right can be quite tricky, using **`default(none)`** is a good idea.

**Task complete time**:

* At thread barriers, whether explicit or implicit
  * at the end of current parallel region, there is an implicit barrier to all tasks
* At `taskwait` directive
  * Wait until all tasks defined in the current task have completed.
  * `#pragma omp taskwait`
  * Note: applies only to tasks generated in the current task, not to "descendants".

```c
// Example of taskwait: Binary Tree Traversal

void postorder(node* p) {
    if (p->left) {
        #pragma omp task
        {
            postorder(p->left);
        }
    }
    if (p->right) {
        #pragma omp task 
        {
            postorder(p->right);
        }
    }
    #pragma omp taskwait // Parent task suspended until children tasks complete
    process(p->data);
}
```

**Task switching**:

* Certain constructs have task scheduling points at defined locations within them
* When a thread encounters a task scheduling point, it is allowed to suspend the current task and execute another (called task switching)
* It can then return to the original task and resume.
* Example of **`taskyield`** from [SC15](https://www.openmp.org/wp-content/uploads/sc15-openmp-CT-MK-tasking.pdf)

```c
omp_lock_t *lock;
for (int i = 0; i < n; i++) {
    #pragma omp task
    {
        something_useful();
        while (!omp_test_lock(lock)) {
            #pragma omp taskyield
            // to make full use of computing resources 
            // and avoid deadlock situations.
        }
        something_critical();
        omp_unset_lock(lock);
    }
}
```

## Reference

* [OpenMP Tasking | SC15](https://www.openmp.org/wp-content/uploads/sc15-openmp-CT-MK-tasking.pdf)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://legacy.cookielau.com/archives/9-sc/0-readme/part7-tasks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
