Sun 02 Sep 2007 12:52:11 PM UTC, original submission:
Hi,
when including <SDL.h> in gnash.cpp as proposed in patch https://savannah.gnu.org/patch/?6180, SDL is working on OS-X insofar as all SDL calls from the main thread (which is properly initialized by SDL now), like user interface, event loop etc are properly executed, gnash is running and usable.
But SDL uses the OSX Objective C interface for I/O, so all SDL calls from other threads trying to make I/O calls (especially audio handlers) fail due to the not-initialized per-thread NSAutoreleasePool required by Objective C calls:
-----
2007-09-02 14:26:30.360 sdl-gnash[24708] *** _NSAutoreleaseNoPool(): Object 0x213bd20 of class NSCFArray autoreleased with no pool in place - just leaking
2007-09-02 14:26:30.363 sdl-gnash[24708] *** _NSAutoreleaseNoPool(): Object 0x2157a10 of class NSCFString autoreleased with no pool in place - just leaking
2007-09-02 14:26:30.399 sdl-gnash[24708] *** _NSAutoreleaseNoPool(): Object 0x210bef0 of class NSCFNumber autoreleased with no pool in place - just leaking
[...much more...]
2007-09-02 14:26:30.402 sdl-gnash[24708] *** _NSAutoreleaseNoPool(): Object 0x219f530 of class NSCFArray autoreleased with no pool in place - just leaking
2007-09-02 14:26:30.403 sdl-gnash[24708] *** _NSAutoreleaseNoPool(): Object 0x213c150 of class SDL_QuartzWindow autoreleased with no pool in place - just leaking
-----
In order to solve the problem 3 opportunities come to my mind:
- start a SDL process loop from main(), which receives and executes
all SDL commands from other threads. Now all SDL calls are
executed synchronized.
- patch relevant part of boost, in particular thread.cpp:
[cf. boost_1_34_1/libs/thread/src/thread.cpp, lines 104-112]
//{
thread_param* p = static_cast<thread_param*>(param);
boost::function0<void> threadfunc = p->m_threadfunc;
p->started();
threadfunc();
#if defined(BOOST_HAS_WINTHREADS)
on_thread_exit();
#endif
//}
Here we need to initize the NSAutoreleasePool before calling threadfunc()
and release it thenafter:
//{
thread_param* p = static_cast<thread_param*>(param);
boost::function0<void> threadfunc = p->m_threadfunc;
p->started();
NSAutoreleasePool *autoreleasepool= [[NSAutoreleasePool alloc] init];
threadfunc();
[autoreleasepool release];
#if defined(BOOST_HAS_WINTHREADS)
on_thread_exit();
#endif
//}
Unfortunately this introduces ObjC code, thus the esoteric Boost Build system
has to be modified, too, don't know how much efforts this would require.
- Handle this locally in gnash. Before calling SDL functions, the NSAutoreleasePool
has to be initialized once per thread, and when the thread dies, it has to be
released. Without per-thread-at-atexit-handlers this may be tricky to implement.
testcase:
# required libs incl. boost and SDL installed in --prefix=`pwd`/gnash/build
# gnash-configcrap-patch #6177 applied to get --prefix working
# gnash-cast-patch #6178 applied to allow compilation with g++-4.0.0
$ ./configure --prefix=`pwd`/gnash/build --disable-shared --enable-static --disable-klash --disable-cygnal --disable-docbook --disable-plugin --enable-media=ffmpeg --enable-gui=sdl --enable-renderer=agg --with-agg-incl=../agg-2.5/include/ --with-agg-lib=../agg-2.5/src
$ make
# if compilation fails due to broken libtool scripts, remove -export-dynamic from
# g++ argument lines and call g++ bypassing broken libtool and autocrap
# You should get a working sdl-gnash binary.
# Try gnash/gui/sdl-gnash test
$ ./gui/sdl-gnash ./testsuite/samples/text_formatting.swf
# Text formatting should work just fine, including mouse input...
$ ./gui/sdl-gnash ./testsuite/samples/sound1.swf
# now you should see the error messages listed above.
For more background info on NSAutoReleasePools see the Apple Developer documentation or http://www.idevgames.com/forum/archive/index.php/t-7710.html
Regards,
|