Skip to content

Instantly share code, notes, and snippets.

@Cheaterman
Last active March 16, 2024 14:33
Show Gist options
  • Save Cheaterman/b294fa4b5e7b5d780d92b4db0f02a39d to your computer and use it in GitHub Desktop.
Save Cheaterman/b294fa4b5e7b5d780d92b4db0f02a39d to your computer and use it in GitHub Desktop.
Kivy/Cython example of GIL vs nogil thread work

Building

Use cythonize --build cysleep.pyx

Running

After building, run python main.py

# cython: language_level=3
cdef extern from 'time.h':
ctypedef long time_t
cdef struct timespec:
time_t tv_sec
long tv_nsec
void nanosleep(const timespec*, timespec*) nogil
def sleep_gil(time: float):
cdef time_t seconds = round(time)
cdef timespec sleep_time = timespec(seconds, int((time - seconds) * 10**9))
nanosleep(&sleep_time, NULL)
def sleep_nogil(time: float):
cdef time_t seconds = round(time)
cdef timespec sleep_time = timespec(seconds, int((time - seconds) * 10**9))
with nogil:
nanosleep(&sleep_time, NULL)
import threading
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import BooleanProperty, NumericProperty
from cysleep import sleep_gil, sleep_nogil
KV = '''
BoxLayout:
orientation: 'vertical'
ToggleButton:
text: 'Use nogil'
on_state: app.use_nogil = self.state == 'down'
Button:
text: 'Sleep now'
on_press: app.sleep()
canvas:
Color:
Ellipse:
pos:
(
self.center_x - self.texture_size[0] / 2 - 90,
self.center_y - 30
)
size: 60, 60
angle_end: app.time * 360 % 360
'''
class SleepTest(App):
use_nogil = BooleanProperty(False)
time = NumericProperty()
def build(self):
def update_time(dt):
self.time += dt
Clock.schedule_interval(update_time, 0)
return Builder.load_string(KV)
def sleep(self):
if self.use_nogil:
target = sleep_nogil
else:
target = sleep_gil
threading.Thread(target=target, args=(1,)).start()
SleepTest().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment