Module Startup and Shutdown (Constructors, Destructors?)


#1

I've been trying to move toward a model extensions are just "modules that ship along with a DLL that have some native code, too". This helps avoid having parallel-and-variously-incompatible versions of the same features.

In trying to merge the functionalities, one thing that extensions could do was that when DLLs were loaded they could run an arbitrary Startup() hook. Then when the DLL was unloaded, it could run a Shutdown() hook. So if you used a native API that had a paired open/close you had a moment to do both.

However, since a module can ship with natives, this raises the question of why the startup code can't just be run as part of the normal course of the module:

 Rebol [
     Title: {ODBC Extension}
     Type: 'Module
 ]

 call-odbc-init-c-function
 odbc-settings: make object! [...]
 ...

Being able to call a native living in the extension like CALL-ODBC-INIT-C-FUNCTION is every bit as good as having a special esoteric C function exposed, that the DLL loader looks up with OS APIs and calls with a magic incantation. All that magic is already done to provide new natives to call, why not use it?

Plus you have more options--you can break it into multiple functions, have it get parameters from the environment, etc. Also very important: there doesn't have to be a distinct model for error handling if something happens--such things already had to have an answer for everything else you might be calling, why make it special for the init?

...but what about the shutdown?

It's not totally obvious that only a module which has some of its code written as user natives would need a shutdown. What if you have a module that opens a persistent network connection--all in usermode--and wants to do some kind of graceful signoff if it can? Why should "extensions" be special?

If that generic hook were available, then native code could be run by putting it in a native ACTION! and doing it that way--just like the init.

This could be a SHUTDOWN: field in the module header. Or it could be an "register-on-shutdown-callback" method that modules offer to the code running in their body (kind of the way it would offer things like EXPORT).

But it seems like maybe it should be more general. Rebol doesn't have constructors and destructors...but, maybe it should? There is now an explicit FREE which can be used to kill off an object, and only HANDLE! does cleanup...but maybe objects should be able to do something about it too.

For now the easiest thing to do to keep extensions going is just to make some module-specific solution and move on. But it's worth thinking about--are there other languages in Rebol's family which have interesting constructor/destructor behavior? Or bad behavior that would be good to know about and avoid? Just wanted to post a note on the topic...


#2

IIRC the only place in Rebol 2 that one can attach automatic cleanup code is in a port scheme, handling a port close event. Which is not exactly a generally useful solution.