Re: possibly ot: thread suspension
On May 12, 9:15 am, Chris Forone <4...@gmx.at> wrote:
how does a thread suspend itself? is a volatile bool enough, that is
checked after each loop?
In contrast to Java, the volatile is not introduced for the
concurrency issues in C++ and the volatile keyword has the only effect
on compiler optimisations. Once you declared a variable volatile, the
compiler will refrain from certain optimisations. That is all. In C++,
the volatile keyword does not include atomic access as it does for
simple types in Java.
Now about the suspend issue: If there are concurrent threads of
computation going on and these threads share some variables, from the
perspective of one thread, those shared variables change values non-
deterministically. Therefore, whenever a thread inspects such a
variable and expects a certain state from that variable in order to do
some further computation, it must not just check it and do something
else if it does not apply. Rather the thread of computation should
wait for that state of condition to apply. It could do busy wait on it
as well, and if it were the only thread assigned to that physical
processor, it could certainly do that. In most cases one physical
processor carries out a number of threads of computation in an
overlapping manner. So, the run-time system rather suspends the thread
that is waiting for a certain state of condition on a shared variable.
There is a background for the necessity of waiting: If the variable is
maintained exclusively by a single thread of computation and that
thread checks that variable, the check result is either false or true
but once false it will always be false and once true it will always be
true. It is because the variable can be changed by that thread only
and that thread can have a chance to change it only if it proceeds.
The situation is different in case of the shared variables: once false
it might be true in the next moment due to a concurrent operation by
an other thread of computation.
In high level language you could just state the condition and the run-
time system arranges for the suspension if necessary. If C++ were a
high level concurrent language, you could state something like this:
shared class BoundedBuffer {
std::dequeue<int> b;
public:
int get() {
when (!b.empty()) {
return b.pop_front();
}
}
...
};
Note that the `shared' declaration denotes a critical resource, which
is protected against simultaneous access. The `when' statement
specifies in what condition the computation can proceed with the
critical action. A possible suspension is arranged automatically.
In contrast, if you work with low level libraries in C++, you have to
arrange about delaying the operation yourself. In most libraries there
is a so-called condition variable for this but you have to care about
the mutual exclusion as well:
class BoundedBuffer {
std::dequeue<int> b;
pthread_cond_t empty;
pthread_cond_t full;
pthread_mutex_t guard;
public:
int get() {
int ret;
pthread_mutex_lock(&guard);
while (b.empty()) {
pthread_cond_wait(&full, &guard);
}
ret = b.pop_front();
pthread_cond_signal(&empty);
pthread_mutex_unlock(&guard);
return ret;
}
...
};
Now you have suspended the thread in case there is no element in the
buffer. The thread would normally be awaken later on by a signal sent
from a corresponding put operation indicating that the buffer has
elements to consume.
If you want to check the return values of the library operations, your
code will be even more complex.
Best Regards,
Szabolcs