2011-03-01 9 views
3

블로킹 작업 (선택)을 수행하고 수신 메시지를 처리하는 C 함수를 래핑하고 있습니다.G 코드를 차단하고 파이썬으로 콜백 할 수있는 C 함수보다 먼저 GIL을 릴리즈 할 수 있습니까?

Py_BEGIN_ALLOW_THREADS             
blocking_function(); 
Py_END_ALLOW_THREADS 

그러나,이 함수는 매개 변수로 콜백 포인터를 소요 발생합니다 나의 이해는 C 함수 차단하려고 할 때 실행하는 다른 스레드를 허용하면서, 올바른 방법은 그것을 호출하는 것입니다. 이 콜백은 C 함수에 의해 사전 처리 된 들어오는 메시지를 처리 ​​할 때 호출됩니다. 성공적으로 파이썬 콜백을 전달할 수 있도록 PyEval_CallObject()을 호출하는 함수에서이 콜백을 래핑했습니다. 그것은 동시에 할 수 있다면 지금은 스레딩 지원을 추가 해요 것을

이 궁금 해요 :

  • 이 차단 작업을 호출하기 전에 GIL을 놓습니다.
  • 이 차단 작업을 안전하게 파이썬 인터프리터로 다시 호출하십시오.

문제가 발생합니까? 그렇다면 주위에 방법이 있습니까?

감사합니다.

+0

"PyEval_CallObject"를 호출하는 내 처리기에서 GIL을 다시 캡처하는 것이 올바른 접근 방법 인 것 같습니다. 그러나 이것은 저장된'PyThreadState'를 전달하는 것을 의미합니다. 이것은 약간 까다로워 보입니다! – Steve

답변

7

몇 달 전에이 API 함수를 사용했고 기억이 약간 흐릿하지만이 코드가 문제를 해결할 것으로 믿습니다. 나는 (3.x를이 다를 수 있습니다) 버전 2.x를 가정입니다 :

PyGILState_STATE gstate; 
gstate = PyGILState_Ensure(); 

/* Make your call to PyEval_CallObject() here (and any other PY API calls). */ 

PyGILState_Release(gstate); 

은 (위의가에서 찍은 : Python C/API docs)

이 기본적으로 Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS 매크로의 역이다. 그 중 GIL을 해제하지만 PyGILState 함수에서 GIL을 획득합니다.

+0

PyGILState_Ensure/Release API는 Python 3에서도 유효합니다. – ncoghlan

1

PyEval_SaveThread의 결과를 저장하기 위해 전역 변수를 사용하는 경우 작동하고 콜백에서 PyEval_RestoreThread을 호출합니다. 콜백의 컨텍스트 포인터를 통해 내 코드의 콜백에이 코드를보다 깨끗하게 전달하는 방법을 알아야합니다.

+0

이제 PyGILState API를 사용할 수있게되었으므로 (dappawit의 대답에 설명 된대로) PyGILState API를 사용할 수있게되었습니다. – ncoghlan