[bitc-dev] Facet pointers (aka interfaces)
Jonathan S. Shapiro
shap at eros-os.org
Sun Jan 30 22:28:16 EST 2005
On Sat, 2005-01-29 at 18:22 +0600, Constantine Plotnikov wrote:
> Jonathan S. Shapiro wrote:
> >Oh boy do I owe Constantine an apology! Just goes to prove that too much
> >coffee and too little sleep can make you really really stupid! Also
> >obnoxious. :-)
> >So first, Constantine is right. We need something like what he is
> >calling "facets." As I thought about I/O today, I realized (a) why we
> >need them and (b) that we already have them (sort-of).
> >For all externally observable purposes, a facet is simply a structure
> >all of whose member fields are procedures. For example:
> >(defstruct trivstream
> > get : (fn () char)
> > put : (fn (char) ()))
> In my proposal there is an additional field.
> (defstruct trivstream
> data : pointer-sized-integer
> get : (fn (pointer-size-integer) char)
> put : (fn (pointer-size-integer char) ()))
> See below on why.
> >We can instantiate this using something like the following:
> >(local ((define repr-state (make-stream-state))
> > (trivstream (lambda () body-returning char)
> > (lambda (char) body-consuming-char)))
> Closures like it have one of the folloing properties:
> - allocate heap memory
> - return structure of varying memory layout
> - expire after exit from function
> As far as I understand BitC goals, neither is good property.
I believe that you have misread the code above. The 'repr-state'
variable is captured. It lives as long as the corresponding facet lives.
It does NOT disappear when the procedure exits.
> - Memory allocation might be unavailble
Indeed. If memory allocation is unavailable, then this style of objects
isn't going to work.
Note, however, that I wasn't trying to capture an implementation. I was
trying to capture a usability concept. I agree that the description
above isn't the right way to do this long term. The question is: has it
captured the desired "feel"? If so, we can then figure out how to make
it work more effectively.
> - Different memory layouts for the function likely make code less
> efficient (for example by consulting some additional structure or by
> causing more code which lead to more cache misses)
You have me completely bewildered here. The behavior of the mechanism
above has precisely the same number of loads and stores as the behavior
of the customary C++ implementation of objects.
> - In IO and in exported capabilities for process there are many cases
> where facet has not to expire after exit from function.
Are you referring to the problem of garbage collecting a buffer out from
under a DMA? If so, I agree that this is a concern, but only if the I/O
mechanism is asynchronous and the garbage collector implementation is
And yes, the mechanism that I outlined is only viable in a garbage
collected environment. As I say, I wasn't trying to propose an
implementation. I was trying to understand if "structure of procedures"
captures the feel you are after.
> In my proposal it is a bit different. The context is provided explictly
> rather than implicitly at it is in case with closures. Also facet
> datatype is small enough to be passed by value rather then by reference.
Providing the state explicitly is an invitation to a type mismatch. In
any case, it was provided explicitly above by the LOCAL form.
The issue of parameter passing is a side issue. How to resolve this is
tied up with how the state of the object is represented, and in any case
I did ask whether we should have a vtable-like structure (which is what
you seem to be proposing).
The conversion of pointers to integers that you propose is an entirely
> >(defstruct (facet-rep 'a)
> > state : 'a
> > methods : (struct-containing-methods 'a))
> Formally speacking it is:
> (defstruct (facet-rep 'a 'b)
> state : 'b
> methods : (struct-containing-methods 'a))
Um. I don't believe so. The syntax
means that the STRUCT-CONTAINING-METHODS is a type constructor that is
parameterized over the type variable 'a (the type of the state).
Therefore, it seems important that the state *also* have type 'a.
> In facet design I'm attempting to make the structure an assignment
Assignment compatibility is a fine goal, and indeed if this is the goal
then you want the type of the embedded state pointer to be opaque. This
is not the same as saying "pointer-sized-integer", which, as far as I
can tell, simply serves to evade the type system.
More information about the bitc-dev