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 开发者_如何学Goorder for code to be "re-entrant" code?
In general, a re-entrant block of code is one that can be entered by another actor before an earlier invocation has finished, without affecting the path that the first actor would have taken through the code. That is, it is possible to re-enter the code while it's already running and still produce correct results.
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.
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.
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.
Re-entrant code is when the pages share a common resource and the resource should not be changed or manipulated. Then this resource is known as re-entrant code or pure code.
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.
Code that can be called by different threads running in parallel. So, the code:
- can have local variables (allocated on each thread's stack)
- should have guarded global and static variables, since the threads will be sharing them and there will be a race condition here.
A computer program is called reentrant if it can be interrupted in the middle of its execution and then safely called again before its previous invocations complete execution. The interruption could be caused by an internal action such as a jump or call, or by an external action such as a hardware interrupt or signal. Once the reentered invocation completes, the previous invocations will resume correct execution.
Non-reentrant example
class Test {
int count;
// Here method1() is not reentrant
int method1()
{
return count + 1;
}
}
Reentrant example
class Test {
int count;
// Here method1() is reentrant
int method1(int count)
{
return count + 1;
}
}
Simply saying, a re-entrant code is a code which can be shared among multiple process.
This is possible when the following conditions are satisfied:
- It should not have global and static data.
- It should not modify it's own code.
- It should not call another re-entrant function or code segment.
So, a code following these conditions can be called re-entrant code.
精彩评论