func create_thread(ch chan bool, args []string, kw map[string]string) { log.Debug("> create_thread") lock.Lock() defer lock.Unlock() defer func() { ch <- true }() _ch := make(chan bool) defer func() { close(_ch) }() thread := pthread.Create(func() { _gstate := C.PyGILState_Ensure() defer func() { C.PyGILState_Release(_gstate) }() embed_function(args, kw) _ch <- true }) defer func() { thread.Kill() }() <-_ch log.Debug("< create_thread: done") }
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 PyGILState_Release(PyGILState_STATE) // Release any resources previously acquired. After this call, Python’s state // will be the same as it was prior to the corresponding PyGILState_Ensure() // call (but generally this state will be unknown to the caller, hence the use // of the GILState API). // // Every call to PyGILState_Ensure() must be matched by a call to // PyGILState_Release() on the same thread. // // New in version 2.3. func PyGILState_Release(state PyGILState) { C.PyGILState_Release(C.PyGILState_STATE(state)) }
func (g *GilState) Release() { if g.set { C.PyGILState_Release(g.state) g.set = false } }