@@ -16,6 +16,92 @@ namespace libcachesim {
1616
1717namespace py = pybind11;
1818
19+ typedef struct __attribute__ ((visibility(" hidden" )))
20+ pypluginAdmissioner_params {
21+ py::object data; // /< Plugin's internal data structure (python object)
22+ py::function admissioner_init_hook;
23+ py::function admissioner_admit_hook;
24+ py::function admissioner_clone_hook;
25+ py::function admissioner_update_hook;
26+ py::function admissioner_free_hook;
27+ std::string admissioner_name;
28+ } pypluginAdmissioner_params_t;
29+
30+ static bool pypluginAdmissioner_admit (admissioner_t *, const request_t *);
31+ static admissioner_t *pypluginAdmissioner_clone (admissioner_t *);
32+ static void pypluginAdmissioner_free (admissioner_t *);
33+ static void pypluginAdmissioner_update (admissioner_t *, const request_t *, const uint64_t );
34+
35+ // TODO: Free hook is currently not invoked at all, see export_cache.cpp and follow
36+ // their implementation pattern of using a custom deleter alongside std::unique_ptr
37+ admissioner_t *create_plugin_admissioner (std::string admissioner_name,
38+ py::function admissioner_init_hook,
39+ py::function admissioner_admit_hook,
40+ py::function admissioner_clone_hook,
41+ py::function admissioner_update_hook,
42+ py::function admissioner_free_hook) {
43+ admissioner_t *admissioner = nullptr ;
44+ try {
45+ admissioner = (admissioner_t *)malloc (sizeof (admissioner_t ));
46+ if (!admissioner) {
47+ throw std::runtime_error (" Failed to initialize admissioner structure" );
48+ }
49+ memset (admissioner, 0 , sizeof (admissioner_t ));
50+
51+ // We will pass a raw pointer for C++ to take ownership of
52+ admissioner->admit = pypluginAdmissioner_admit;
53+ admissioner->clone = pypluginAdmissioner_clone;
54+ admissioner->free = pypluginAdmissioner_free;
55+ admissioner->update = pypluginAdmissioner_update;
56+
57+ // Initialize pointers to python hook functions
58+ std::unique_ptr<pypluginAdmissioner_params_t> params =
59+ std::make_unique<pypluginAdmissioner_params_t>(
60+ pypluginAdmissioner_params_t ());
61+ params->data = admissioner_init_hook ();
62+ params->admissioner_admit_hook = admissioner_admit_hook;
63+ params->admissioner_clone_hook = admissioner_clone_hook;
64+ params->admissioner_update_hook = admissioner_update_hook;
65+ params->admissioner_free_hook = admissioner_free_hook;
66+ params->admissioner_name = admissioner_name;
67+
68+ // Transfer ownership of params to admissioner
69+ admissioner->params = params.release ();
70+ return admissioner;
71+
72+ } catch (...) {
73+ if (admissioner)
74+ free (admissioner);
75+ throw ;
76+ }
77+ }
78+
79+ static bool pypluginAdmissioner_admit (admissioner_t *admissioner, const request_t *req) {
80+ pypluginAdmissioner_params_t* params =
81+ (pypluginAdmissioner_params_t*)admissioner->params ;
82+ return params->admissioner_admit_hook (params->data , req).cast <bool >();
83+ }
84+
85+ static admissioner_t *pypluginAdmissioner_clone (admissioner_t *admissioner) {
86+ pypluginAdmissioner_params_t* params =
87+ (pypluginAdmissioner_params_t*)admissioner->params ;
88+ return params->admissioner_clone_hook (params->data ).cast <admissioner_t *>();
89+ }
90+
91+ static void pypluginAdmissioner_free (admissioner_t *admissioner) {
92+ pypluginAdmissioner_params_t* params =
93+ (pypluginAdmissioner_params_t*)admissioner->params ;
94+ params->admissioner_free_hook (params->data );
95+ }
96+
97+ static void pypluginAdmissioner_update (admissioner_t *admissioner,
98+ const request_t *req,
99+ const uint64_t cache_size) {
100+ pypluginAdmissioner_params_t* params =
101+ (pypluginAdmissioner_params_t*)admissioner->params ;
102+ params->admissioner_update_hook (params->data , req, cache_size);
103+ }
104+
19105template <admissioner_t *(*fn)(const char *)>
20106void export_admissioner_creator (py::module &m, const std::string &name) {
21107 m.def (
@@ -107,6 +193,7 @@ void export_admissioner(py::module &m) {
107193 // **** ****
108194 // ***********************************************************************
109195
196+ // Exposing existing implementations of admission algorithms
110197 export_admissioner_creator<create_bloomfilter_admissioner>(
111198 m, " create_bloomfilter_admissioner" );
112199 export_admissioner_creator<create_prob_admissioner>(
@@ -117,6 +204,18 @@ void export_admissioner(py::module &m) {
117204 m, " create_size_probabilistic_admissioner" );
118205 export_admissioner_creator<create_adaptsize_admissioner>(
119206 m, " create_adaptsize_admissioner" );
207+
208+ m.def (
209+ " create_plugin_admissioner" ,
210+ &create_plugin_admissioner,
211+ " admissioner_name" ,
212+ " admissioner_init_hook" ,
213+ " admissioner_admit_hook" ,
214+ " admissioner_clone_hook" ,
215+ " admissioner_update_hook" ,
216+ " admissioner_free_hook" ,
217+ py::return_value_policy::take_ownership
218+ );
120219}
121220
122221} // namespace libcachesim
0 commit comments