Skip to content

Commit b5ba47d

Browse files
nickrobinson251kpamnanydependabot[bot]
authored
Backport deque memory fix (#898)
* Use `Base._unsetindex!` in `pop!` and `popfirst!` (#897) * Bump codecov/codecov-action from 3 to 4 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](codecov/codecov-action@v3...v4) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]> * Use `Base._unsetindex!` in `pop!` and `popfirst!` for Deque So that popped elements are not rooted by the deque and can be GCed when they drop out of caller scope. * Test Deque for leaks * Use `Base._unsetindex!` in `pop!` and `popfirst!` for CircularDeque So that popped elements are not rooted by the deque and can be GCed when they drop out of caller scope. * Test CircularDeque for leaks --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump version * Make compatible with ancient Julia versions * fixup! Make compatible with ancient Julia versions * fixup! fixup! Make compatible with ancient Julia versions --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Kiran Pamnany <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent 685f7bc commit b5ba47d

File tree

6 files changed

+59
-2
lines changed

6 files changed

+59
-2
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "DataStructures"
22
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
3-
version = "0.18.16"
3+
version = "0.18.17"
44

55
[deps]
66
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"

src/DataStructures.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,10 @@ module DataStructures
112112
include("splay_tree.jl")
113113

114114
include("deprecations.jl")
115-
end
115+
116+
@static if VERSION <= v"1.3"
117+
_unsetindex!(a, i) = a
118+
else
119+
_unsetindex! = Base._unsetindex!
120+
end
121+
end

src/circ_deque.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ end
6363

6464
@inline Base.@propagate_inbounds function Base.pop!(D::CircularDeque)
6565
v = last(D)
66+
_unsetindex!(D.buffer, D.last) # see issue/884
6667
D.n -= 1
6768
tmp = D.last - 1
6869
D.last = ifelse(tmp < 1, D.capacity, tmp)
@@ -90,6 +91,7 @@ Remove the element at the front.
9091
"""
9192
@inline Base.@propagate_inbounds function Base.popfirst!(D::CircularDeque)
9293
v = first(D)
94+
_unsetindex!(D.buffer, D.first) # see issue/884
9395
D.n -= 1
9496
tmp = D.first + 1
9597
D.first = ifelse(tmp > D.capacity, 1, tmp)

src/deque.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ function Base.pop!(q::Deque{T}) where T
276276
@assert rear.back >= rear.front
277277

278278
@inbounds x = rear.data[rear.back]
279+
_unsetindex!(rear.data, rear.back) # see issue/884
279280
rear.back -= 1
280281
if rear.back < rear.front
281282
if q.nblocks > 1
@@ -301,6 +302,7 @@ function Base.popfirst!(q::Deque{T}) where T
301302
@assert head.back >= head.front
302303

303304
@inbounds x = head.data[head.front]
305+
_unsetindex!(head.data, head.front) # see issue/884
304306
head.front += 1
305307
if head.back < head.front
306308
if q.nblocks > 1

test/test_circ_deque.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,29 @@
8181
for i in 1:5 push!(D, i) end
8282
@test collect([i for i in D]) == collect(1:5)
8383
end
84+
85+
VERSION >= v"1.3" && @testset "pop! and popfirst! do not leak" begin
86+
D = CircularDeque{String}(5)
87+
88+
@testset "pop! doesn't leak" begin
89+
push!(D,"foo")
90+
push!(D,"bar")
91+
ss2 = Base.summarysize(D)
92+
pop!(D)
93+
GC.gc(true)
94+
ss1 = Base.summarysize(D)
95+
@test ss1 < ss2
96+
end
97+
@testset "popfirst! doesn't leak" begin
98+
push!(D,"baz")
99+
push!(D,"bug")
100+
ss2 = Base.summarysize(D)
101+
popfirst!(D)
102+
GC.gc(true)
103+
ss1 = Base.summarysize(D)
104+
@test ss1 < ss2
105+
end
106+
end
84107
end
85108

86109
nothing

test/test_deque.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,28 @@
197197
@test typeof(empty!(q)) === typeof(Deque{Int}())
198198
@test isempty(q)
199199
end
200+
201+
VERSION >= v"1.3" && @testset "pop! and popfirst! don't leak" begin
202+
q = Deque{String}(5)
203+
GC.gc(true)
204+
205+
@testset "pop! doesn't leak" begin
206+
push!(q,"foo")
207+
push!(q,"bar")
208+
ss2 = Base.summarysize(q.head)
209+
pop!(q)
210+
GC.gc(true)
211+
ss1 = Base.summarysize(q.head)
212+
@test ss1 < ss2
213+
end
214+
@testset "popfirst! doesn't leak" begin
215+
push!(q,"baz")
216+
push!(q,"bug")
217+
ss2 = Base.summarysize(q.head)
218+
popfirst!(q)
219+
GC.gc(true)
220+
ss1 = Base.summarysize(q.head)
221+
@test ss1 < ss2
222+
end
223+
end
200224
end # @testset Deque

0 commit comments

Comments
 (0)