// BlockThreads() reclaims the GIL (and restores per-thread state), after is has // been released by UnblockThreads(). // // If this function is called without UnblockThreads() having been called, then // nothing happens and the function returns immediately. func (lock *Lock) BlockThreads() { if lock.gilState == nil { panic("BlockThreads() called on Unlocked Lock") } if lock.thState != nil { C.PyEval_RestoreThread(lock.thState) lock.thState = nil } }
// Unlock unlocks the lock. When it returns no calls into Python made be made. // // If the lock is not locked when this function is called, then nothing happens, // and the function returns immediately. Also, it is not necessay to call // BlockThreads() before calling Unlock(), even if UnblockThreads() has been // called. func (lock *Lock) Unlock() { if lock.gilState == nil { return } if lock.thState != nil { C.PyEval_RestoreThread(lock.thState) lock.thState = nil } lock.gilState.Release() runtime.UnlockOSThread() lock.gilState = nil }
// Unlock unlocks the lock. When it returns no calls into Python may be made. // // If the lock is not locked when this function is called, then nothing happens, // and the function returns immediately. Also, it is not necessay to call // BlockThreads() before calling Unlock(), even if UnblockThreads() has been // called. func (lock *Lock) Unlock() { if lock.gilState == nil { return } if lock.thState != nil { C.PyEval_RestoreThread(lock.thState) lock.thState = nil } releaseOsThread := lock.dec() lock.gilState.Release() if releaseOsThread { runtime.UnlockOSThread() } lock.gilState = nil }
//export gil func gil(self, args *C.PyObject) *C.PyObject { var res *C.PyObject tState := C.PyEval_SaveThread() var mu sync.Mutex mu.Lock() go func() { C.PyEval_RestoreThread(tState) res = C.PyLong_FromLong(1) mu.Unlock() }() mu.Lock() return res }
func (t *Thread) loop() { runtime.LockOSThread() threadState := threadInit() if threadState == nil { gilState := C.PyGILState_Ensure() oldThreadState := C.PyGILState_GetThisThreadState() threadState = C.PyThreadState_New(oldThreadState.interp) C.PyGILState_Release(gilState) } for f := range t.queue { C.PyEval_RestoreThread(threadState) f() threadState = C.PyEval_SaveThread() } gilState := C.PyGILState_Ensure() C.PyThreadState_Clear(threadState) C.PyThreadState_Delete(threadState) C.PyGILState_Release(gilState) }
// void PyEval_RestoreThread(PyThreadState *tstate) // Acquire the global interpreter lock (if it has been created and thread // support is enabled) and set the thread state to tstate, which must not be // NULL. If the lock has been created, the current thread must not have // acquired it, otherwise deadlock ensues. (This function is available even // when thread support is disabled at compile time.) func PyEval_RestoreThread(state *PyThreadState) { C.PyEval_RestoreThread(state.ptr) }