New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Request: Support fields on foreign classes #994
Comments
I have this problem in mind since a while, tried various solutions that where not enougth generic for me. The solution without being completely generic is to fusion |
That sounds about right to me. I don't know much about the internals yet so I was more focusing on describing the problem a I saw it :-) I wonder if there is a problem simply allowing create/destroy callbacks on ANY/every class... performance? If that was done then any class that wanted could attach some C data and the foreign distinction would cease to matter at the class level. |
I redid the fusion patch with a unified object as: typedef struct
{
Obj obj;
size_t fieldsSize;
size_t dataSize;
Value fields[FLEXIBLE_ARRAY];
// uint8_t data[FLEXIBLE_ARRAY];
} ObjMemorySegment; And I already start to see some performances degradations:
|
I made some progress, allowing foreign class to inherit from class with attributes, there is a initialization issue thought. |
Well, that's a great start. :-)
What's the issue? Wouldn't a subclass simply be the RAM allocation of each of it's prior classes in the inheritance chain combined? I think |
The issue is that you can't call an initialize method from the super class, since it would meant re-entrancy. So basically if it is mandatory to initialize an object you are doomed... In the case of foreign sub-classing a foreign class, you are in control and can call a super initialize function in C from C. |
Would you mind giving an example of what wouldn't work? |
class Foo {
construct new() {
_secret = SecretFactory.construct()
}
...
}
foreign class Bar is Foo {
foreign construct new() // here in C you can't call Foo.new(), therefore since Foo rely on _secret to be
// initialized by the constructor to function correctly, you end up in a limbo state
} |
I see now. Yeah, if we had everything except that single edge case I think that'd be a huge improvement. :-) |
What should be the behavior around inheritance of
|
Ruby might be better to answer that one... In my experience not doing the allocation is very bad mojo, but I don't know enough to know if that could or should be different for inheritance. I would say the simpler thing would be to simply always require it. In my understanding this is how the actual storage for the underlying class is created - the VM doesn't do that on it's own, though I suppose those are the bits you're fiddling with now. I mean I suppose you could do the callback and then not allocate and expect the VM to do it for you, but then why are you using a foreign class at all? If you only needed a callback you could do that with a foreign method called from inside your |
Is your request related to a specific problem you're having?
Yes. I'm work on networking for Wren CLI and the server object needs to hold some state on the C side. It also has some Wren state that is of course stored in fields. Evidently this is currently impossible so you're forced to create two classes, the Wren class and then the C foreign class - and then the Wren class must wrap the foreign class. This is because foreign classes currently do not allow fields. So you end up with something like:
This starts to feel very unwieldy. TCPServer now has to keep a reference to UVServer and vice versa (so some things can possibly be passed up the stack). And many functions (anything that requires the lower-level C data) have to be proxied down from the non-foreign class.
Perhaps UVServer will get more complex but so far I feel like I'm asked to create a whole second class and all this proxying complexity soley to attach a some small amount of data to each Wren instance on the C side. Am I missing something? Is there a better pattern here I'm not aware of?
The solution you'd prefer / feature you'd like to see added...
It would be nice if this restriction was removed - if a class could both be foreign AND have fields. A foreign class's RAM allocation might this look like:
Of course this wouldn't have to be contiguous memory, that would be an implementation detail.
Any alternative solutions you considered...
destroy
callback that passed the number back to C again where the memory could deallocated and then the handle returned viawrenReleaseHandle
.I haven't tried this, it's just what popped into my head.
Perhaps only using the foreign class as a data wrapper and NOTHING more... I have a feeling that might just push the proxying complexity into main class, but on the C side? Example: to close the connection I need the data structures from the C side... so if
close
was a foreign method onTCPServer
the first thing it would have to do is access_uv
to get the underlying data so that it can close the connection. I suppose this pattern could be abstracted a bit and perhaps would turn out better. I'm unsure.Or taken even further:
CData's
<allocate>
function could look at type (a string) and then decide how much memory needs to be allocated. The memory would only be typecast back to whatever useful structure is necessary in theforeign
functions onTCPServer
.And then on the C side:
Not terrible. I don't love any of these as much as the idea of just having fields though. :)
Additional context...
None.
The text was updated successfully, but these errors were encountered: