@@ -25,6 +25,12 @@ if Base.VERSION ≥ v"1.11"
2525 )
2626end
2727
28+ const LOCK = ReentrantLock ()
29+
30+ function __init__ ()
31+ Base. lock (LOCK)
32+ return nothing
33+ end
2834
2935"""
3036 lock(f)
@@ -42,11 +48,16 @@ See [`@lock`](@ref) for the macro form.
4248 This function is experimental. Its semantics may be changed without notice.
4349"""
4450function lock (f)
51+ Base. lock (LOCK)
52+ task = current_task ()
53+ sticky, task. sticky = task. sticky, true
4554 state = C. PyGILState_Ensure ()
4655 try
4756 f ()
4857 finally
4958 C. PyGILState_Release (state)
59+ task. sticky = sticky
60+ Base. unlock (LOCK)
5061 end
5162end
5263
@@ -67,11 +78,16 @@ The macro equivalent of [`lock`](@ref).
6778"""
6879macro lock (expr)
6980 quote
81+ Base. lock ($ LOCK)
82+ task = current_task ()
83+ sticky, task. sticky = task. sticky, true
7084 state = C. PyGILState_Ensure ()
7185 try
7286 $ (esc (expr))
7387 finally
7488 C. PyGILState_Release (state)
89+ task. sticky = sticky
90+ Base. unlock ($ LOCK)
7591 end
7692 end
7793end
@@ -92,11 +108,17 @@ See [`@unlock`](@ref) for the macro form.
92108 This function is experimental. Its semantics may be changed without notice.
93109"""
94110function unlock (f)
111+ if ! islocked (LOCK)
112+ error (" GIL is not held" )
113+ end
114+
115+ Base. unlock (LOCK)
95116 state = C. PyEval_SaveThread ()
96117 try
97118 f ()
98119 finally
99120 C. PyEval_RestoreThread (state)
121+ Base. lock (LOCK)
100122 end
101123end
102124
@@ -117,11 +139,17 @@ The macro equivalent of [`unlock`](@ref).
117139"""
118140macro unlock (expr)
119141 quote
142+ if ! islocked ($ LOCK)
143+ error (" GIL is not held" )
144+ end
145+
146+ Base. unlock ($ LOCK)
120147 state = C. PyEval_SaveThread ()
121148 try
122149 $ (esc (expr))
123150 finally
124151 C. PyEval_RestoreThread (state)
152+ Base. lock ($ LOCK)
125153 end
126154 end
127155end
0 commit comments