Skip to content

Instantly share code, notes, and snippets.

@pranavsharma
Created July 25, 2023 06:43
Show Gist options
  • Save pranavsharma/21524ed737ca0b57949a96eaf1fa607d to your computer and use it in GitHub Desktop.
Save pranavsharma/21524ed737ca0b57949a96eaf1fa607d to your computer and use it in GitHub Desktop.
// Author: Pranav Sharma
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
#include <thread>
#include <iostream>
#include <chrono>
#include <mutex>
#include <queue>
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
namespace py = pybind11;
#include <pybind11/pybind11.h>
using PyCallback = std::function<void()>;
using CppCallback = std::function<void(void*)>;
struct ThreadPool {
std::mutex m;
std::queue<std::function<void(void)>> q;
std::thread t;
void Schedule(std::function<void(void)> f) {
std::lock_guard<std::mutex> l(m);
q.push(f);
}
~ThreadPool() {
t.join();
}
ThreadPool() {
t = std::thread([this](){
while (true) {
std::function<void(void)> f;
{
std::lock_guard<std::mutex> l(m);
if (!q.empty()) {
f = q.front();
q.pop();
}
}
if (f) {
f();
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
}
};
ThreadPool* tp = nullptr;
struct UserData {
PyCallback py_callback;
};
void Callback(void* user_data) {
std::cout << "Inside CPP callback\n";
UserData* user_data_holder = reinterpret_cast<UserData*>(user_data);
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
user_data_holder->py_callback();
PyGILState_Release(gstate);
}
void RunAsync(CppCallback cpp_callback, void* user_data) {
tp->Schedule([=]()->void
{
std::cout << "Inside thread..sleeping\n";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::cout << "Inside thread...done sleeping, calling cpp callback\n";
if (cpp_callback) {
cpp_callback(user_data);
}
});
}
PYBIND11_MODULE(test_python_callback, m) {
m.def("init", [](){
tp = new ThreadPool();
});
m.def("run_async", [](PyCallback py_callback)->void{
auto user_data_holder = new UserData();
user_data_holder->py_callback = py_callback;
{
//py::gil_scoped_release release;
RunAsync(Callback, user_data_holder);
}
});
#ifdef VERSION_INFO
m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO);
#else
m.attr("__version__") = "dev";
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment