Add section on multi-thread issues that affect single threaded applications

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9897 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2007-08-14 20:24:26 +00:00
commit 090e3796ad

View file

@ -69,6 +69,7 @@
<li><a href="#inheritance_mirroring">Inheritance</a>
<li><a href="#proxy_classes_gc">Proxy classes and garbage collection</a>
<li><a href="#java_pgcpp">The premature garbage collection prevention parameter for proxy class marshalling</a>
<li><a href="#java_multithread_libraries">Single threaded applications and thread safety</a>
</ul>
<li><a href="#type_wrapper_classes">Type wrapper classes</a>
<li><a href="#enum_classes">Enum classes</a>
@ -2317,6 +2318,7 @@ See <a href="#imclass_pragmas">The intermediary JNI class pragmas</a> section fo
<p>
A Java proxy class is generated for each structure, union or C++ class that is wrapped.
Proxy classes have also been called <a href="http://java.sun.com/developer/JDCTechTips/2001/tt0612.html#tip2">peer classes</a>.
The default proxy class for our previous example looks like this:
</p>
@ -2866,6 +2868,94 @@ For example:
<b>Compatibility note:</b> The generation of this additional parameter did not occur in versions prior to SWIG-1.3.30.
</p>
<H4><a name="java_multithread_libraries"></a>20.4.3.5 Single threaded applications and thread safety</H4>
<p>
Single threaded Java applications using JNI need to consider thread safety.
The same applies for .NET applications using PInvoke.
Consider the C++ class:
</p>
<div class="code"><pre>
class Test {
string str;
public:
Test() : str("initial") {}
};
</pre></div>
<p>
and the Java proxy class generated by SWIG:
</p>
<div class="code"><pre>
public class Test {
private long swigCPtr;
protected boolean swigCMemOwn;
protected Test(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(Test obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
// Call C++ destructor
public synchronized void delete() {
if(swigCPtr != 0 &amp;&amp; swigCMemOwn) {
swigCMemOwn = false;
exampleJNI.delete_Test(swigCPtr);
}
swigCPtr = 0;
}
// Call C++ constructor
public Test() {
this(exampleJNI.new_Test(), true);
}
}
</pre></div>
<p>
It has two methods that call JNI methods, namely, <tt>exampleJNI.new_Test()</tt> for the C++ constructor and <tt>exampleJNI.delete_Test()</tt> for the C++ destructor.
If the garbage collector collects an instance of this class, ie <tt>delete()</tt> is not explicitly called, then the C++ destructor will be run in a different thread to the main thread.
This is because when an object is marked for garbage collection, any objects with finalizers are added to a finalization queue
and the objects in the finalization queue have their <tt>finalize()</tt> methods run in a separate finalization thread.
Therefore, if the C memory allocator is not thread safe, then the heap will get corrupted sooner or later, when a concurrent C++ delete and new are executed.
It is thus essential, even in single threaded usage, to link to the C multi-thread runtime libraries,
for example, use the /MD option for Visual C++ on Windows.
Alternatively, lock all access to C++ functions that have heap allocation/deallocation.
</p>
<p>
Note that some of the STL in Visual C++ 6 is not thread safe, so although code might be linked to the multithread runtime libraries, undefined behaviour might still occur in a single threaded Java program.
Similarly some older versions of Sun Studio have bugs in the multi-threaded implementation of the std::string class and so will lead to undefined behaviour in these supposedly single threaded Java applications.
</p>
<p>
The following innocuous Java usage of Test is an example that will crash very quickly on a multiprocessor machine if the JNI compiled code is linked against the single thread C runtime libraries.
</p>
<div class="code"><pre>
for (int i=0; i&lt;100000; i++) {
System.out.println("Iteration " + i);
for (int k=0; k&lt;10; k++) {
Test test = new Test();
}
System.gc();
}
</pre></div>
<H3><a name="type_wrapper_classes"></a>20.4.4 Type wrapper classes</H3>