tags:

views:

153

answers:

4

This might be a dumb question but I've spent some time asking Google and haven't been able to find anything.

I have an an OSX OpenGL app I'm trying to modify. When I create the app a whole bunch of initialisation functions are called -- including methods where I can specify my own mouse and keyboard handlers etc. For example:

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(700, 700);
glutCreateWindow("Map Abstraction");
glutReshapeFunc(resizeWindow);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutMouseFunc(mousePressedButton);
glutMotionFunc(mouseMovedButton);
glutKeyboardFunc(keyPressed);

At some point I pass control to glutMainLoop and my application runs. In the process of running I create a whole bunch of objects. I'd like to clean these up. Is there any way I can tell GLUT to call a cleanup method before it quits?

+1  A: 

If you are using C/C++ maybe you can use an atexit() call?

Francisco Soto
Yes, I should have mentioned I'm using C++. I'm looking at a solution based on atexit but it's not so nice as specifying a cleanup callback.Anyway, it's a good suggestions. Thanks!
Daniel
A: 

Typically you don't need to do this; just exiting the application will tear down any resources you've allocated. Even if you've captured the screen, it should go back to normal.

Nicholas Riley
I don't understand; how would the GLUT know what I've malloc'd?
Daniel
It is not GLUT who does that, its the operating system. Your application closes and the OS cleans up after yourself.
Francisco Soto
-1. This is REALLY bad practice. It encourages sloppy programming practices such as not properly tracking your memory. If you have written your application correctly you should be able to unwind memory allocations easily without relying on the OS to clear up after you.
Goz
+1 to balance. It doesn't matter if its bad practice. Its HOW GLUT WORKS. The glutModalLoop function does not return, so NSApplication::Run does not return. In conditions where the framework is already promising to not do any cleanup, trying to force application objects to cleanup is a wasted effort.
Chris Becke
@Goz - aiee. If this kind of cleanup were actually necessary, it would be a bug in the OS. In fact, in OS X 10.6, Apple now explicitly encourages applications to let themselves be killed rather than gracefully shut down when possible, in order to speed up logging out: it's called sudden termination (http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSProcessInfo_Class/Reference/Reference.html#//apple_ref/doc/uid/20000316-SW3).
Nicholas Riley
@Nicholas: Alas it is this kind of approach that leads to a game like Battlefield needing to CreateProcess a new process and terminating the old at each level change. This is bad practice. I admit from looking into it that this is what GLUT encourages you to do but this is bad going. Especially with all the OpenGL driver bugs about I have doubts that the GL clean up will proceed completely ...
Goz
The questioner is asking what to do when *exiting*; if you're leaking within your app, that's your problem. Resource leaks in OpenGL drivers are bugs in the drivers; sure, you may need to work around them, but there's no need to always write as if they exist.
Nicholas Riley
A: 

If the process is going to terminate, this doesn't matter, because the system will reclaim all the memory.

Since glutMainLoop() is NOT designed to return, only 2 plausible options remain:

  1. Use atexit();
  2. Download the source and change the function; ((>_<))
jweyrich
-1 for saying it doesn't matter.
Goz
+1 to balance. With glut, it really doesn't.
Chris Becke
It DOES matter, because if you have active server/database/whatever resources, the system won't reclaim them at the end of the process.
paercebal
@paercebal What kind of resources are you referring to?All file descriptors are closed when the process terminates, except sockets with outstanding operations in cases where SO_LINGER isn't used. Still, they'll remain in TIME_WAIT state for a while, and finally die. Am I missing something else?
jweyrich
Even if it does not matter I think it would be good practice to close/dispose things yourself.
Francisco Soto
@Francisco I agree with this point of view, but glut is known for not allowing this to be done as it normally would. However, I read @paercebal mention of `glutMainLoopEvent()`, present in newer version(s) of glut, which allow you to halt the loop and do proper cleaning.
jweyrich
@jweyrich : In the C++ world, anything could be a resource. For example, you are logging data, and your log format needs a suffix upon process exit. Or you could have opened a database connection, or communicating with another process, or sharing memory, and you need to close the connection, or tell the process you did exit. The exact detail doesn't matter. In C++, resources are to be handled (RAII pattern), not to let dangling for the OS to clean behind you.
paercebal
A: 

I fell for this once in a while, trying to play with GLUT. I tried everything I could thing of, including IIRC exiting glutMainLoop through an exception catched in the main function but...

When using glutMainLoop

My solution was the following : Create a global Context object, who will be owner of all your resources, and free those resources in the destructor.

This global Context object destructor will be called immediately after exiting the main.

It is important Context is a global variable, and not a variable declared in the main function, because for a reason that still escapes me (I still fail to see the interest of this implementation choice), glutMainLoop won't return.

In my Linux box (Ubuntu), the destructor is called correctly. I guess it should work the same way on Windows and MacOS, too.

Note that this is the C++ version of Francisco Soto's atexit() solution, without the possible limitations.

Using glutMainLoopEvent

Apparently, some implementations have a glutMainLoopEvent which can be used instead of calling glutMainLoop.

http://openglut.sourceforge.net/group__mainloop.html#ga1

glutMainLoopEvent will only resolve the pending events, and then return. Thus, you must provide the event loop (the for(;;) construct) around the call to glutMainLoopEvent, but this way, you can work with a GLUT and still have control on the event loop, and free your resources when needed.

paercebal