Пример #1
0
func initAndLock(initsigs bool) *Lock {
	// Lock the current goroutine to the current OS thread, until we have
	// released the GIL (as CPython uses per-thread state)
	runtime.LockOSThread()

	// Initialize the default Python interpreter
	if initsigs {
		C.Py_InitializeEx(1)
	} else {
		C.Py_InitializeEx(0)
	}

	// Enable Python thread support, and then immediately release the GIL (and
	// thus "deativate" and per-thread state associated with the current thread
	C.PyEval_InitThreads()
	C.PyEval_SaveThread()

	// We can now unlock the current goroutine from the current OS thread, as
	// there is no active per-thread state
	runtime.UnlockOSThread()

	// Now that Python is setup, we can return a locked Lock, ready for the
	// calling code to use
	return NewLock()
}
Пример #2
0
// UnblockThreads() releases the GIL so that other Python threads may run.  It
// does not free the per-thread state created by Lock, nor does it call
// runtime.UnlockOSThread().  This function is intended to allow other Python
// threads to run whilst the calling code is either performing a slow/long
// running operation or is going to block.
//
// Nothing happens if this function is called more than once, all calls but the
// first will be ignored.
func (lock *Lock) UnblockThreads() {
	if lock.gilState == nil {
		panic("UnblockThreads() called on Unlocked Lock")
	}

	if lock.thState == nil {
		lock.thState = C.PyEval_SaveThread()
	}
}
Пример #3
0
//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
}
Пример #4
0
func threadInit() (defaultThreadState *C.PyThreadState) {
	initLock.Lock()
	defer initLock.Unlock()

	if !initialized {
		C.Py_InitializeEx(0)
		C.PyEval_InitThreads()
		C.PySys_SetArgvEx(0, nil, 0)

		pyEmptyTuple = C.PyTuple_New(0)
		falseObject = &object{C.False_INCREF()}
		trueObject = &object{C.True_INCREF()}

		defaultThreadState = C.PyEval_SaveThread()

		initialized = true
	}

	return
}
Пример #5
0
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)
}
Пример #6
0
// PyThreadState* PyEval_SaveThread()
// Release the global interpreter lock (if it has been created and thread
// support is enabled) and reset the thread state to NULL, returning the
// previous thread state (which is not NULL). If the lock has been created,
// the current thread must have acquired it. (This function is available even
// when thread support is disabled at compile time.)
func PyEval_SaveThread() *PyThreadState {
	state := C.PyEval_SaveThread()
	return &PyThreadState{ptr: state}
}