Task
The concept of a process embodies 2 characteristics:
- the unit of dispatching is usually referred to as a thread or lightweight process
- the unit of resource ownership is usually referred to as a process or task
uC++ _Task (CS343)
uC++‘s _Task is the full concurrency abstraction: thread + stack + mutual exclusion. It’s a coroutine (distinguished main() member, own execution state) with its own thread of control that begins executing main on creation, plus monitor-style mutex on its public members.
_Task Worker {
int id;
void main() { // thread starts here on creation
for ( int i = 0; i < 100; i += 1 ) {
// do work...
if ( someCondition ) _Accept( pause ); // external scheduling
}
}
public:
Worker( int id ) : id( id ) {}
void pause() {} // mutex member — client calls this
void stop() {}
};Derivation from object properties
| thread? | stack? | + mutex? | = abstraction |
|---|---|---|---|
| No | No | — / _Mutex | class / monitor |
| No | Yes | — / _Mutex | _Coroutine / _Cormonitor |
| Yes | No | — / _Mutex | rejected (thread with no stack nonsensical) |
| Yes | Yes | — / _Mutex | _Task |
Missing thread ⇒ borrows caller’s thread. Missing stack ⇒ no suspend/resume state.
Scheduling
- External,
_Accept( m )inmain()picks which member to accept next. See External Scheduling - Internal,
uConditionwait/signal inside a member. See Internal Scheduling - Termination,
_Accept( stop )/_Accept( ~Task ). See Accepting the Destructor
How _Task is implemented (Buhr §9.2)
Every _Task has the same runtime-managed queue set as a _Monitor, plus a mutex queue per member:
entry queue (C)
b
mutex queues
X Y d order of
b d c arrival
a c a
condition
A
acceptor /
shared vars signalled stack (S/W)
condition
B
exit
active task blocked task duplicate entry
- Entry queue (C), newly-arrived callers to any mutex member; entered before they know which member they’ll be routed to
- Mutex queues (one per member), callers routed to a specific member (e.g.
insertvsremove);_Accept( insert )picks from theinsertqueue - Condition queues (A, B, …), tasks that called
uCondition::wait, internal scheduling - Acceptor/Signalled stack (S), LIFO stack of task’s own thread when it
_Accepts orsignals; when the accepted call finishes, the top of S resumes
Priority C < W < S means the acceptor/signaller runs next, then signalled tasks, then fresh entry-queue arrivals, this is what “no barging” concretely enforces. See Monitor Types.
_Acceptjust pushes onto S
_Accept( insert )sets a filter “only dequeue from theinsertmutex queue” and pushes the current task onto S. The scheduler then picks aninsertcaller off its mutex queue, runs it to completion (or until itwaits), then pops S and resumes the acceptor. Nested_Accepts form a stack of blocked acceptors, each resumes only after the one above it exits.
Destructor accept
~Taskis a mutex member._Accept( ~Task )inmain()causes the thread to block until some client callsdelete(or the declaring scope exits), which dequeues the destructor from its mutex queue like any other call. See Accepting the Destructor.