Data-Layout-BuddySystem
view release on metacpan or search on metacpan
lib/Data/Layout/BuddySystem.pm view on Meta::CPAN
print for qx(zip $z $0 && aws s3 cp $z s3://AppaAppsSourceVersions/$z && rm $z);
}
#1 Methods
sub new # Create a new Buddy system
{return bless {};
}
sub freeChains{$_[0]{freeChains} //= []} ## Addresses of free blocks organised by power of two size
sub usedSize {$_[0]{usedSize} //= {}} ## {address} = size of allocation at that address
sub wentTo {$_[0]{wentTo} //= {}} ## {address1} = address2 - where address 1 was relocated to by copy
sub cameFrom {$_[0]{cameFrom} //= {}} ## {address1} = address2 - where address 1 came from before being copied
sub allFrees {$_[0]{allFrees} //= []} ## [chain] = count of allocations minus frees on this chain
sub nameAlloc {$_[0]{nameAlloc} //= {}} ## {name} = name of allocation if a name has been supplied
sub allocName {$_[0]{allocName} //= {}} ## {address} = name of allocation at this address if a name has been supplied
sub size {scalar @{$_[0]->freeChains}} ## Number of free chains in use
sub allocField($$$) # Allocate a block in the buddy system, give it a name that is invariant even after this buddy system has been copied to a new buddy system to compact its storage, and re...
{my ($buddySystem, $name, $size) = @_; # Buddy system, name of block, integer log2(size of allocation)
$name or # Check name has been supplied
confess "Name required";
lib/Data/Layout/BuddySystem.pm view on Meta::CPAN
for($s..$size) # Spread excess space across lower chains
{my $i = $size-($_+1-$s);
$buddySystem->freeChains->[$i]{(1<<$i)}++;
}
return $alloc # Return allocation
}
} # alloc
sub locateAddress($$) # Find the current location of a block by its original address after it has been copied to a new buddy system
{my ($buddySystem, $alloc) = @_; # Buddy system, address at which the block was originally located
$buddySystem->wentTo->{$alloc} // $alloc # The relocated address if there is one, else the current address
} # locateAddress
sub locateName($$) # Find the current location of a named block after it has been copied to a new buddy system
{my ($buddySystem, $name) = @_; # Buddy system, name of the block
my $alloc = $buddySystem->nameAlloc->{$name}; # Address of named block
defined($alloc) or confess "No such named block: $name"; # Complain of no such block exists
$buddySystem->locateAddress($alloc) # The relocated address if there is one, else the current address
} # locateName
sub sizeAddress($$) # Size of allocation at an address
{my ($buddySystem, $address) = @_; # Buddy system, address of allocation whiose size we want
$buddySystem->{usedSize}{$address} # Size of allocation at specified address
} # sizeAddress
sub sizeName($$) # Size of a named allocation
{my ($buddySystem, $name) = @_; # Buddy system, address of allocation whiose size we want
my $address = $buddySystem->locateName($name); # Address of allocation
lib/Data/Layout/BuddySystem.pm view on Meta::CPAN
{my $s = $U->{$u}; # Size of this used block
$T[$u] = uc $A[$s % $L];
}
}
my $T = join '', @T; # Representation as a string
say STDOUT "$title $T" if $title;
$T
} # visualise
#2 Relocation # These methods copy one buddy system to another compacting free space in the process.
sub copy($$;$) # Copy a buddy system to compact its free space, the largest blocks are placed in (0) - ascending, (1) - descending order of size, blocks that get relocated to new positi...
{my ($buddySystem, $order, $copy) = @_; # Buddy system, order, optional copy method to copy an old allocation into its corresponding new allocation
my $n = new; # The new buddy system
if (my $u = $buddySystem->usedSize) # Used blocks decreasing in size but increasing by address within each size
{my @u = sort
{my $c = $order ? $u->{$b} <=> $u->{$a} : $u->{$a} <=> $u->{$b}; # 0 - Ascending, 1 - Descending order
return $c unless $c == 0;
$a <=> $b # Ascending address
} keys %$u;
for my $a(@u) # Each used block
{my $size = $u->{$a}; # Size of this block
my $A; # Address of relocated block
if (my $name = $buddySystem->allocName->{$a}) # Name attached to the block
{$A = $n->allocField($name, $size); # Create new block with same name in new buddy system
}
else
{$A = $n->alloc($size); # Matching block in new buddy system
}
$copy->($a, $A, $size) if $copy; # Copy data from old block to new block, using the specified size
if (my $f = $buddySystem->cameFrom->{$a}) # Address this block originally came from if different from new address
{if ($f != $A) # Record new position if different
{$n->cameFrom->{$A} = $f; # The original address at which the block was allocated
lib/Data/Layout/BuddySystem.pm view on Meta::CPAN
Parameter Description
1 $buddySystem Buddy system
=head2 Relocation
These methods copy one buddy system to another compacting free space in the process.
=head3 copy($buddySystem, $order, $copy)
Copy a buddy system to compact its free space, the largest blocks are placed in (0) - ascending, (1) - descending order of size, blocks that get relocated to new positions in the new buddy system will still be accessible by their original address or ...
Parameter Description
1 $buddySystem Buddy system
2 $order order
3 $copy optional copy method to copy an old allocation into its corresponding new allocation
=head3 copyLargestLast($buddySystem, $copy)
Copy a buddy system, compacting free space, the new addresses of allocations can be found in wentTo, the largest blocks are placed last
( run in 0.584 second using v1.01-cache-2.11-cpan-71847e10f99 )