Discussion:
WinInitialize in rexx dll - why?
(too old to reply)
Michael Greene
2008-01-15 02:17:12 UTC
Permalink
Raw Message
I was looking through the SysIni function in the sample provided in the
OS/2 toolkit and I see the following:


BOOL terminate = TRUE; /* perform WinTerminate call */

... code ...


hab = WinInitialize((USHORT)0); /* create anchor block */


if (!hab) { /* already done? get desktop anchor */
hab = WinQueryAnchorBlock(HWND_DESKTOP);

terminate = FALSE; /* don't terminate */
}


... code ...

if (terminate) WinTerminate(hab); /* destroy anchor block */



and before exit points:

if (terminate) WinTerminate(hab);


I don't understand why this is needed or better put, I don't see in in
the docs where this is required. Am I missing something?

Mike
Rich Walsh
2008-01-15 06:46:03 UTC
Permalink
Raw Message
Post by Michael Greene
I was looking through the SysIni function in the sample provided in the
BOOL terminate = TRUE; /* perform WinTerminate call */
... code ...
hab = WinInitialize((USHORT)0); /* create anchor block */
if (!hab) { /* already done? get desktop anchor */
hab = WinQueryAnchorBlock(HWND_DESKTOP);
terminate = FALSE; /* don't terminate */
}
... code ...
if (terminate) WinTerminate(hab); /* destroy anchor block */
if (terminate) WinTerminate(hab);
I don't understand why this is needed or better put, I don't see in in
the docs where this is required. Am I missing something?
Before calling any PM functions, you need to initialize PM for that thread.
Of course, if you allocate resources you should free them when you're done.
However, it's possible that some other code already did the init, in which
case you certainly shouldn't free stuff that other code may still need.

This code is designed to ensure that WinInitialize() has been called and
to determine whether it should call WinTerminate() or leave that task to
some other code.

If WinInitialize() hasn't been called previously, it will return a HAB.
The non-zero return signals that this code should call WinTerminate().
If it has been called previously, the second call will generate an error
and return zero, signaling that this code shouldn't call WinTerminate().
Since the code needs a HAB to pass to subsequent calls, it retrieves the
current HAB by calling WinQueryAnchorBlock().

Note: this code appears to ignore one possibility: that it's operating
in a non-PM environment where WinInitialize() and WinQueryAnchorBlock()
will always fail. It may be that the author chose to ignore that here
and instead deals with it when a subsequent Prf* call fails (if PM isn't
present, ini-access functions will also always fail).
--
== == almost usable email address: Rich AT E-vertise.Com == ==
___________________________________________________________________
|
| New! DragText v3.9 with NLS support
Rich Walsh | A Distinctly Different Desktop Enhancement
Ft Myers, FL | http://e-vertise.com/dragtext/
___________________________________________________________________
Alex Taylor
2008-01-15 11:39:02 UTC
Permalink
Raw Message
Post by Rich Walsh
Of course, if you allocate resources you should free them when you're
done. However, it's possible that some other code already did the init,
in which case you certainly shouldn't free stuff that other code may still
need.
This code is designed to ensure that WinInitialize() has been called and
to determine whether it should call WinTerminate() or leave that task to
some other code.
I see I neglected that particular bit of logic in RXULS, although I did put
such a check in for the subsequent WinCreateMsgQueue() call. Fixed.
--
Alex Taylor
Fukushima, Japan
http://www.cs-club.org/~alex

Please take off hat when replying.
Paul Ratcliffe
2008-01-15 09:56:00 UTC
Permalink
Raw Message
Post by Michael Greene
I don't understand why this is needed or better put, I don't see in in
the docs where this is required. Am I missing something?
DLLs operate in the context of the calling process. Whatever the DLL
allocates it should free. It should not (read MUST NOT) free things it didn't
allocate, even it it uses them. A lot of people forget this very basic premise.
Ilya Zakharevich
2008-01-15 23:42:38 UTC
Permalink
Raw Message
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Paul Ratcliffe
Post by Paul Ratcliffe
Post by Michael Greene
I don't understand why this is needed or better put, I don't see in in
the docs where this is required. Am I missing something?
DLLs operate in the context of the calling process. Whatever the DLL
allocates it should free. It should not (read MUST NOT) free things it didn't
allocate, even it it uses them. A lot of people forget this very basic premise.
Sure, if you want to write buggy code, feel free to code this way...

A "more correct" way is: if you need a resource, you need a
thread-safe use counter. Chronologically-first one who needs a
resource, allocates it. Chronologically-last one who ceases to need a
resource, deallocates it.

=======================================================

But given that REXX DLLs work un absolutely undefined environment
(which resources are shared for different processes, and which are
not?), I'm not sure that even this is bullet-proof. I would not be
comfortable with freeing ANYTHING from REXX DLL; I was bitten by
another process unloading DLLs from under my nose too many times...

A conservative approach is to let users choose what he thinks is safer
in their environment: to leak resources, or to risk out-of-order
freeing of the resources.

=======================================================

So, IMO, the original code does not make too much sense. Too little,
too late...

Hope this helps,
Ilya

Loading...