Closed ta0kira closed 4 years ago
Another option is to make type instances shared and remove the caches. That would make all type calls from outside of the respective type inefficient, however.
With that last option, the only sharing would be between values that were initialized from @value
functions from the same type. So, pretty much the same as not sharing and not caching.
Regardless of the solution, this will require changing the C++ API.
It's probably better to do #50 first, since updating instance semantics will break all existing C++ extensions. In particular, I don't feel like hand-editing all of the builtins.
The breaking change that uses shared_ptr
instead of &
can be made without committing to a particular caching policy. Changes to caching can then be done later without breaking existing extensions, e.g., providing a helper macro to construct GetType_Foo
, etc.
Overall, this should only break categories backed by C++ (since they could have @type
members), since the zeolite
compiler currently disallows @type
members.
One major issue I hadn't thought of is that this will require all occurrences of type instances to be shared, e.g., params stored within other type instances, and in ParamTuple
.
This also requires adding a self
variable (or similar) to all @type
-function implementations so that they don't need to GetType_Foo
/CreateType_Foo
to call other functions or to create values.
This is problematic because value construction requires the derived type (to give @value
functions access to the params), whereas self
in @type
calls will be S<TypeInstance>
. On the other hand, @value
creation requires memory allocation, which is already quite a bit slower than a cache lookup.
Also note that it's critical for the functioning of reduce
that there is no TypeInstance
duplication at any time, other than isomorphic unions and intersections.
Closing this, since TypeInstance
is now shared. I'll create a new issue if/when I decide to implement some sort of cache clearing. Caches currently use weak_ptr
, so the only thing that needs to be deallocated is the empty entries in the map
.
(Also, regarding my comment above about avoiding duplication of TypeInstance
s: This really only applies to categories that have no params.)
The main reason to do this is to remove types from the cache when they're no longer needed.
The cache can probably be handled by storing
weak_ptr
, having the type instance store an iterator to its cache entry, and removing itself in its destructor.An alternative to this is to just disallow unbounded type recursion, e.g., prohibit this:
That's probably not feasible for mutual recursion, however. Maybe the problem is using
Type<#x>
in param substitution.