[closer-devel] slots on layers
Attila Lendvai
attila.lendvai at gmail.com
Mon Aug 18 21:06:39 UTC 2008
dear list,
from time to time we are returning to an important use-case that can't
(?) be done using contextl currently. what we need is slots on the
layer prototype that keep the expected semantics when layers are
restored using (current-layer-context) and (funcall-with-layer-context
...).
the problem is that if a non-special slot is defined for a layer, then
it's shared between all threads (in the slot of the single cached
prototype). but :special t slots won't work as expected either,
because they store their values in special bindings which are lost
when going through c-l-c/f-w-l-c.
our real-world use-case is this: we have a bunch of factory methods
that build up a gui component hierarchy. this algorithm is driven by
the metadata of the data model of the application. this metadata has
entities, typed properties, associations, etc, so if you define a data
model then in return you get a 90% gui that can be used to navigate
and edit the data.
to fill in the remaining 10% for each project, we need to customize
this algorithm (a bunch of layered methods), which is achived using
layers. it serves well most of the time, but often at the entry points
of this algorithm we need to store some lexically available
information in the layer instance to make it accessible deep inside
the recursive algorithm where the customized methods of the layer get
called.
the problem: the gui built by this algorithm is huge/infinite in
various directions, so it's built lazily as the data graph is
navigated. when the user clicks something in the browser, the server
potentially needs to extend the component graph by invoking some
closures. we restore the layer context when those closures are called,
but the slots of the layers are not restored.
the current contextl implementation tries hard to speed up layer
activation. for us a much simpler implementation would suffice: the
layer instance would not only be a prototype but a full instance which
is instantiated at each layer activation/deactivation and the value of
the remained slots copied over from the parent layer instance. the
instance could be directly rebound in the *layer* variable. also note
that this alternative implementation could fall back to using
prototypes when the layer has no slots (which is probably most of
the deployed usages. users, speak up! :)
we understand that this can be much slower when it comes to changing
the current effective layer, but we are not sure if this really counts
when it comes to the overall application performance. we don't know
how others are using contextl but in our usages the number of changes
to the active layers is negligable compared to the rest of the
runtime.
any thoughts?
--
attila
PS: a simple example:
CONTEXTL> (deflayer foo2 ()
((slot :initform 42 :accessor slot-of :initarg :slot :special t)))
CONTEXTL> (mapcar #'slot-of
(with-active-layers ((foo2 :slot 2))
(list (layer-context-prototype (current-layer-context))
(with-active-layers ((foo2 :slot 3))
(layer-context-prototype
(current-layer-context))))))
it returns (42 42) while we expect here to get (2 3). this effectively
means that we can't reinstate layer contexts that have slots.
More information about the closer-devel
mailing list