Skip to content

Commit ff81f14

Browse files
committed
make Request objects immutable
1 parent d34be21 commit ff81f14

5 files changed

Lines changed: 40 additions & 112 deletions

File tree

docs/src/reference/pointtopoint.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
```@docs
66
MPI.Request
7-
MPI.RequestSet
87
MPI.Status
98
```
109

src/collective.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ If `comm` is an intercommunicator, then it blocks until all members of the other
2929
$(_doc_external("MPI_Ibarrier"))
3030
"""
3131
function Ibarrier(comm::Comm)
32-
req = Request()
32+
rreq = Ref{MPI_Request}()
3333
# int MPI_Ibarrier(MPI_Comm comm, MPI_Req req)
34-
@mpichk ccall((:MPI_Ibarrier, libmpi), Cint, (MPI_Comm, Ptr{MPI_Request}), comm, req)
35-
return req
34+
@mpichk ccall((:MPI_Ibarrier, libmpi), Cint, (MPI_Comm, Ptr{MPI_Request}), comm, rreq)
35+
return Request(rreq[])
3636
end
3737

3838

@@ -911,7 +911,7 @@ function Neighbor_allgather!(sendbuf::Buffer, recvbuf::UBuffer, graph_comm::Comm
911911
(MPIPtr, Cint, MPI_Datatype, MPIPtr, Cint, MPI_Datatype, MPI_Comm),
912912
sendbuf.data, sendbuf.count, sendbuf.datatype,
913913
recvbuf.data, recvbuf.count, recvbuf.datatype, graph_comm) v"3.0"
914-
914+
915915
return recvbuf.data
916916
end
917917
Neighbor_allgather!(sendbuf, recvbuf::UBuffer, graph_comm::Comm) =

src/nonblocking.jl

Lines changed: 26 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -53,31 +53,31 @@ checked by other means.
5353
5454
See also [`Cancel!`](@ref).
5555
"""
56-
mutable struct Request
56+
struct Request
5757
val::MPI_Request
58-
buffer
5958
end
6059
Base.:(==)(a::Request, b::Request) = a.val == b.val
6160
Base.cconvert(::Type{MPI_Request}, request::Request) = request
6261
Base.unsafe_convert(::Type{MPI_Request}, request::Request) = request.val
63-
Base.unsafe_convert(::Type{Ptr{MPI_Request}}, request::Request) = convert(Ptr{MPI_Request}, pointer_from_objref(request))
62+
Base.cconvert(::Type{Ptr{MPI_Request}}, request::Request) = Ref(request.val)
6463

65-
const REQUEST_NULL = Request(Consts.MPI_REQUEST_NULL[], nothing)
66-
add_load_time_hook!(() -> REQUEST_NULL.val = Consts.MPI_REQUEST_NULL[])
64+
@static if VERSION < v"1.8"
65+
REQUEST_NULL = Request(Consts.MPI_REQUEST_NULL[])
66+
else
67+
REQUEST_NULL::Request = Request(Consts.MPI_REQUEST_NULL[])
68+
end
69+
add_load_time_hook!(() -> global REQUEST_NULL = Request(Consts.MPI_REQUEST_NULL[]))
6770

68-
Request() = Request(REQUEST_NULL.val, nothing)
6971
isnull(req::Request) = req == REQUEST_NULL
7072

7173
function free(req::Request)
7274
if req != REQUEST_NULL && !MPI.Finalized()
7375
# int MPI_Request_free(MPI_Request *req)
7476
@mpichk ccall((:MPI_Request_free, libmpi), Cint, (Ptr{MPI_Request},), req)
7577
end
76-
req.buffer = nothing
7778
return nothing
7879
end
7980

80-
8181
"""
8282
status = Probe(src::Integer, tag::Integer, comm::Comm)
8383
@@ -153,9 +153,6 @@ function Wait(req::Request, status::Union{Ref{Status}, Nothing}=nothing)
153153
@mpichk ccall((:MPI_Wait, libmpi), Cint,
154154
(Ptr{MPI_Request}, MPIPtr),
155155
req, something(status, Consts.MPI_STATUS_IGNORE[]))
156-
if isnull(req) # only clear the buffer for non-persistent requests
157-
req.buffer = nothing
158-
end
159156
return nothing
160157
end
161158
function Wait(req::Request, ::Type{Status})
@@ -181,9 +178,6 @@ function Test(req::Request, status::Union{Ref{Status}, Nothing}=nothing)
181178
@mpichk ccall((:MPI_Test, libmpi), Cint,
182179
(Ptr{MPI_Request}, Ptr{Cint}, Ptr{Status}),
183180
req, flag, something(status, Consts.MPI_STATUS_IGNORE[]))
184-
if isnull(req)
185-
req.buffer = nothing
186-
end
187181
return flag[] != 0
188182
end
189183
function Test(req::Request, ::Type{Status})
@@ -193,56 +187,6 @@ function Test(req::Request, ::Type{Status})
193187
end
194188

195189

196-
"""
197-
RequestSet(requests::Vector{Request})
198-
199-
A wrapper for an array of `Request`s that can be used to reduce intermediate memory
200-
allocations in [`Waitall`](@ref), [`Testall`](@ref), [`Waitany`](@ref), [`Testany`](@ref),
201-
[`Waitsome`](@ref) or [`Testsome`](@ref).
202-
203-
"""
204-
mutable struct RequestSet <: AbstractVector{Request}
205-
requests::Vector{Request}
206-
vals::Vector{MPI_Request}
207-
end
208-
209-
function RequestSet(requests::Vector{Request})
210-
n = length(requests)
211-
vals = Vector{MPI_Request}(undef, n)
212-
for i = 1:n
213-
vals[i] = requests[i].val
214-
end
215-
return RequestSet(requests, vals)
216-
end
217-
218-
Base.length(reqs::RequestSet) = length(reqs.requests)
219-
Base.getindex(reqs::RequestSet, i::Integer) = reqs.requests[i]
220-
function Base.setindex!(reqs::RequestSet, req::Request, i::Integer)
221-
reqs.vals[i] = req.val
222-
reqs.requests[i] = req
223-
end
224-
225-
function Base.push!(reqs::RequestSet, req::Request)
226-
push!(reqs.vals, req.val)
227-
push!(reqs.requests, req)
228-
end
229-
230-
231-
function update!(reqs::RequestSet, i::Integer)
232-
req = reqs[i]
233-
req.val = reqs.vals[i]
234-
if isnull(req)
235-
req.buffer = nothing
236-
end
237-
end
238-
function update!(reqs::RequestSet)
239-
n = length(reqs)
240-
for i = 1:n
241-
update!(reqs, i)
242-
end
243-
end
244-
245-
246190
"""
247191
Waitall(reqs::AbstractVector{Request}[, statuses::Vector{Status}])
248192
statuses = Waitall(reqs::AbstractVector{Request}, Status)
@@ -255,24 +199,22 @@ each request.
255199
# External links
256200
$(_doc_external("MPI_Waitall"))
257201
"""
258-
function Waitall(reqs::RequestSet, statuses::Union{AbstractVector{Status},Nothing}=nothing)
202+
function Waitall(reqs::AbstractVector{Request}, statuses::Union{AbstractVector{Status},Nothing}=nothing)
259203
n = length(reqs)
260204
n == 0 && return nothing
261205
@assert isnothing(statuses) || length(statuses) >= n
262206
# int MPI_Waitall(int count, MPI_Request array_of_requests[],
263207
# MPI_Status array_of_statuses[])
264208
@mpichk ccall((:MPI_Waitall, libmpi), Cint,
265209
(Cint, Ptr{MPI_Request}, Ptr{Status}),
266-
n, reqs.vals, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
267-
update!(reqs)
210+
n, reqs, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
268211
return nothing
269212
end
270-
function Waitall(reqs::RequestSet, ::Type{Status})
213+
function Waitall(reqs::AbstractVector{Request}, ::Type{Status})
271214
statuses = Array{Status}(undef, length(reqs))
272215
Waitall(reqs, statuses)
273216
return statuses
274217
end
275-
Waitall(reqs::AbstractVector{Request}, args...) = Waitall(RequestSet(reqs), args...)
276218

277219

278220
"""
@@ -289,24 +231,22 @@ each request.
289231
# External links
290232
$(_doc_external("MPI_Testall"))
291233
"""
292-
function Testall(reqs::RequestSet, statuses::Union{AbstractVector{Status},Nothing}=nothing)
234+
function Testall(reqs::AbstractVector{Request}, statuses::Union{AbstractVector{Status},Nothing}=nothing)
293235
n = length(reqs)
294236
flag = Ref{Cint}()
295237
@assert isnothing(statuses) || length(statuses) >= n
296238
# int MPI_Testall(int count, MPI_Request array_of_requests[], int *flag,
297239
# MPI_Status array_of_statuses[])
298240
@mpichk ccall((:MPI_Testall, libmpi), Cint,
299241
(Cint, Ptr{MPI_Request}, Ptr{Cint}, MPIPtr),
300-
n, reqs.vals, flag, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
301-
update!(reqs)
242+
n, reqs, flag, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
302243
return flag[] != 0
303244
end
304-
function Testall(reqs::RequestSet, ::Type{Status})
245+
function Testall(reqs::AbstractVector{Request}, ::Type{Status})
305246
statuses = Array{Status}(undef, length(reqs))
306247
flag = Testall(reqs, statuses)
307248
return flag, statuses
308249
end
309-
Testall(reqs::Vector{Request}, args...) = Testall(RequestSet(reqs), args...)
310250

311251
"""
312252
i = Waitany(reqs::AbstractVector{Request}[, status::Ref{Status}])
@@ -323,28 +263,26 @@ The optional `status` argument can be used to obtain the return `Status` of the
323263
# External links
324264
$(_doc_external("MPI_Waitany"))
325265
"""
326-
function Waitany(reqs::RequestSet, status::Union{Ref{Status}, Nothing}=nothing)
266+
function Waitany(reqs::AbstractVector{Request}, status::Union{Ref{Status}, Nothing}=nothing)
327267
ref_idx = Ref{Cint}()
328268
n = length(reqs)
329269
# int MPI_Waitany(int count, MPI_Request array_of_requests[], int *index,
330270
# MPI_Status *status)
331271
@mpichk ccall((:MPI_Waitany, libmpi), Cint,
332272
(Cint, Ptr{MPI_Request}, Ptr{Cint}, MPIPtr),
333-
n, reqs.vals, ref_idx, something(status, Consts.MPI_STATUS_IGNORE[]))
273+
n, reqs, ref_idx, something(status, Consts.MPI_STATUS_IGNORE[]))
334274
idx = ref_idx[]
335275
if idx == Consts.MPI_UNDEFINED[]
336276
return nothing
337277
end
338278
i = Int(idx) + 1
339-
update!(reqs, i)
340279
return i
341280
end
342-
function Waitany(reqs::RequestSet, ::Type{Status})
281+
function Waitany(reqs::AbstractVector{Request}, ::Type{Status})
343282
status = Ref(STATUS_ZERO)
344283
i = Waitany(reqs, status)
345284
return i, status[]
346285
end
347-
Waitany(reqs::Vector{Request}, args...) = Waitany(RequestSet(reqs), args...)
348286

349287
"""
350288
flag, idx = Testany(reqs::AbstractVector{Request}[, status::Ref{Status}])
@@ -364,31 +302,29 @@ The optional `status` argument can be used to obtain the return `Status` of the
364302
# External links
365303
$(_doc_external("MPI_Testany"))
366304
"""
367-
function Testany(reqs::RequestSet, status::Union{Ref{Status}, Nothing}=nothing)
305+
function Testany(reqs::AbstractVector{Request}, status::Union{Ref{Status}, Nothing}=nothing)
368306
ref_idx = Ref{Cint}()
369307
rflag = Ref{Cint}()
370308
n = length(reqs)
371309
# int MPI_Testany(int count, MPI_Request array_of_requests[], int *index,
372310
# int *flag, MPI_Status *status)
373311
@mpichk ccall((:MPI_Testany, libmpi), Cint,
374312
(Cint, Ptr{MPI_Request}, Ptr{Cint}, Ptr{Cint}, MPIPtr),
375-
n, reqs.vals, ref_idx, rflag, something(status, Consts.MPI_STATUS_IGNORE[]))
313+
n, reqs, ref_idx, rflag, something(status, Consts.MPI_STATUS_IGNORE[]))
376314
idx = ref_idx[]
377315
flag = rflag[] != 0
378316

379317
if idx == Consts.MPI_UNDEFINED[]
380318
return flag, nothing
381319
end
382320
i = Int(idx) + 1
383-
update!(reqs, i)
384321
return flag, i
385322
end
386-
function Testany(reqs::RequestSet, ::Type{Status})
323+
function Testany(reqs::AbstractVector{Request}, ::Type{Status})
387324
status = Ref(STATUS_ZERO)
388325
flag, i = Testany(reqs, status)
389326
return flag, i, status[]
390327
end
391-
Testany(reqs::Vector{Request}, args...) = Testany(RequestSet(reqs), args...)
392328

393329
"""
394330
inds = Waitsome(reqs::AbstractVector{Request}[, statuses::Vector{Status}])
@@ -404,7 +340,7 @@ completed request.
404340
# External links
405341
$(_doc_external("MPI_Waitsome"))
406342
"""
407-
function Waitsome(reqs::RequestSet, statuses::Union{AbstractVector{Status},Nothing}=nothing)
343+
function Waitsome(reqs::AbstractVector{Request}, statuses::Union{AbstractVector{Status},Nothing}=nothing)
408344
ref_nout = Ref{Cint}()
409345
n = length(reqs)
410346
idxs = Vector{Cint}(undef, n)
@@ -415,22 +351,20 @@ function Waitsome(reqs::RequestSet, statuses::Union{AbstractVector{Status},Nothi
415351
# MPI_Status array_of_statuses[])
416352
@mpichk ccall((:MPI_Waitsome, libmpi), Cint,
417353
(Cint, Ptr{MPI_Request}, Ptr{Cint}, Ptr{Cint}, Ptr{Status}),
418-
n, reqs.vals, ref_nout, idxs, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
354+
n, reqs, ref_nout, idxs, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
419355
nout = Int(ref_nout[])
420356
# This can happen if there were no valid requests
421357
if nout == Consts.MPI_UNDEFINED[]
422358
return nothing
423359
end
424-
update!(reqs)
425360
return [Int(idxs[i]) + 1 for i = 1:nout]
426361
end
427-
function Waitsome(reqs::RequestSet, ::Type{Status})
362+
function Waitsome(reqs::AbstractVector{Request}, ::Type{Status})
428363
statuses = Array{Status}(undef, length(reqs))
429364
inds = Waitsome(reqs, statuses)
430365
resize!(statuses, isnothing(inds) ? 0 : length(inds))
431366
return inds, statuses
432367
end
433-
Waitsome(reqs::Vector{Request}, args...) = Waitsome(RequestSet(reqs), args...)
434368

435369
"""
436370
inds = Testsome(reqs::AbstractVector{Request}[, statuses::Vector{Status}])
@@ -446,7 +380,7 @@ completed request.
446380
# External links
447381
$(_doc_external("MPI_Testsome"))
448382
"""
449-
function Testsome(reqs::RequestSet, statuses::Union{AbstractVector{Status},Nothing}=nothing)
383+
function Testsome(reqs::AbstractVector{Request}, statuses::Union{AbstractVector{Status},Nothing}=nothing)
450384
ref_nout = Ref{Cint}()
451385
n = length(reqs)
452386
idxs = Vector{Cint}(undef, n)
@@ -457,22 +391,20 @@ function Testsome(reqs::RequestSet, statuses::Union{AbstractVector{Status},Nothi
457391
# MPI_Status array_of_statuses[])
458392
@mpichk ccall((:MPI_Testsome, libmpi), Cint,
459393
(Cint, Ptr{MPI_Request}, Ptr{Cint}, Ptr{Cint}, Ptr{Status}),
460-
n, reqs.vals, ref_nout, idxs, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
394+
n, reqs, ref_nout, idxs, something(statuses, Consts.MPI_STATUSES_IGNORE[]))
461395
nout = Int(ref_nout[])
462396
# This can happen if there were no valid requests
463397
if nout == Consts.MPI_UNDEFINED[]
464398
return nothing
465399
end
466-
update!(reqs)
467400
return [Int(idxs[i]) + 1 for i = 1:nout]
468401
end
469-
function Testsome(reqs::RequestSet, ::Type{Status})
402+
function Testsome(reqs::AbstractVector{Request}, ::Type{Status})
470403
statuses = Array{Status}(undef, length(reqs))
471404
inds = Testsome(reqs, statuses)
472405
resize!(statuses, isnothing(inds) ? 0 : length(inds))
473406
return inds, statuses
474407
end
475-
Testsome(reqs::Vector{Request}, args...) = Testsome(RequestSet(reqs), args...)
476408

477409
"""
478410
Cancel!(req::Request)

src/pointtopoint.jl

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,13 @@ Isend(data, comm::Comm; dest::Integer, tag::Integer=0) =
6262
Isend(data, dest, tag, comm)
6363

6464
function Isend(buf::Buffer, dest::Integer, tag::Integer, comm::Comm)
65-
req = Request()
65+
rreq = Ref{MPI_Request}()
6666
# int MPI_Isend(const void* buf, int count, MPI_Datatype datatype, int dest,
6767
# int tag, MPI_Comm comm, MPI_Request *request)
6868
@mpichk ccall((:MPI_Isend, libmpi), Cint,
6969
(MPIPtr, Cint, MPI_Datatype, Cint, Cint, MPI_Comm, Ptr{MPI_Request}),
70-
buf.data, buf.count, buf.datatype, dest, tag, comm, req)
71-
req.buffer = buf
72-
finalizer(free, req)
73-
return req
70+
buf.data, buf.count, buf.datatype, dest, tag, comm, rreq)
71+
return Request(rreq[])
7472
end
7573
Isend(data, dest::Integer, tag::Integer, comm::Comm) =
7674
Isend(Buffer_send(data), dest, tag, comm)
@@ -205,15 +203,13 @@ $(_doc_external("MPI_Irecv"))
205203
Irecv!(recvbuf, comm::Comm; source::Integer=Consts.MPI_ANY_SOURCE[], tag::Integer=Consts.MPI_ANY_TAG[]) =
206204
Irecv!(recvbuf, source, tag, comm)
207205
function Irecv!(buf::Buffer, source::Integer, tag::Integer, comm::Comm)
208-
req = Request()
206+
rreq = Ref{MPI_Request}()
209207
# int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source,
210208
# int tag, MPI_Comm comm, MPI_Request *request)
211209
@mpichk ccall((:MPI_Irecv, libmpi), Cint,
212210
(MPIPtr, Cint, MPI_Datatype, Cint, Cint, MPI_Comm, Ptr{MPI_Request}),
213-
buf.data, buf.count, buf.datatype, source, tag, comm, req)
214-
req.buffer = buf
215-
finalizer(free, req)
216-
return req
211+
buf.data, buf.count, buf.datatype, source, tag, comm, rreq)
212+
return Request(rreq[])
217213
end
218214
Irecv!(data, source::Integer, tag::Integer, comm::Comm) =
219215
Irecv!(Buffer(data), source, tag, comm)

0 commit comments

Comments
 (0)