Mercurial > hg
changeset 43959:f384d68d8ea8
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
author | Georges Racinet <georges.racinet@octobus.net> |
---|---|
date | Wed, 27 Nov 2019 17:59:58 +0100 |
parents | 26cf356ae772 |
children | ab3fd8077f5e |
files | mercurial/cext/revlog.c rust/hg-cpython/src/cindex.rs |
diffstat | 2 files changed, 26 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- 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],