[PATCH resend 03/13] msscript.ocx: Add initial IScriptModule stub implementation.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Mon Jun 1 07:21:44 CDT 2020
Hi Jacek,
On 29/05/2020 21:46, Jacek Caban wrote:
> On 29.05.2020 18:52, Jacek Caban wrote:
>> Hi Gabriel,
>>
>> On 26.05.2020 14:41, Gabriel Ivăncescu wrote:
>>> Signed-off-by: Gabriel Ivăncescu<gabrielopcode at gmail.com>
>>> ---
>>>
>>> We have to treat a ref count of 0 in a special manner when they are
>>> linked
>>> to the script control, because the modules must exist even when they
>>> have
>>> no external refs (as the script control can still use them).
>>>
>>> However, as evidenced by the tests, they must*not* keep a ref to the
>>> script
>>> control in this case, as it would create a circular ref and make no
>>> sense,
>>> anyway.
>>>
>>> The alternative solution to allocate separate data for modules would
>>> require copying the data to multiple places (one for Module Collection,
>>> and one for orphaned Modules) which is more complicated, in my opinion.
>>
>>
>> There must be a cleaner way. If you need too much special treatment
>> for orphaned modules, it means that the design needs to be improved.
>> One thing that is often useful for similar cases are weak reference:
>> never reference control from module and make sure that control always
>> invalidates the module->control pointer when it actually releases the
>> object.
Ok so, I'll give some examples to illustrate why it has to be done
either this way (with refcount checks), or by allocating separate
objects for modules when requesting an external ref (on top of the
objects stored in the collection).
I will send a patch series with the latter (separate objects) to show
the alternative solution, but it does complicate the code a bit and the
enumerator as I mentioned initially... that's what I meant the first
time and why I went with the refcount checks.
So, the tests show that the behavior is like this:
Module Collection is tied to Control. Obtaining a ref to the collection,
then updating the control via put_Language, and using the older
collection ref will refer to the new control (i.e. if it had 5 modules,
then put_Language resets it back to 1, the old collection will also
report 1 module and refer to it). So keeping it on the control is the
easiest as it avoids pointless allocations in the code.
Modules are, obviously, tied to the collection (in an array for random
access by index). A collection needs module names, for example. The
control also needs access to the first (global) module to simplify the
code. So modules always exist after put_Language, even if there's no
explicit ref to them. In this case, they can't ref anything since the
caller might only hold a ref to the control.
However, consider what happens if the caller/user obtains a ref to a
module. First of all, this keeps the control alive, so releasing the ref
to the script control in this case will not destroy it, you can still
use the module ref to do stuff with it. So, a module obtained externally
needs to hold a ref to the control.
Secondly, put_Language detaches the modules from the control (or
collection). They lose their ref to the control, and operations on them
return E_FAIL.
What I did with this patch series is to hold a refcount of 0 when no
external (caller/user) refs are held to the module, but only the
control/collection can access them (and their names). Increasing
refcount to above 0 will obtain a ref to the control, since it means
they have an external ref.
put_Language would detach them from the module, releasing the control
ref only if the ref was above 0 (i.e. they had external ref), otherwise
it would simply destroy the module, as it means they had no external ref.
The alternative I will send later works like this: keep an array of
modules (without the interface) that keeps the module data in the
control/collection. When an external ref is requested, we allocate (if
it's not already, otherwise we share it) a module interface and have it
keep a ref to the control and point to the module data in the array.
put_Language would detach all the allocated objects from the control.
The end result is the same, but personally, I believe it introduces more
complexity to the code, as we have more allocations to deal with, and
more error handling (even in the enumerator). :-/
That's why I preferred the refcount check implementation, but anyway,
I'll do the alternative so you can see how it looks like and if you
prefer it.
>
>
> Or maybe script module should just store ScriptHost reference.
>
It wouldn't change much and we need a ref to the control anyway (to
start the script for example). Note that modules that haven't been
detached by put_Language must keep the control alive if they have
external refs.
Thanks,
Gabriel
More information about the wine-devel
mailing list