@@ -24,18 +24,23 @@ Returns `true` if the current thread has the GIL or `false` otherwise.
2424hasgil () = C. PyGILState_Check () == Cint (1 )
2525
2626"""
27- lock(f)
27+ lock(f; exclusive=true )
2828
2929Lock the GIL, compute `f()`, unlock the GIL, then return the result of `f()`.
3030
3131Use this to run Python code from threads that do not currently hold the GIL, such as new
3232threads. Since the main Julia thread holds the GIL by default, you will need to
3333[`unlock`](@ref) the GIL before using this function.
3434
35+ Setting the `exclusive` keyword to `false` allows more than one Julia `Task`
36+ to attempt to acquire the GIL. This may be useful if one Julia `Task` calls
37+ code which releases the GIL, in which case another Julia task could acquire
38+ it. However, this is probably not a sound approach.
39+
3540See [`@lock`](@ref) for the macro form.
3641"""
37- function lock (f)
38- Base. lock (_jl_gil_lock)
42+ function lock (f; exclusive = true )
43+ exclusive && Base. lock (_jl_gil_lock)
3944 try
4045 state = C. PyGILState_Ensure ()
4146 try
@@ -44,19 +49,24 @@ function lock(f)
4449 C. PyGILState_Release (state)
4550 end
4651 finally
47- Base. unlock (_jl_gil_lock)
52+ exclusive && Base. unlock (_jl_gil_lock)
4853 end
4954end
5055
5156"""
52- @lock expr
57+ @lock [exclusive=true] expr
5358
5459Lock the GIL, compute `expr`, unlock the GIL, then return the result of `expr`.
5560
5661Use this to run Python code from threads that do not currently hold the GIL, such as new
5762threads. Since the main Julia thread holds the GIL by default, you will need to
5863[`@unlock`](@ref) the GIL before using this function.
5964
65+ Setting the `exclusive` parameter to `false` allows more than one Julia `Task`
66+ to attempt to acquire the GIL. This may be useful if one Julia `Task` calls
67+ code which releases the GIL, in which case another Julia task could acquire
68+ it. However, this is probably not a sound approach.
69+
6070The macro equivalent of [`lock`](@ref).
6171"""
6272macro lock (expr)
@@ -75,6 +85,27 @@ macro lock(expr)
7585 end
7686end
7787
88+ macro lock (parameter, expr)
89+ parameter. head == :(= ) &&
90+ parameter. args[1 ] == :exclusive ||
91+ throw (ArgumentError (" The only accepted parameter to @lock is `exclusive`." ))
92+
93+ do_lock = esc (parameter. args[2 ])
94+ quote
95+ $ do_lock && Base. lock (_jl_gil_lock)
96+ try
97+ state = C. PyGILState_Ensure ()
98+ try
99+ $ (esc (expr))
100+ finally
101+ C. PyGILState_Release (state)
102+ end
103+ finally
104+ $ do_lock && Base. unlock (_jl_gil_lock)
105+ end
106+ end
107+ end
108+
78109"""
79110 unlock(f)
80111
0 commit comments