Stanley M. Ho wrote:
Hi Bryan,

Bryan Atsatt wrote:
...
It seems to me that if we're going to follow this model, then:

1. There is a 1:1 relationship between ModuleDefinition instances and
Module instances.

ModuleSystem is the one actually handling the module instances'
instantiation, initialization, and release. Typically, instantiating a
Module from a ModuleDefinition through the ModuleSystem will return the
same cached Module instance for sharing, and it's 1:1. That said, the
ModuleSystem also has a releaseModule() method (see Section 7.1.4 in the
spec) that allows Module instance to be released from the cache when
necessary, and that Module instance will be GCed eventually. If a
ModuleDefinition is instantiated multiple times and each time
ModuleSystem.releaseModule() is also called for that ModuleDefinition,
it is possible to have multiple Module instances in memory for a given
ModuleDefinition, although calling getModuleInstance() method on
ModuleDefinition will only return the Module instance in the
ModuleSystem's cache.

Apparently I don't understand the use case here. Though releaseModule()
is exactly like the detach() method I put in the prototype, I realized
long ago that this pattern does not work well for isolation, as you
cannot control access to the original instances *or* the subsequent
instances--there is no "transaction" model.

A separate, private, Repository instance, OTOH, does provide such a model.

Can you please explain the use case for releaseModule()?

If there is no strong case for this, I would much prefer to stick with
the very simple 1:1 model.


2. Given #1, why does the getModuleInstance() method on ModuleDefinition
need to call through to the ModuleSystem? As it is, the ModuleSystem
must keep a separate map, which seems like overkill. The definition type
will be specific to the module system, so it can always instantiate the
correct type, and simply cache it in a field.

That's because ModuleSystem does much more than instantiating a Module
instance from a ModuleDefinition. ModuleSystem is also responsible for
initializing the Module instance to interconnect the imported modules
(and resolve potential cyclic dependencies) and to perform type
consistency checking. To do module initialization properly, ModuleSystem
needs to be aware of all the cached Module instances (so they can be
reused for sharing) and all the Module instances that are in the process
of instantiation, initialization, and release.

Of course ModuleSystem must be involved, but that is orthogonal to
*where* the instance is cached.

Would you agree that if we did not support releaseModule(), caching the
Module instance in the ModuleDefinition would eliminate some complexity?


The getModuleInstance() method on ModuleDefinition is simply a
convenience method to get to the Module instance from the ModuleSystem,
and ModuleDefinition does not keep track of any Module instance itself.
It is the ModuleSystem doing all the actual works.

3. The ModuleDefinition copy operation and semantics must be defined. We
could simply implement Cloneable, or create a copy() operation. Either
way, it needs to be clear *what* is copied; I would think we would copy
all of the data *except* for the ModuleDefinitionContent.

It is unclear to me which use case you have in mind that requires
cloning of ModuleDefinition. At a high level, the information in
ModuleDefinition can be retrieved from ModuleDefinitionContent. If you
have a ModuleDefinitionContent instance, you could simply construct new
ModuleDefinition instances with it, and you don't need cloning.

Isolation requires creating a separate repository instance that wraps
another, and hands out *copies* of definitions from the underlying instance.

We simply need a standard way to make such a copy, one that does not
require knowing the actual subtype.


- Stanley

Reply via email to