Skip to content

Commit e947aa8

Browse files
committed
Enable juliac build
1 parent 062fddb commit e947aa8

File tree

3 files changed

+38
-14
lines changed

3 files changed

+38
-14
lines changed

src/FFTW.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@ end
3131

3232
if VERSION >= v"1.11.0"
3333
# This can be be deleted once FFTW_jll is upgraded to the real lazy jll code, to get the real benefits of this mess
34-
mutable struct FakeLazyLibrary
34+
mutable struct FakeLazyLibrary{T}
3535
reallibrary::Symbol
36-
on_load_callback
36+
on_load_callback::T
3737
@atomic h::Ptr{Cvoid}
3838
end
3939
import Libdl: LazyLibrary, dlopen
40-
function dlopen(lib::FakeLazyLibrary)
40+
function dlopen(lib::FakeLazyLibrary{T}) where T
4141
h = @atomic :monotonic lib.h
4242
h != C_NULL && return h
4343
@lock fftwlock begin
4444
h = @atomic :monotonic lib.h
4545
h != C_NULL && return h
46-
h = dlopen(getglobal(FFTW, lib.reallibrary))
46+
h = dlopen(getglobal(FFTW, lib.reallibrary)::String)
4747
lib.on_load_callback()
4848
@atomic :release lib.h = h
4949
end

src/fft.jl

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,14 +320,26 @@ unsafe_convert(::Type{PlanPtr}, p::FFTWPlan) = p.plan
320320
# pushing the plan to be destroyed to the deferred_destroy_plans (which itself is protected by a lock).
321321
# This is accomplished by the maybe_destroy_plan function, which is used as the plan finalizer.
322322

323+
struct FFTWPlanDestructor
324+
ptr::PlanPtr
325+
use_32bit_lib::Bool
326+
end
327+
328+
FFTWPlanDestructor(plan::FFTWPlan{<:fftwSingle}) = FFTWPlanDestructor(plan.plan, true)
329+
FFTWPlanDestructor(plan::FFTWPlan{<:fftwDouble}) = FFTWPlanDestructor(plan.plan, false)
330+
323331
# these functions should only be called while the fftwlock is held
324-
unsafe_destroy_plan(@nospecialize(plan::FFTWPlan{<:fftwDouble})) =
325-
ccall((:fftw_destroy_plan,libfftw3), Cvoid, (PlanPtr,), plan)
326-
unsafe_destroy_plan(@nospecialize(plan::FFTWPlan{<:fftwSingle})) =
327-
ccall((:fftwf_destroy_plan,libfftw3f), Cvoid, (PlanPtr,), plan)
332+
unsafe_destroy_plan(plan::FFTWPlan) = unsafe_destroy_plan(FFTWPlanDestructor(plan))
333+
function unsafe_destroy_plan(destructor::FFTWPlanDestructor)
334+
if destructor.use_32bit_lib
335+
ccall((:fftwf_destroy_plan,libfftw3f), Cvoid, (PlanPtr,), destructor.ptr)
336+
else
337+
ccall((:fftw_destroy_plan,libfftw3), Cvoid, (PlanPtr,), destructor.ptr)
338+
end
339+
end
328340

329341
const deferred_destroy_lock = ReentrantLock() # lock protecting the deferred_destroy_plans list
330-
const deferred_destroy_plans = FFTWPlan[]
342+
const deferred_destroy_plans = FFTWPlanDestructor[]
331343

332344
function destroy_deferred()
333345
lock(deferred_destroy_lock)
@@ -375,7 +387,7 @@ function maybe_destroy_plan(plan::FFTWPlan)
375387
unlock(fftwlock)
376388
end
377389
else
378-
push!(deferred_destroy_plans, plan)
390+
push!(deferred_destroy_plans, FFTWPlanDestructor(plan))
379391
end
380392
finally
381393
unlock(deferred_destroy_lock)
@@ -495,11 +507,11 @@ function assert_applicable(p::FFTWPlan{T,K,inplace}, X::StridedArray{T}, Y::Stri
495507
elseif alignment_of(Y) != p.oalign && p.flags & UNALIGNED == 0
496508
throw(ArgumentError("FFTW plan applied to output with wrong memory alignment"))
497509
elseif inplace != (pointer(X) == pointer(Y))
498-
throw(ArgumentError(string("FFTW ",
510+
throw(ArgumentError(join(["FFTW ",
499511
inplace ? "in-place" : "out-of-place",
500512
" plan applied to ",
501513
inplace ? "out-of-place" : "in-place",
502-
" data")))
514+
" data"])))
503515
end
504516
end
505517

src/providers.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,20 @@ end
4545
# callback function that FFTW uses to launch `num` parallel
4646
# tasks (FFTW/fftw3#175):
4747
function spawnloop(f::Ptr{Cvoid}, fdata::Ptr{Cvoid}, elsize::Csize_t, num::Cint, callback_data::Ptr{Cvoid})
48-
@sync for i = 0:num-1
49-
Threads.@spawn ccall(f, Ptr{Cvoid}, (Ptr{Cvoid},), fdata + elsize*i)
48+
# Wrap the for-loop in a simplified @sync, achieving type stability by not depending on a Channel{Any}.
49+
# This is necessary for JuliaC to compile. The result runs as long as fftw only uses on thread.
50+
# If FFTW.set_num_threads is used to activate more threads, there will still be a runtime error due to @spawn,
51+
# which is limited by https://github.com/JuliaLang/julia/issues/58818 anyway.
52+
tasks = Channel{Task}(Inf)
53+
try
54+
for i = 0:num-1
55+
put!(tasks, Threads.@spawn ccall(f, Ptr{Cvoid}, (Ptr{Cvoid},), fdata + elsize*i))
56+
end
57+
while isready(tasks)
58+
wait(take!(tasks))
59+
end
60+
finally
61+
close(tasks)
5062
end
5163
end
5264

0 commit comments

Comments
 (0)