Skip to content

Commit 0046573

Browse files
committed
fixup [ci skip]: switch to runtime branching for MT-safe Condition API
Jeff suggested we branch at runtime on whether `Condition` requires the MT-safe API or not. This implements that, to encourage further discussion and experimentation with the API before we finalize the implementation. Thus, in addition to the existing API and usage of `Condition()` (which remain unchanged), this commit adds the option to construct it as a thread-safe variant: `Condition(#=threadsafe=#true)` and `Condition(ReentrantLock())` thereby enabling the same type to be used for both MT and ST usage, and branching the API at runtime based on the additional requirements imposed by MT-safety.
1 parent 587479a commit 0046573

File tree

3 files changed

+14
-11
lines changed

3 files changed

+14
-11
lines changed

base/event.jl

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ this, and can be used for level-triggered events.
9494
9595
This object is NOT thread-safe. See [`Threads.ConditionMT`](@ref) for a thread-safe version.
9696
"""
97-
mutable struct GenericCondition{L<:AbstractLock}
97+
struct GenericCondition{L<:AbstractLock}
9898
waitq::Vector{Any}
9999
lock::L
100100

@@ -227,12 +227,9 @@ function notify(e::GenericEvent)
227227
end
228228

229229

230-
const ConditionST = GenericCondition{CooperativeLock}
230+
const ConditionST = GenericCondition{AlwaysLockedST}
231231
const EventST = GenericEvent{CooperativeLock}
232232

233-
# default (Julia v1.0) is currently single-threaded
234-
const Condition = GenericCondition{AlwaysLockedST}
235-
236233

237234
## scheduler and work queue
238235

@@ -436,11 +433,11 @@ Use [`isopen`](@ref) to check whether it is still active.
436433
"""
437434
mutable struct AsyncCondition
438435
handle::Ptr{Cvoid}
439-
cond::Condition
436+
cond::ConditionST
440437
isopen::Bool
441438

442439
function AsyncCondition()
443-
this = new(Libc.malloc(_sizeof_uv_async), Condition(), true)
440+
this = new(Libc.malloc(_sizeof_uv_async), ConditionST(), true)
444441
associate_julia_struct(this.handle, this)
445442
finalizer(uvfinalize, this)
446443
err = ccall(:uv_async_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}),
@@ -494,14 +491,14 @@ to check whether a timer is still active.
494491
"""
495492
mutable struct Timer
496493
handle::Ptr{Cvoid}
497-
cond::Condition
494+
cond::ConditionST
498495
isopen::Bool
499496

500497
function Timer(timeout::Real; interval::Real = 0.0)
501498
timeout 0 || throw(ArgumentError("timer cannot have negative timeout of $timeout seconds"))
502499
interval 0 || throw(ArgumentError("timer cannot have negative repeat interval of $interval seconds"))
503500

504-
this = new(Libc.malloc(_sizeof_uv_timer), Condition(), true)
501+
this = new(Libc.malloc(_sizeof_uv_timer), ConditionST(), true)
505502
err = ccall(:uv_timer_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), eventloop(), this)
506503
if err != 0
507504
#TODO: this codepath is currently not tested

base/lock.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ This construct is NOT threadsafe.
169169
mutable struct Semaphore
170170
sem_size::Int
171171
curr_cnt::Int
172-
cond_wait::Condition
173-
Semaphore(sem_size) = sem_size > 0 ? new(sem_size, 0, Condition()) : throw(ArgumentError("Semaphore size must be > 0"))
172+
cond_wait::ConditionST
173+
Semaphore(sem_size) = sem_size > 0 ? new(sem_size, 0, ConditionST()) : throw(ArgumentError("Semaphore size must be > 0"))
174174
end
175175

176176
"""

base/sysimg.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ include("task.jl")
317317
include("lock.jl")
318318
include("threads.jl")
319319
include("weakkeydict.jl")
320+
321+
# default (Julia v1.0) is currently single-threaded
322+
const Condition = GenericCondition{Union{AlwaysLockedST, Threads.ReentrantLockMT}}
323+
Condition() = Condition(AlwaysLockedST())
324+
Condition(threadsafe::Bool) = Condition(threadsafe ? Threads.ReentrantLockMT() : AlwaysLockedST())
325+
# but uses MT-safe versions, when possible
320326
const ReentrantLock = Threads.ReentrantLockMT
321327
const Event = Threads.EventMT
322328

0 commit comments

Comments
 (0)