Skip to content

Commit 0eabe22

Browse files
authored
remove unused and not-recommended Threads.Mutex (#32875)
1 parent b451d55 commit 0eabe22

File tree

6 files changed

+13
-148
lines changed

6 files changed

+13
-148
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ Deprecated or removed
106106
---------------------
107107

108108
* `@spawn expr` from the `Distributed` standard library should be replaced with `@spawnat :any expr` ([#32600]).
109+
* `Threads.Mutex` and `Threads.RecursiveSpinLock` have been removed; use `ReentrantLock` (preferred) or
110+
`Threads.SpinLock` instead ([#32875]).
109111

110112
External dependencies
111113
---------------------

base/deprecated.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,12 @@ MPFR.BigFloat(x::Real, prec::Int) = BigFloat(x; precision=prec)
188188
MPFR.BigFloat(x::Real, prec::Int, rounding::RoundingMode) = BigFloat(x, rounding; precision=prec)
189189

190190
# END 1.0 deprecations
191+
192+
# BEGIN 1.3 deprecations
193+
194+
@eval Threads begin
195+
Base.@deprecate_binding RecursiveSpinLock ReentrantLock
196+
Base.@deprecate_binding Mutex ReentrantLock
197+
end
198+
199+
# END 1.3 deprecations

base/locks-mt.jl

Lines changed: 1 addition & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import .Base: unsafe_convert, lock, trylock, unlock, islocked, wait, notify, AbstractLock
44

5-
export SpinLock, RecursiveSpinLock, Mutex
5+
export SpinLock
66

77
# Important Note: these low-level primitives defined here
88
# are typically not for general usage
@@ -24,9 +24,6 @@ Each [`lock`](@ref) must be matched with an [`unlock`](@ref).
2424
Test-and-test-and-set spin locks are quickest up to about 30ish
2525
contending threads. If you have more contention than that, perhaps
2626
a lock is the wrong way to synchronize.
27-
28-
See also [`Mutex`](@ref) for a more efficient version on one core or if the
29-
lock may be held for a considerable length of time.
3027
"""
3128
struct SpinLock <: AbstractLock
3229
handle::Atomic{Int}
@@ -63,142 +60,3 @@ end
6360
function islocked(l::SpinLock)
6461
return l.handle[] != 0
6562
end
66-
67-
"""
68-
RecursiveSpinLock()
69-
70-
Creates a reentrant lock.
71-
The same thread can acquire the lock as many times as required.
72-
Each [`lock`](@ref) must be matched with an [`unlock`](@ref).
73-
74-
See also [`SpinLock`](@ref) for a slightly faster version.
75-
76-
See also [`Mutex`](@ref) for a more efficient version on one core or if the lock
77-
may be held for a considerable length of time.
78-
"""
79-
struct RecursiveSpinLock <: AbstractLock
80-
ownertid::Atomic{Int16}
81-
handle::Atomic{Int}
82-
RecursiveSpinLock() = new(Atomic{Int16}(0), Atomic{Int}(0))
83-
end
84-
85-
function lock(l::RecursiveSpinLock)
86-
if l.ownertid[] == threadid()
87-
l.handle[] += 1
88-
return
89-
end
90-
while true
91-
if l.handle[] == 0
92-
if atomic_cas!(l.handle, 0, 1) == 0
93-
l.ownertid[] = threadid()
94-
return
95-
end
96-
end
97-
ccall(:jl_cpu_pause, Cvoid, ())
98-
# Temporary solution before we have gc transition support in codegen.
99-
ccall(:jl_gc_safepoint, Cvoid, ())
100-
end
101-
end
102-
103-
function trylock(l::RecursiveSpinLock)
104-
if l.ownertid[] == threadid()
105-
l.handle[] += 1
106-
return true
107-
end
108-
if l.handle[] == 0
109-
if atomic_cas!(l.handle, 0, 1) == 0
110-
l.ownertid[] = threadid()
111-
return true
112-
end
113-
return false
114-
end
115-
return false
116-
end
117-
118-
function unlock(l::RecursiveSpinLock)
119-
@assert(l.ownertid[] == threadid(), "unlock from wrong thread")
120-
@assert(l.handle[] != 0, "unlock count must match lock count")
121-
if l.handle[] == 1
122-
l.ownertid[] = 0
123-
l.handle[] = 0
124-
ccall(:jl_cpu_wake, Cvoid, ())
125-
else
126-
l.handle[] -= 1
127-
end
128-
return
129-
end
130-
131-
function islocked(l::RecursiveSpinLock)
132-
return l.handle[] != 0
133-
end
134-
135-
##########################################
136-
# System Mutexes
137-
##########################################
138-
139-
# These are mutexes from libuv.
140-
const UV_MUTEX_SIZE = ccall(:jl_sizeof_uv_mutex, Cint, ())
141-
142-
"""
143-
Mutex()
144-
145-
These are standard system mutexes for locking critical sections of logic.
146-
147-
On Windows, this is a critical section object,
148-
on pthreads, this is a `pthread_mutex_t`.
149-
150-
See also [`SpinLock`](@ref) for a lighter-weight lock.
151-
"""
152-
mutable struct Mutex <: AbstractLock
153-
ownertid::Int16
154-
handle::Ptr{Cvoid}
155-
function Mutex()
156-
m = new(zero(Int16), Libc.malloc(UV_MUTEX_SIZE))
157-
ccall(:uv_mutex_init, Cvoid, (Ptr{Cvoid},), m.handle)
158-
finalizer(mutex_destroy, m)
159-
return m
160-
end
161-
end
162-
163-
unsafe_convert(::Type{Ptr{Cvoid}}, m::Mutex) = m.handle
164-
165-
function mutex_destroy(x::Mutex)
166-
h = x.handle
167-
if h != C_NULL
168-
x.handle = C_NULL
169-
ccall(:uv_mutex_destroy, Cvoid, (Ptr{Cvoid},), h)
170-
Libc.free(h)
171-
nothing
172-
end
173-
end
174-
175-
function lock(m::Mutex)
176-
m.ownertid == threadid() && concurrency_violation() # deadlock
177-
# Temporary solution before we have gc transition support in codegen.
178-
# This could mess up gc state when we add codegen support.
179-
gc_state = ccall(:jl_gc_safe_enter, Int8, ())
180-
ccall(:uv_mutex_lock, Cvoid, (Ptr{Cvoid},), m)
181-
ccall(:jl_gc_safe_leave, Cvoid, (Int8,), gc_state)
182-
m.ownertid = threadid()
183-
return
184-
end
185-
186-
function trylock(m::Mutex)
187-
m.ownertid == threadid() && concurrency_violation() # deadlock
188-
r = ccall(:uv_mutex_trylock, Cint, (Ptr{Cvoid},), m)
189-
if r == 0
190-
m.ownertid = threadid()
191-
end
192-
return r == 0
193-
end
194-
195-
function unlock(m::Mutex)
196-
m.ownertid == threadid() || concurrency_violation()
197-
m.ownertid = 0
198-
ccall(:uv_mutex_unlock, Cvoid, (Ptr{Cvoid},), m)
199-
return
200-
end
201-
202-
function islocked(m::Mutex)
203-
return m.ownertid != 0
204-
end

doc/src/base/multi-threading.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,5 @@ Base.@threadcall
3636
These building blocks are used to create the regular synchronization objects.
3737

3838
```@docs
39-
Base.Threads.Mutex
4039
Base.Threads.SpinLock
4140
```

src/sys.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ JL_DLLEXPORT uint32_t jl_getutf8(ios_t *s)
7575
return wc;
7676
}
7777

78-
JL_DLLEXPORT int jl_sizeof_uv_mutex(void) { return sizeof(uv_mutex_t); }
7978
JL_DLLEXPORT int jl_sizeof_off_t(void) { return sizeof(off_t); }
8079
#ifndef _OS_WINDOWS_
8180
JL_DLLEXPORT int jl_sizeof_mode_t(void) { return sizeof(mode_t); }

test/threads_exec.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
using Test
44
using Base.Threads
5-
using Base.Threads: SpinLock, Mutex
5+
using Base.Threads: SpinLock
66

77
# threading constructs
88

@@ -110,7 +110,6 @@ end
110110

111111
@test threaded_add_locked(SpinLock, 0, 10000) == 10000
112112
@test threaded_add_locked(ReentrantLock, 0, 10000) == 10000
113-
@test threaded_add_locked(Mutex, 0, 10000) == 10000
114113

115114
# Check if the recursive lock can be locked and unlocked correctly.
116115
let critical = ReentrantLock()
@@ -151,7 +150,6 @@ end
151150

152151
threaded_gc_locked(SpinLock)
153152
threaded_gc_locked(Threads.ReentrantLock)
154-
threaded_gc_locked(Mutex)
155153

156154
# Issue 14726
157155
# Make sure that eval'ing in a different module doesn't mess up other threads

0 commit comments

Comments
 (0)