-
Notifications
You must be signed in to change notification settings - Fork 17
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
support for the BufferProtocol #26
Comments
@Stewori I want to work on that, please give hints and guide to get started. |
Are you familiar with the buffer protocol in CPython and how Jython implements it?
|
This thread from Jython mailing list is also an important read on this topic: |
The most recent changes to the buffer interface improved support for direct buffers and deprecated the type that attempts to simulate a C pointer for this specific use. The aim was to make at least the first objective possible. When passing a Jython object with the buffer protocol to a CPython extension, I would hope it were possible to create the right kind of façade to access the the byte array in store. Taking an interface freezes the object (in some sense), until a release, but that may not pin it in memory, which would have to be JyNI's responsibility for the filetime of the buffer view. This is an extension of the lock JyNI must hold on the objects it handles for the lifetime of a native call. It is surely also necessary in order to simulate the GIL on which C extensions are will rely. It seems like this locking would work unless the CPython extension is badly-behaved enough to hold C pointers to implementation, which would be an error in CPython too. Oh, and call-backs are an interesting problem. I'm missing what it is you can't do when Jython is implemented the most natural way. |
Also CPython requires a release call to PyBuffer_Release, which we would use to trigger e.g. JNI's Release[PrimitiveType]ArrayElements() (see https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp17314) However, I suspect in CPython it is less critical than in the JVM and extensions are maybe sloppier or tend to allocate buffer access for longer periods, maybe the whole runtime, but that's just a believe. So, a direct nio.ByteBuffer might be the healthier solution.
I suppose you refer to arrays. If a C-extension defines its own types etc it might expose internal, self-managed memory via buffer protocol. Since this memory would not be JVM-allocated I see no way how to make it accessible for Jython via arrays (i.e. without copying). Best solution in this case would be a direct nio.ByteBuffer. You took care to add nio.ByteBuffer support to Jython, so that should be the way to go.
I hope that JyNI's curent GIL simulation is sufficient. Anyway, a C-extension could release the GIL and still keep buffer access open (or is that invalid behavior?). So buffer allocators need to be counted. Multithreading must be considered.
What callbacks do you mean? |
Ok, we're aligned I think on getting and releasing a PyBuffer, and JyNI's responsibility to pin and un-pin the JVM array. If a C extension returns its own type that bears the (CPython) buffer interface then JyNI has to provide a Jython You keep writing direct I'm not sure about GIL simulation, but you've thought about it at length, I guess. I think you shouldn't, perhaps can't, take a global interpreter lock on Jython. But in the presence of real concurrency, are not assumptions made by CPython extensions likely to fail? I think it would be ok as long as you pin all objects you touch, and un-pin on return. In contrast, it is fine to take a buffer and return still holding it (like the constructor of a The case is hard enough where the thread that entered calls back into a Python (compiled to Java), e.g. if you sub-class |
Yes, direct is used intentionally. It refers to memory hosted outside the JVM. I suspect JVM might not allow to obtain an array view on direct ByteBuffers. However, direct ByteBuffers are IMO the only way to expose external, possibly C-extension-managed memory on Java side. In the other direction, JyNI would request a direct ByteBuffr view on a PyBuffer. If that's not possible, it would use byte array as a fallback. JyNI does not take a global interpreter lock. Its GIL only affects native code. It allows multiple threads on Java side but only one thread on native side. The native thread keeps the GIL when it calls back into JVM, but the GIL is a reentrant lock. This usually works fine because usually only a single thread is concerned in native work as extensions are designed for single threaded CPython. Or they release the GIL; JyNI supports the corresponding macros. See details in https://arxiv.org/abs/1607.00825. |
@ysz I think a good initial step would be to implement some test cases. Add some functions concerning buffer protocol operations to the DemoExtension. Add a |
PyByteArray would be the next step towards PyByteArray, BufferProtocol, SciPy and Pandas support. It should be implemented in context of overall support for the BufferProtocol
The text was updated successfully, but these errors were encountered: