Синхронизация связывания Python и C
Я работаю над реализацией привязок Python для моей библиотеки C в реальном времени. Я читал, что потоки в Python не являются реальными потоками и что они на самом деле не работают параллельно (из-за глобальной блокировки интерпретатора). Тем не менее, мне пришлось бы рассмотреть следующую ситуацию.
Представьте себе следующую функцию C:
int stoppable_lock(mutex *m, bool *stop)
{
while (!stop || !*stop)
if (timed_lock(m, SOME_TIME) == SUCCESS)
return SUCCESS;
return DIDNT_LOCK;
}
Эта функция ожидает мьютекса, но с помощью stop
, можно отменить. В простейшем случае, чтобы иметь возможность изящно остановить поток, используя его, независимо от того, что происходит с другими пользователями мьютекса (например, если они умирают, удерживая блокировку).
Моя проблема состоит в том, чтобы выяснить, как написать оболочку Python для этой функции. Разбор аргументов (с PyArg_ParseTuple
Я могу восстановить мьютекс, нет проблем. Тем не менее, тип объектов, которые могут быть отправлены в функцию, выглядит как строки, числа и объекты. Первые два, очевидно, не могут заменить bool *
и я сомневаюсь писать обертку для bool *
хорошая идея
У меня вопрос, как я могу получить параметр, который является ссылкой на переменную (совместно используемую с другими потоками Python), а не просто его копию?
Вот функция с частью, которую я пропускаю (для использования как mutex.stoppable_lock(stop)
):
static PyObject *_stoppable_lock(_mutex *obj, PyObject *args)
{
int ret;
BOOL_STAR stop;
if (!PyArg_ParseTuple(args, "?", &stop))
{
PyErr_SetString(PyExc_ValueError, "Usage: mutex.stoppable_lock(BOOL_STAR)");
return NULL;
}
ret = stoppable_lock(obj->orig, stop);
if (_set_exception(ret))
return NULL;
Py_RETURN_NONE;
}
Где мне неизвестно что BOOL_STAR
а также "?"
должно быть.
3 ответа
Вам нужно создать тип оболочки для bool
, с функциями мутатора Python для встроенного значения. Если вы хотите избежать создания своего собственного типа, и если вы уверены, что C _Bool совпадает с C++ bool, то вы можете использовать ctypes.c_bool. Сценарий Python может затем сделать
stop = ctypes.c_bool(False)
stoppable_lock(mutex, ctypes.addressof(stop))
а другой поток мог тогда сделать stop.value = True
, Модуль расширения будет ожидать long, а затем приведёт это к указателю. Если вы хотите, чтобы это было более безопасно для типов, вам нужно создать свой собственный тип оболочки для bool.
Потоки Python - это реальные потоки (по крайней мере, в CPython для большинства серверных реализаций потоков). Но вы правы, потому что благодаря GIL сам код Python никогда не выполняется параллельно, хотя многие функции (особенно IO) подойдут.
Относительно вашего основного вопроса: Если вы хотите напрямую следовать логике реализации C (имея ссылку на bool), NPE уже сказал это: вы можете заключить его в изменяемый объект, например:
class MutableBool:
value = False
В противном случае весь код stoppable_lock
также может быть легко переопределено в Python, и тогда оно может стать более простым.
У меня вопрос, как я могу получить параметр, который является ссылкой на переменную (совместно используемую с другими потоками Python), а не просто его копию?
Вы могли бы обернуть stop
в изменяемом объекте и передать ссылку на этот объект.