Hi, fellow-cell'ers. I have this problem: I am attempting to port an existing bunch of software to Cells - to "cellulize" it. But there is one specific aspect - a "feature" that I am using - that does not work with Cells. I ask for advice.
The "existing bunch" has made a habit of using classes with a number of ":allocation :class" slots. We occasionally have to access these slots without having access to an instance of the class; therefore we use the trick of accessing the slot-in-case of "sb-mop:class-prototype <class>".
Now this has worked just fine until I start to cellulize the classes. Then it does not work at all. I have spent some time cooking down the problem. The attached file manifests the problem when you run it on an Sbcl system.
To answer the most obvious question: no. No, I haven't tried it on CMUCL or any other LISP system capable of supporting Cells. And to the second-most obvious question, also no. No, I don't want to rewrite my current implementation to use some other technique to access class-specific information.
My - shall we call it - hope is that someone with an in-deep knowledge of Cells can spot what aspect of SBCL class implementation that Cell fails to respect. I have spent a number of days digging into this, and I must admit failure. I simply cannot figure out why Cells make this otherwise fine working feature of SBCL fail. The failure happens someplace deep down in the PCL instance allocation, where all traces of Cells override ought to have disappeared...
The problem seems to be, that when a class defined with DEFMODEL, subclass of MODEL, has a class-allocated slot, the initialization of the SB-PCL:PROTOTYPE slot triggered by the first use of SB-MOP:CLASS-PROTOTYPE - fails. Actually, it fails so thoroughly, that even the error report from the failure - eh - fails. When the access attempt is finished and the error break terminated, the SB-PCL:PROTOTYPE slot is not NIL, as it was after DEFMODEL and FINALIZE-INHERITANCE. It is unbound. However that happens - I haven't got the foggiest idea. The attached file contains a few failed attempts to work around the problem by digging deeper into the SBCL CLOS implementation.
best regards --peder chr.
Hello,
I can hardly be considered to have an in depth knowledge of Cells, so I might be completely wrong, but the problem seems to be with the print-object for model class: from family.lisp: (defmethod print-object ((self model) s) #+shhh (format s "~a" (type-of self)) (format s "~a~a" (if (mdead self) "DEAD!" "") (or (md-name self) (type-of self))))
I have no idea why this would even be called when accessing class-allocated slots, but it is, and fails because slots needed to print the prototype object are unbound. This can be worked around by setting them, adding:
(setf (slot-value (sb-mop:class-prototype (find-class 'my-model)) 'cells::.md-state) :prototype (slot-value (sb-mop:class-prototype (find-class 'my-model)) 'cells::.md-name) :prototype)
To your file after finalize-inheritance makes the example work. I have no idea if this doesn't break something, I know about PCL even less than about Cells.
Regards, Jakub Higersberger
Hello Jakub. Thanks for your answer. Well, there is no denying that your double setf makes the problem disappear in my small example. On the other hand, I would not dare to use a solution like this without knowing what the problem really is. And I still don't know that.
Modifying the content of the prototype object of a class - which is what your proposal does - is too likely to have some devastating side effects - now .MD-STATE and .MD-NAME are no longer NIL by default, as specified in the definition of MODEL, they are :PROTOTYPE...
And you are only partially right in that the problem is related to PRINT-OBJECT. I know that the error that I (and you, obviously) get looks like a problem with PRINT-OBJECT - but I think that this is because there is a deeper-lying problem that throws a condition - which then uses PRINT-OBJECT to write out something about the problem - and then that fails, too.
Next step for me will to make an attempt to make PRINT-OBJECT more robust so I can get to the "real" condition.
best regards --peder chr.
On Wednesday 20 May 2009, you wrote:
Hello,
I can hardly be considered to have an in depth knowledge of Cells, so I might be completely wrong, but the problem seems to be with the print-object for model class: from family.lisp: (defmethod print-object ((self model) s) #+shhh (format s "~a" (type-of self)) (format s "~a~a" (if (mdead self) "DEAD!" "") (or (md-name self) (type-of self))))
I have no idea why this would even be called when accessing class-allocated slots, but it is, and fails because slots needed to print the prototype object are unbound. This can be worked around by setting them, adding:
(setf (slot-value (sb-mop:class-prototype (find-class 'my-model)) 'cells::.md-state) :prototype (slot-value (sb-mop:class-prototype (find-class 'my-model)) 'cells::.md-name) :prototype)
To your file after finalize-inheritance makes the example work. I have no idea if this doesn't break something, I know about PCL even less than about Cells.
Regards, Jakub Higersberger
Peder Chr. Nørgaard wrote:
Hello Jakub. Thanks for your answer. Well, there is no denying that your double setf makes the problem disappear in my small example. On the other hand, I would not dare to use a solution like this without knowing what the problem really is. And I still don't know that.
Modifying the content of the prototype object of a class - which is what your proposal does - is too likely to have some devastating side effects - now .MD-STATE and .MD-NAME are no longer NIL by default, as specified in the definition of MODEL, they are :PROTOTYPE...
And you are only partially right in that the problem is related to PRINT-OBJECT. I know that the error that I (and you, obviously) get looks like a problem with PRINT-OBJECT - but I think that this is because there is a deeper-lying problem that throws a condition - which then uses PRINT-OBJECT to write out something about the problem - and then that fails, too.
Next step for me will to make an attempt to make PRINT-OBJECT more robust so I can get to the "real" condition.
Good plan.
Note that of course you could just lose the method if that is easier. This is just debugging code and it often bites me, too -- when stuck on a Cells issue I often end up tossing this and other print-objects.
Nothing wrong tho with an effort to make it more robust so it can just stay in place.
kt