revlog: made C Capsule an array of function pointers
Although it's perfectly valid to put a function pointer in
a capsule, as we've been doing since the start of rust/hg-cpython,
an array of function pointers has several advantages:
- it can hold several functions. That's our main motivation here.
We plan to expose index_length() and index_node(), which will
be needed for a Rust implementation of nodemap.
- it could also have data
- (probably minor in the case of Mercurial) proper support for
architectures for which data and code pointers don't have the
same size.
Differential Revision: https://phab.mercurial-scm.org/D7543
--- a/mercurial/cext/revlog.c Sun Dec 22 23:09:37 2019 -0500
+++ b/mercurial/cext/revlog.c Wed Nov 27 17:59:58 2019 +0100
@@ -37,6 +37,10 @@
int children[16];
} nodetreenode;
+typedef struct {
+ int (*index_parents)(PyObject *, int, int *);
+} Revlog_CAPI;
+
/*
* A base-16 trie for fast node->rev mapping.
*
@@ -3032,6 +3036,10 @@
};
#endif /* WITH_RUST */
+static Revlog_CAPI CAPI = {
+ HgRevlogIndex_GetParents,
+};
+
void revlog_module_init(PyObject *mod)
{
PyObject *caps = NULL;
@@ -3055,11 +3063,9 @@
if (nullentry)
PyObject_GC_UnTrack(nullentry);
- caps = PyCapsule_New(HgRevlogIndex_GetParents,
- "mercurial.cext.parsers.index_get_parents_CAPI",
- NULL);
+ caps = PyCapsule_New(&CAPI, "mercurial.cext.parsers.revlog_CAPI", NULL);
if (caps != NULL)
- PyModule_AddObject(mod, "index_get_parents_CAPI", caps);
+ PyModule_AddObject(mod, "revlog_CAPI", caps);
#ifdef WITH_RUST
rustlazyancestorsType.tp_new = PyType_GenericNew;
--- a/rust/hg-cpython/src/cindex.rs Sun Dec 22 23:09:37 2019 -0500
+++ b/rust/hg-cpython/src/cindex.rs Wed Nov 27 17:59:58 2019 +0100
@@ -14,15 +14,18 @@
use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION};
use libc::c_int;
-py_capsule_fn!(
- from mercurial.cext.parsers import index_get_parents_CAPI
- as get_parents_capi
- signature (
- index: *mut RawPyObject,
- rev: c_int,
- ps: *mut [c_int; 2],
- ) -> c_int
-);
+#[repr(C)]
+pub struct Revlog_CAPI {
+ index_parents: unsafe extern "C" fn(
+ index: *mut revlog_capi::RawPyObject,
+ rev: c_int,
+ ps: *mut [c_int; 2],
+ ) -> c_int,
+}
+
+py_capsule!(
+ from mercurial.cext.parsers import revlog_CAPI
+ as revlog_capi for Revlog_CAPI);
/// A `Graph` backed up by objects and functions from revlog.c
///
@@ -58,14 +61,14 @@
/// mechanisms in other contexts.
pub struct Index {
index: PyObject,
- parents: get_parents_capi::CapsuleFn,
+ capi: &'static Revlog_CAPI,
}
impl Index {
pub fn new(py: Python, index: PyObject) -> PyResult<Self> {
Ok(Index {
index: index,
- parents: get_parents_capi::retrieve(py)?,
+ capi: unsafe { revlog_capi::retrieve(py)? },
})
}
}
@@ -75,7 +78,7 @@
let guard = Python::acquire_gil();
Index {
index: self.index.clone_ref(guard.python()),
- parents: self.parents.clone(),
+ capi: self.capi,
}
}
}
@@ -88,7 +91,7 @@
}
let mut res: [c_int; 2] = [0; 2];
let code = unsafe {
- (self.parents)(
+ (self.capi.index_parents)(
self.index.as_ptr(),
rev as c_int,
&mut res as *mut [c_int; 2],