On Wed, Sep 7, 2016 at 10:42 PM, Ben Coman <b...@openinworld.com> wrote: > On Wed, Sep 7, 2016 at 9:09 PM, Esteban Lorenzano <esteba...@gmail.com> wrote: >> >> On 07 Sep 2016, at 14:56, Ben Coman <b...@openinworld.com> wrote: >> >> On Tue, Sep 6, 2016 at 8:08 PM, Esteban Lorenzano <esteba...@gmail.com> >> wrote: >> >> Hi, >> >> sorry for arriving so late to this, but I was on holidays :) >> this is how autoRelease works: >> >> 1) #autoRelease of an object registers object for finalisation with a >> particular executor. Then behaviour is divided: >> >> 2.1.1) for ExternalAddresses, it just registers in regular way, who will >> call #finalize on GC >> 2.1.2) finalize will just call a free assuming ExternalAddress was allocated >> (which is a malloc) >> >> 2.2.1) for all FFIExternalReference, it will register for finalisation what >> #resourceData answers (normally, the handle of the object) >> 2.2.2) finalisation process will call the object >> class>>#finalizeResourceData: method, with the #resourceData result as >> parameter >> 2.2.3) each kind of external reference can decide how to free that data (by >> default is also just freeing). >> >> An example of this is how CairoFontFace works (or AthensCairoSurface). >> >> >> >> At the bottom of FFIExternalResourceExecutor class comment I read... >> "Note that in #finalizeResourceData: you cannot >> access any other properties of your instance, >> since it is already garbage collected." >> >> But in my experiments it seems okay to access instance variables in >> #finalize. >> For example... >> >> CXString >> autoRelease >> self class finalizationRegistry add: self >> >> CXString >> finalize >> Transcript crShow: 'Finalizing CXString ' ; show: self private_flags. >> self dispose. >> Transcript show: ', done!'. >> >> CXString >>private_flags >> "This method was automatically generated" >> ^handle unsignedLongAt: 5 >> >> Libclang getClangVersion autoRelease. >> Smalltalk garbageCollect. >> "==> Finalizing CXString 1, done! " >> >> >> Is this an unlucky coincidence? Or maybe something changed from NB >> to UFFI? (There is a reference to NB there) >> >> >> yes, is a coincidence. >> the idea of using #finalizeResourceData: is that you keep minimal >> information (in general, just the handle)… this way we ensure instances will >> be collected because we will not have circular references (preventing the >> weakregistry to work). >> >> In general, you can always implement as you did it, but I would prefer the >> #finalizeResourceData: approach, even for structures. >> The only reason it is not implemented is because I didn’t reach the >> necessity, then I just skipped it (not in purpose, it was not in my head >> :P), but now is a good moment to implement it… if you want it :) > > Thanks for the offer, but hold off for the moment. I think I actually > need more than just finalization session management. To get a real > displayable string requires calling the clang_getCString() library > function. I imagine I'd like to call this from CXString>>printOn: -- > but this of course this would break after restarting the image. > > extern "C" { > const char *clang_getCString(CXString string) { > .... > return static_cast<const char *>(string.data); > }} > > typedef struct { > const void *data; > unsigned private_flags; > } CXString; > > So I think I need to register CXString with SessionManager to set *data <-- 0 > on startup. > > An alternative might be adding a session variable to CXString, > FFIExternalStructure subclass: #CXString > instanceVariableNames: 'session' > classVariableNames: '' > poolDictionaries: 'CXStringFlag' > package: 'Libclang' > > except doing so crashes when calling.... > getClangVersion > ^ self ffiCall: #( CXString clang_getClangVersion () ) module: Libclang
So this worked... CXString >> resetData handle unsignedLongAt: 1 put: 0. CXString class >> startUp: resuming resuming ifTrue: [ self allInstances do: [ :cxs | cxs resetData ] ]. CXString class >> initialize "self initialize" SessionManager default registerSystemClassNamed: self name Now immediate after a save/restart, doing... CXString allInstances first getString "==> UndefinedObject(nil)" instead of crashing the VM. Can you see/guess any traps hidden from me? Now I wonder early it is practical to prioritise such a reset. My first thought is at least before #printString starts getting called ?? cheers -ben