@@ -19,6 +19,8 @@ const PyJuliaBase_Type = Ref(C.PyNULL)
1919const PYJLVALUES = []
2020# unused indices in PYJLVALUES
2121const PYJLFREEVALUES = Int[]
22+ # Thread safety for PYJLVALUES and PYJLFREEVALUES
23+ const PYJLVALUES_LOCK = Threads. SpinLock ()
2224
2325function _pyjl_new (t:: C.PyPtr , :: C.PyPtr , :: C.PyPtr )
2426 o = ccall (UnsafePtr {C.PyTypeObject} (t). alloc[! ], C. PyPtr, (C. PyPtr, C. Py_ssize_t), t, 0 )
3133function _pyjl_dealloc (o:: C.PyPtr )
3234 idx = UnsafePtr {PyJuliaValueObject} (o). value[]
3335 if idx != 0
34- PYJLVALUES[idx] = nothing
35- push! (PYJLFREEVALUES, idx)
36+ Base. @lock PYJLVALUES_LOCK begin
37+ PYJLVALUES[idx] = nothing
38+ push! (PYJLFREEVALUES, idx)
39+ end
3640 end
3741 UnsafePtr {PyJuliaValueObject} (o). weaklist[! ] == C. PyNULL || C. PyObject_ClearWeakRefs (o)
3842 ccall (UnsafePtr {C.PyTypeObject} (C. Py_Type (o)). free[! ], Cvoid, (C. PyPtr,), o)
3943 nothing
4044end
4145
4246const PYJLMETHODS = Vector {Any} ()
47+ const PYJLMETHODS_LOCK = Threads. SpinLock ()
4348
4449function PyJulia_MethodNum (f)
4550 @nospecialize f
46- push! (PYJLMETHODS, f)
47- return length (PYJLMETHODS)
51+ Base. @lock PYJLMETHODS_LOCK begin
52+ push! (PYJLMETHODS, f)
53+ return length (PYJLMETHODS)
54+ end
4855end
4956
5057function _pyjl_isnull (o:: C.PyPtr , :: C.PyPtr )
@@ -58,12 +65,13 @@ function _pyjl_callmethod(o::C.PyPtr, args::C.PyPtr)
5865 @assert nargs > 0
5966 num = C. PyLong_AsLongLong (C. PyTuple_GetItem (args, 0 ))
6067 num == - 1 && return C. PyNULL
61- f = PYJLMETHODS[num]
68+ f = Base . @lock PYJLMETHODS_LOCK PYJLMETHODS[num]
6269 # this form gets defined in jlwrap/base.jl
6370 return _pyjl_callmethod (f, o, args, nargs):: C.PyPtr
6471end
6572
6673const PYJLBUFCACHE = Dict {Ptr{Cvoid},Any} ()
74+ const PYJLBUFCACHE_LOCK = Threads. SpinLock ()
6775
6876@kwdef struct PyBufferInfo{N}
6977 # data
@@ -177,7 +185,9 @@ function _pyjl_get_buffer_impl(
177185
178186 # internal
179187 cptr = Base. pointer_from_objref (c)
180- PYJLBUFCACHE[cptr] = c
188+ Base. @lock PYJLBUFCACHE_LOCK begin
189+ PYJLBUFCACHE[cptr] = c
190+ end
181191 b. internal[] = cptr
182192
183193 # obj
@@ -195,7 +205,7 @@ function _pyjl_get_buffer(o::C.PyPtr, buf::Ptr{C.Py_buffer}, flags::Cint)
195205 C. Py_DecRef (num_)
196206 num == - 1 && return Cint (- 1 )
197207 try
198- f = PYJLMETHODS[num]
208+ f = Base . @lock PYJLMETHODS_LOCK PYJLMETHODS[num]
199209 x = PyJuliaValue_GetValue (o)
200210 return _pyjl_get_buffer_impl (o, buf, flags, x, f):: Cint
201211 catch exc
@@ -209,7 +219,9 @@ function _pyjl_get_buffer(o::C.PyPtr, buf::Ptr{C.Py_buffer}, flags::Cint)
209219end
210220
211221function _pyjl_release_buffer (xo:: C.PyPtr , buf:: Ptr{C.Py_buffer} )
212- delete! (PYJLBUFCACHE, UnsafePtr (buf). internal[! ])
222+ Base. @lock PYJLBUFCACHE_LOCK begin
223+ delete! (PYJLBUFCACHE, UnsafePtr (buf). internal[! ])
224+ end
213225 nothing
214226end
215227
@@ -339,22 +351,31 @@ end
339351
340352PyJuliaValue_IsNull (o) = Base. GC. @preserve o UnsafePtr {PyJuliaValueObject} (C. asptr (o)). value[] == 0
341353
342- PyJuliaValue_GetValue (o) = Base. GC. @preserve o PYJLVALUES[UnsafePtr {PyJuliaValueObject} (C. asptr (o)). value[]]
354+ PyJuliaValue_GetValue (o) = Base. GC. @preserve o begin
355+ idx = UnsafePtr {PyJuliaValueObject} (C. asptr (o)). value[]
356+ Base. @lock PYJLVALUES_LOCK begin
357+ PYJLVALUES[idx]
358+ end
359+ end
343360
344361PyJuliaValue_SetValue (_o, @nospecialize (v)) = Base. GC. @preserve _o begin
345362 o = C. asptr (_o)
346363 idx = UnsafePtr {PyJuliaValueObject} (o). value[]
347364 if idx == 0
348- if isempty (PYJLFREEVALUES)
349- push! (PYJLVALUES, v)
350- idx = length (PYJLVALUES)
351- else
352- idx = pop! (PYJLFREEVALUES)
353- PYJLVALUES[idx] = v
365+ Base. @lock PYJLVALUES_LOCK begin
366+ if isempty (PYJLFREEVALUES)
367+ push! (PYJLVALUES, v)
368+ idx = length (PYJLVALUES)
369+ else
370+ idx = pop! (PYJLFREEVALUES)
371+ PYJLVALUES[idx] = v
372+ end
354373 end
355374 UnsafePtr {PyJuliaValueObject} (o). value[] = idx
356375 else
357- PYJLVALUES[idx] = v
376+ Base. @lock PYJLVALUES_LOCK begin
377+ PYJLVALUES[idx] = v
378+ end
358379 end
359380 nothing
360381end
0 commit comments