@@ -537,6 +537,8 @@ function rehash!{K,V}(h::Dict{K,V}, newsz = length(h.keys))
537
537
count = 0
538
538
maxprobe = h. maxprobe
539
539
540
+ # make sure the following is atomic wrt finalizers
541
+ prev_finalizers = gc_finalizers_enable (false )
540
542
for i = 1 : sz
541
543
if olds[i] == 0x1
542
544
k = oldk[i]
@@ -551,11 +553,6 @@ function rehash!{K,V}(h::Dict{K,V}, newsz = length(h.keys))
551
553
keys[index] = k
552
554
vals[index] = v
553
555
count += 1
554
-
555
- if h. age != age0
556
- # if `h` is changed by a finalizer, retry
557
- return rehash! (h, newsz)
558
- end
559
556
end
560
557
end
561
558
@@ -565,7 +562,8 @@ function rehash!{K,V}(h::Dict{K,V}, newsz = length(h.keys))
565
562
h. count = count
566
563
h. ndel = 0
567
564
h. maxprobe = maxprobe
568
- assert (h. age == age0)
565
+ @assert h. age == age0
566
+ gc_finalizers_enable (prev_finalizers)
569
567
570
568
return h
571
569
end
@@ -584,6 +582,7 @@ function sizehint!(d::Dict, newsz)
584
582
end
585
583
586
584
function empty! {K,V} (h:: Dict{K,V} )
585
+ prev_finalizers = gc_finalizers_enable (false )
587
586
fill! (h. slots, 0x0 )
588
587
sz = length (h. slots)
589
588
empty! (h. keys)
@@ -594,6 +593,7 @@ function empty!{K,V}(h::Dict{K,V})
594
593
h. count = 0
595
594
h. age += 1
596
595
h. idxfloor = 1
596
+ gc_finalizers_enable (prev_finalizers)
597
597
return h
598
598
end
599
599
@@ -698,6 +698,7 @@ function setindex!{K,V}(h::Dict{K,V}, v0, key0)
698
698
end
699
699
v = convert (V, v0)
700
700
701
+ prev_finalizers = gc_finalizers_enable (false )
701
702
index = ht_keyindex2 (h, key)
702
703
703
704
if index > 0
@@ -707,37 +708,31 @@ function setindex!{K,V}(h::Dict{K,V}, v0, key0)
707
708
else
708
709
_setindex! (h, v, key, - index)
709
710
end
711
+ gc_finalizers_enable (prev_finalizers)
710
712
711
713
return h
712
714
end
713
715
714
- function get! {K,V} (h:: Dict{K,V} , key0, default)
715
- key = convert (K,key0)
716
- if ! isequal (key,key0)
717
- throw (ArgumentError (" $key0 is not a valid key for type $K " ))
718
- end
719
-
720
- index = ht_keyindex2 (h, key)
721
-
722
- index > 0 && return h. vals[index]
723
-
724
- v = convert (V, default)
725
- _setindex! (h, v, key, - index)
726
- return v
727
- end
728
-
716
+ get! {K,V} (h:: Dict{K,V} , key0, default) = get! (()-> default, h, key0)
729
717
function get! {K,V} (default:: Callable , h:: Dict{K,V} , key0)
730
718
key = convert (K,key0)
731
719
if ! isequal (key,key0)
732
720
throw (ArgumentError (" $key0 is not a valid key for type $K " ))
733
721
end
734
722
723
+ prev_finalizers = gc_finalizers_enable (false )
735
724
index = ht_keyindex2 (h, key)
736
725
737
- index > 0 && return h. vals[index]
726
+ if index > 0
727
+ val = h. vals[index]
728
+ gc_finalizers_enable (prev_finalizers)
729
+ return val
730
+ end
738
731
739
732
age0 = h. age
740
- v = convert (V, default ())
733
+ gc_finalizers_enable (prev_finalizers)
734
+ v = convert (V, default ())
735
+ prev_finalizers = gc_finalizers_enable (false )
741
736
if h. age != age0
742
737
index = ht_keyindex2 (h, key)
743
738
end
@@ -748,6 +743,7 @@ function get!{K,V}(default::Callable, h::Dict{K,V}, key0)
748
743
else
749
744
_setindex! (h, v, key, - index)
750
745
end
746
+ gc_finalizers_enable (prev_finalizers)
751
747
return v
752
748
end
753
749
@@ -761,26 +757,47 @@ end
761
757
762
758
763
759
function getindex {K,V} (h:: Dict{K,V} , key)
760
+ prev_finalizers = gc_finalizers_enable (false )
764
761
index = ht_keyindex (h, key)
765
- return (index< 0 ) ? throw (KeyError (key)) : h. vals[index]:: V
762
+ index < 0 && throw (KeyError (key))
763
+ val = h. vals[index]:: V
764
+ gc_finalizers_enable (prev_finalizers)
765
+ return val
766
766
end
767
767
768
768
function get {K,V} (h:: Dict{K,V} , key, default)
769
+ prev_finalizers = gc_finalizers_enable (false )
769
770
index = ht_keyindex (h, key)
770
- return (index< 0 ) ? default : h. vals[index]:: V
771
+ val = (index < 0 ) ? default : h. vals[index]:: V
772
+ gc_finalizers_enable (prev_finalizers)
773
+ return val
771
774
end
772
775
773
776
function get {K,V} (default:: Callable , h:: Dict{K,V} , key)
777
+ prev_finalizers = gc_finalizers_enable (false )
774
778
index = ht_keyindex (h, key)
775
- return (index< 0 ) ? default () : h. vals[index]:: V
779
+ if index < 0
780
+ gc_finalizers_enable (prev_finalizers)
781
+ return default ()
782
+ end
783
+ val = h. vals[index]:: V
784
+ gc_finalizers_enable (prev_finalizers)
785
+ return val
776
786
end
777
787
778
788
haskey (h:: Dict , key) = (ht_keyindex (h, key) >= 0 )
779
789
in {T<:Dict} (key, v:: KeyIterator{T} ) = (ht_keyindex (v. dict, key) >= 0 )
780
790
781
791
function getkey {K,V} (h:: Dict{K,V} , key, default)
792
+ prev_finalizers = gc_finalizers_enable (false )
782
793
index = ht_keyindex (h, key)
783
- return (index< 0 ) ? default : h. keys[index]:: K
794
+ if index < 0
795
+ gc_finalizers_enable (prev_finalizers)
796
+ return default
797
+ end
798
+ val = h. keys[index]:: V
799
+ gc_finalizers_enable (prev_finalizers)
800
+ return val
784
801
end
785
802
786
803
function _pop! (h:: Dict , index)
@@ -790,13 +807,24 @@ function _pop!(h::Dict, index)
790
807
end
791
808
792
809
function pop! (h:: Dict , key)
810
+ prev_finalizers = gc_finalizers_enable (false )
793
811
index = ht_keyindex (h, key)
794
- index > 0 ? _pop! (h, index) : throw (KeyError (key))
812
+ index < 0 && throw (KeyError (key))
813
+ val = _pop! (h, index)
814
+ gc_finalizers_enable (prev_finalizers)
815
+ return val
795
816
end
796
817
797
818
function pop! (h:: Dict , key, default)
819
+ prev_finalizers = gc_finalizers_enable (false )
798
820
index = ht_keyindex (h, key)
799
- index > 0 ? _pop! (h, index) : default
821
+ if index < 0
822
+ gc_finalizers_enable (prev_finalizers)
823
+ return default
824
+ end
825
+ val = _pop! (h, index)
826
+ gc_finalizers_enable (prev_finalizers)
827
+ return val
800
828
end
801
829
802
830
function _delete! (h:: Dict , index)
@@ -806,13 +834,17 @@ function _delete!(h::Dict, index)
806
834
h. ndel += 1
807
835
h. count -= 1
808
836
h. age += 1
809
- h
837
+ return h
810
838
end
811
839
812
840
function delete! (h:: Dict , key)
841
+ prev_finalizers = gc_finalizers_enable (false )
813
842
index = ht_keyindex (h, key)
814
- if index > 0 ; _delete! (h, index); end
815
- h
843
+ if index > 0
844
+ _delete! (h, index)
845
+ end
846
+ gc_finalizers_enable (prev_finalizers)
847
+ return h
816
848
end
817
849
818
850
function skip_deleted (h:: Dict , i)
@@ -840,32 +872,28 @@ next{T<:Dict}(v::ValueIterator{T}, i) = (v.dict.vals[i], skip_deleted(v.dict,i+1
840
872
# weak key dictionaries
841
873
842
874
type WeakKeyDict{K,V} <: Associative{K,V}
843
- ht:: Dict{Any,V}
844
- deleter:: Function
845
-
846
- WeakKeyDict () = new (Dict {Any,V} (), identity)
875
+ ht:: Dict{WeakRef,V}
876
+ WeakKeyDict () = new (Dict {WeakRef,V} ())
847
877
end
848
878
WeakKeyDict () = WeakKeyDict {Any,Any} ()
849
879
850
- function weak_key_delete! (t:: Dict , k)
880
+ function weak_key_delete! (t:: Dict , k:: WeakRef )
851
881
# when a weak key is finalized, remove from dictionary if it is still there
852
882
wk = getkey (t, k, secret_table_token)
853
- if ! is (wk,secret_table_token) && is (wk . value , k)
883
+ if is (wk, k)
854
884
delete! (t, k)
855
885
end
856
886
end
857
887
858
888
function setindex! {K} (wkh:: WeakKeyDict{K} , v, key)
859
889
t = wkh. ht
860
890
k = convert (K, key)
861
- if is (wkh. deleter, identity)
862
- wkh. deleter = x-> weak_key_delete! (t, x)
863
- end
864
- t[WeakRef (k)] = v
891
+ wr = WeakRef (k)
892
+ t[wr] = v
865
893
# TODO : it might be better to avoid the finalizer, allow
866
894
# wiped WeakRefs to remain in the table, and delete them as
867
895
# they are discovered by getindex and setindex!.
868
- finalizer (k, wkh . deleter )
896
+ finalizer (k, x -> weak_key_delete! (t, wr) )
869
897
return t
870
898
end
871
899
0 commit comments