Could someone tell me what code can be called "re-entrant" code? I came across this word when reading some real time operating system. What disciplines must be stuck to in order for code to be "re-entrant" code?
Many thanks =8^D
Could someone tell me what code can be called "re-entrant" code? I came across this word when reading some real time operating system. What disciplines must be stuck to in order for code to be "re-entrant" code?
Many thanks =8^D
In general, a re-entrant block of code is one that can be entered by another actor before an earlier invocation has finished. That is, it is possible to re-enter the code while it's already running.
In most cases, the "actors" are threads of the same process, but the concepts of thread safety and re-entrant are subtly different: not every thread-safe block is re-entrant, but every re-entrant block is thread-safe. That is, re-entrancy is a stronger property than thread safety. Here's a good example from Raymond Chen of how a block of code might be thread-safe but not re-entrant.
There's a special case when the code is recursive: the same actor is calling into the code before its own invocation is finished, as Marc Gravell points out. All correct recursive blocks are re-entrant; of course, not every re-entrant block is recursive.
Can another thread call the code while a first thread is in the middle of running it? If the code yields to a callback function, can the callback function itself call the code before the first runthrough has completed?
If the code uses global vars that aren't locked down, or has its own static vars that it doesn't take special precautions with, any of those scenarios might break it.
Virtually any kind of recursive code could be classified as reentrant (i.e. you can call back into the same method without having finished it), but this is used in particular when talking about locks, mutex, semaphores etc. For example, a lock is re-entrant if once you have the lock you can successfully "lock" the code again (i.e. you don't deadlock yourself) - for example:
public void AddIfNecessary(string s) {
lock(syncObj) {
if(!Contains(s)) Add(s);
}
}
public void Add(string s) {
lock(syncObj) {
list.Add(s);
}
}
public bool Contains(string s) {
lock(syncObj) {
return list.Contains(s);
}
}
Here the fact that the lock is re-entrant means we can call Contains
and Add
without worrying that we already have the "exclusive" lock, making the code simpler. Internally, a counter is used rather than a simple "in use" flag.
John Feminella's answer says:
a re-entrant block of code is one that can be entered by another actor before an earlier invocation has finished. That is, it is possible to re-enter the code while it's already running.
But that is also true of non-re-entrant block of code. If the block of code has been written without regard to this issue, it will still be possible for a second actor to enter it simultaneously.
The issue is what effect this has on the results of either invocation. So more accurately: a re-entrant block is one that can be entered by another actor before an earlier invocation has finished, without changing the outcome of either invocation.
Neither invocation should be able to detect the "presence" of the other.