working flip-flop via DESTROY approach
[p5sagit/Mutually-Assured-Destruction.git] / notes / flip-flop.pl
CommitLineData
4fb76cf4 1#!/usr/bin/env perl
2
3use strict;
4use warnings;
5use Scalar::Util qw(weaken isweak);
6
7# $X strong -> $Y
8# $Y weak -> $X
9#
10# $Y goes out of scope - all fine
11#
12# $X goes out of scope - need to swap to
13#
14# $X weak -> $Y
15# $Y strong -> $X
16#
17# but not if $Y is already out of scope - so don't do it unless $Y's refcount
18# is >1
19
20BEGIN {
21 package Foo;
22
23 use Devel::GlobalDestruction 'in_global_destruction';
24 use Scalar::Util qw(weaken isweak);
25 use Devel::Refcount qw(refcount);
26
27 sub DESTROY {
28 my $self = shift;
29 warn "DESTROY fired for $self\n";
30 return if in_global_destruction;
31 warn "Not in global destruction\n";
32 return unless isweak $self->{back}{forward};
33 warn "Reference to us is weak\n";
34 return unless $self->{forward};
35 warn "Have forward pointer\n";
36 return unless refcount($self->{forward}) > 1;
37 warn "Next in chain has refcount of ".(refcount $self->{forward})."\n";
38 $self->{back}{forward} = $self; #->{back}{forward};
39 weaken $self->{forward};
40 warn "Swapped links - $self now has weak ref to ${\$self->{forward}} and ${\$self->{back}} has a strong ref to $self\n";
41 return;
42 }
43}
44
45# set this shit up
46my $one = bless({}, 'Foo');
47my $two = bless({}, 'Foo');
48weaken(my $weak_one = $one);
49weaken(my $weak_two = $two);
50$one->{forward} = $two;
51weaken($two->{forward} = $one);
52weaken($one->{back} = $two);
53weaken($two->{back} = $one);
54
55sub status {
56 warn "One: ${\($weak_one||'GONE')} Two: ${\($weak_two||'GONE')}\n";
57 warn "One's forward is${\(isweak($weak_one->{forward}) ? '' : ' not')} weak\n" if $weak_one;
58 warn "Two's forward is${\(isweak($weak_two->{forward}) ? '' : ' not')} weak\n" if $weak_two;
59}
60
61warn "\$one is $one, \$two is $two";
62warn "Undefining \$two\n";
63undef($two);
64status;
65warn "Restoring \$two\n";
66$two = $weak_two;
67warn "Undefining \$one\n";
68undef($one);
69status;
70warn "Restoring \$one\n";
71$one = $weak_one;
72warn "Undefining \$two\n";
73undef($two);
74status;
75warn "Restoring \$two\n";
76$two = $weak_two;
77warn "Undefining both\n";
78undef($one);
79undef($two);
80status;
81warn "Done\n";