Thursday, October 15, 2009

Reentrancer

Reentrancy is important in order to allow for safe concurrent execution.  Being reentrant, we can know that an execution of a program will be totally independent of any other execution that may be running, and therefore assures us (to whatever degree possible) that we can scale this application, such as for handling concurrent requests of different users.  We can do this without performing additional analysis to verify that the application will function as expected.

I believe that this refactoring is sufficient to create reentrancy.  To think about why this is the case, it's useful to think of how different threads of execution might come to "know" or influence one another.  When a thread/execution starts from a blank slate, it has to obtain access to resources in order to do its work.  It can either create objects of its own, or access shared state, represented in the OO world as static constructs.  Objects created by one thread cannot be seen in other threads unless a reference is somehow communicated.  This communication can essentially only happen through static constructs--hence the differentiation between mutable and immutable static constructs.  Immutable static constructs, once created, are essentially harmless as they are read-only.  Mutable static constructs, however, would open the door for this type of troubling communication.  By moving these type of constructs to a thread local type storage, each thread thinks that they are accessing an application-wide static construct, where in reality, they are accessing only their own copy, so in this way, threads are almost "tricked" into being reentrant.

Unfortunately the real world is a bit messier than this.  When it comes to libraries/system calls, external state can find its way in.  Whether it be an externally managed singleton type resource, or some externally shared medium, problems can arise.  Though it makes this tool more cumbersome to use, I think that warnings about library functions is about the best that can be expected at this point.  The semantics at the source code level are pretty straightforward, but when a library call may delegate responsibility to any sort of platform dependent implementation of some function, a tool like this couldn't expect to be able to analyze all possible cases.

I think it's pretty clear that reentrant programs are thread safe--the programmer has gone through a great deal of effort to effectively sandbox each execution so that it can't substantively interact with any other execution.  Thread safety alone, however, generally implies that resources are being shared and that attention is being paid to how these interactions occur, but the bottom line is that they still occur, hence reentrancy is not guaranteed.

No comments:

Post a Comment