From: William S F. <ws...@fu...> - 2006-07-31 20:43:02
|
Thomas Dudziak wrote: > Hi folks, > > after spending some more time with my earlier problem with directors > (http://article.gmane.org/gmane.comp.programming.swig/8178/match=director+java), > I finally managed to put together a sample that shows the problem. > The issue is apparently when directors are used in threads in the > C/C++ part: they cannot be deleted properly and stay in the VM > effectively preventing it from shutting down. > In the sample, the word 'Test' gets printed 10 times followed by the > word 'Finished' which signalizes that the native thread is about to > finish (incl. letting go of all listener objects). Finally, the Java > main method prints a 'Finished' and exists. However, the VM does not > shut down but stays up, apparently because of the director. > > cheers, > Tom > > ---------- > Main.java: > ---------- > > package swigtest; > > public class Main { > public static class SampleListener extends Listener { > public void callback(String msg) { > System.out.println(msg); > } > } > > public static void main(String[] args) { > SampleListener listener = new SampleListener(); > Test test = new Test(); > > test.addListener(listener); > test.start(); > test.removeListener(listener); > System.out.println("Finished"); > } > } > > ------ > Test.h > ------ > > #pragma once > > #include <windows.h> > #include <process.h> > #include <string> > #include <vector> > #include <algorithm> > > class Listener { > public: > virtual void callback(const std::wstring &msg) = 0; > }; > > static unsigned int __stdcall run(void *param); > > class Test { > public: > Test() {} > ~Test() {} > > void start() { > _threadFinished = false; > _threadHandle = _beginthreadex(NULL, > 0, > run, > this, > 0, > &_threadId); > while (!_threadFinished) { > Sleep(100); > } > notifyListeners(L"Finishing"); > removeAllListeners(); > } > > void addListener(Listener *listener) { > _listeners.push_back(listener); > } > > void removeListener(Listener *listener) { > std::vector<Listener *>::iterator it = > std::find(_listeners.begin(), _listeners.end(), listener); > > if (it != _listeners.end()) { > _listeners.erase(it); > } > } > > void removeAllListeners() { > _listeners.clear(); > } > > void notifyListeners(const std::wstring &msg) { > for (std::vector<Listener *>::iterator it = > _listeners.begin(); it != _listeners.end(); ++it) > { > (*it)->callback(msg); > } > } > > void finish() { > _threadFinished = true; > } > private: > uintptr_t _threadHandle; > unsigned int _threadId; > bool _threadFinished; > std::vector<Listener *> _listeners; > }; > > static unsigned int __stdcall run(void *param) { > Test *testObj = (Test *)param; > > for (int idx = 0; idx < 10; idx++) > { > testObj->notifyListeners(L"Test"); > Sleep(500); > } > testObj->finish(); > return 0; > } > > ----------- > swig-test.i > ----------- > > %module(directors="1") swigtest > > %{ > #include <string> > #include "Test.h" > %} > > %include "std_wstring.i" > > %feature("director") Listener; > class Listener { > public: > virtual ~Listener() {} > virtual void callback(const std::wstring &msg) = 0; > }; > > class Test { > public: > Test(); > ~Test(); > > void start(); > > void addListener(Listener *listener); > void removeListener(Listener *listener); > }; > > %pragma(java) jniclasscode=%{ > static { > System.loadLibrary("swigtest"); > } > %} > Did you try this with 1.3.29? This version has some fixes to release some unnecessary local references. William |