############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Chris Jefferson. ## ## Copyright of GAP belongs to its developers, whose names are too numerous ## to list here. Please refer to the COPYRIGHT file for details. ## ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file defines various types of caching data structures ## ## Note that this file is read very early in GAP's startup, so we cannot ## make MemoizePosIntFunction a method and use method dispatch, or other ## bits of nice GAP functionality. ##
InstallGlobalFunction(MemoizePosIntFunction, function(func, extra...)
local boundvals, original, uniqueobj, options, r;
# This is an object which cannot exist anywhere else
uniqueobj := "";
options := rec(
defaults := [],
flush := true,
errorHandler := function(x)
ErrorNoReturn("<val> must be a positive integer"); end);
if LEN_LIST(extra) > 0then for r in REC_NAMES(extra[1]) do if IsBound(options.(r)) then
options.(r) := extra[1].(r); else
ErrorNoReturn("Invalid option: ", r); fi;
od; fi;
if options.flush then
InstallMethod(FlushCaches, [], function()
boundvals := MakeWriteOnceAtomic(AtomicList(original));
TryNextMethod(); end); fi;
return function(val)
local v, boundcpy; if not IsPosInt(val) then
return options.errorHandler(val); fi; # Make a copy of the reference to boundvals, in case the cache # is flushed, which will causes boundvals to be bound to a new list.
boundcpy := boundvals;
v := GetWithDefault(boundcpy, val, uniqueobj); if IsIdenticalObj(v, uniqueobj) then # As the list is WriteOnceAtomic, if two threads call # func(val) at the same time they will still return the # same value (the first assigned to the list).
boundcpy[val] := func(val);
v := boundcpy[val]; fi;
return v; end; end);
InstallGlobalFunction(GET_FROM_SORTED_CACHE, function(cache, key, maker)
local pos, val;
# Check whether this has been stored already.
atomic readonly cache do
pos:= POSITION_SORTED_LIST( cache[1], key ); if pos <= Length( cache[1] ) and cache[1][pos] = key then
return cache[2][ pos ]; fi;
od;
# Compute new value.
val := maker();
# Store the value. Need to recompute pos as the maker function may have # changed the cache, eg. by recursively calling itself (resp. its "parent # function", the one containing the call to GET_FROM_SORTED_CACHE)
atomic readwrite cache do
pos:= POSITION_SORTED_LIST( cache[1], key ); if pos <= Length( cache[1] ) and cache[1][pos] = key then # oops, something else computed the value in the meantime; # so use that instead
val:= cache[2][ pos ]; else
Add( cache[1], Immutable( key ), pos );
Add( cache[2], val, pos ); fi;
od;
# Return the value.
return val; end);
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.7Angebot
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.