// cache.sr


get "BRAVO1.DF"
get "CACHE.DF"
get "VM.DF"


// Outgoing Procedures

external	[
	PlGetCache
	SiPutCache
	CiInCache
	]


// Outgoing Statics

// external


// Incoming Procedures

external	[
	GetSi
	SiPut
	CallersFrame
	gets
	umin
	move
	ult
	errhlta
	LruInc
	DlruOld
	ugt
	]


// Incoming Statics

external	[
	mpfnof
	]


// Local Statics

// static


// Local Structures

// structure


// Local Manifests

manifest	[
	pidCii = 1
	pidPl = 1
	pidCi = 3
	]


// P L   G E T   C A C H E

let PlGetCache(cache, si) = valof		// manifest pidCii (si) above
[
let lnci = cache>>CACHE.lnci
let lnpl = lnci - offaplCi
let ci = CiEn(cache, FCiiFound)
if ci ne ciNil then
	[
	ci>>CI.tlru = LruInc(lv cache>>CACHE.tlru)
	resultis lv ci>>CI.apl
	]
if lnci gr lnciMax then errhlta(214)
let pl = vec lnciMax - offaplCi
pl>>PL.cw = lnciMax - offaplCi
GetSi(pl, si, lnciMax - offaplCi)
resultis lv CiCache(cache, si, pl)>>CI.apl
] // end PlGetCache


// F   C I I   F O U N D

and FCiiFound(cache, ci, fmPlGetCache) =
	ci>>CI.cii eq fmPlGetCache ! pidCii
// end FCiiFound


// S I   P U T   C A C H E

and SiPutCache(cache, pl) = valof
[
let ci = CiInCache(cache, pl)
if ci ne ciNil then
	[
	ci>>CI.tlru = LruInc(lv cache>>CACHE.tlru)
	resultis ci>>CI.cii
	]
let si = SiPut(siNil, pl)
CiCache(cache, si, pl)
resultis si
] // end SiPutCache


// C I   I N   C A C H E

and CiInCache(cache, pl) =		// manifest pidPl above
	CiEn(cache, FCiFound)
// end CiInCache


// F   C I   F O U N D

and FCiFound(cache, ci, fmCiInCache) = valof
[
let lnci = cache>>CACHE.lnci
let lnpl = lnci - offaplCi
let pl = lv ci>>CI.apl
let plCompare = fmCiInCache ! pidPl
let cwCompare = plCompare>>PL.cw
for iw = 0 to umin(cwCompare, lnpl)-1 do
	if pl ! iw ne plCompare ! iw then resultis false
if cwCompare gr lnpl then
	[
	(mpfnof ! fnscrfs)>>OF.pos = (ci>>CI.cii + lnpl) lshift 1
	for iw = lnpl to cwCompare-1 do
		if gets(fnscrfs) ne plCompare ! iw then
			resultis false
	]
resultis true
] // end FCiFound


// C I   C A C H E

and CiCache(cache, si, pl) = valof
[
let ci = lv cache>>CACHE.aci		// manifest pidCi above
CiEn(cache, FOlder)
ci>>CI.cii = si
move(pl, lv ci>>CI.apl, umin(pl>>PL.cw, cache>>CACHE.lnci-offaplCi))
ci>>CI.tlru = LruInc(lv cache>>CACHE.tlru)
resultis ci
] // end CiCache


// F   O L D E R

and FOlder(cache, ci, fmCiCache) = valof
[
let lru = cache>>CACHE.tlru
if ugt(DlruOld(ci>>CI.tlru, lru),
    DlruOld((fmCiCache ! pidCi)>>CI.tlru, lru)) then
	fmCiCache ! pidCi = ci
resultis false
] // end FOlder


// C I   E N

and CiEn(cache, FProc) = valof
[
let fmCaller = CallersFrame() + ofsetParamF
let lnci = cache>>CACHE.lnci
let ci = lv cache>>CACHE.aci
for i = 0 to cache>>CACHE.cci-1 do
	[
	if FProc(cache, ci, fmCaller) then resultis ci
	ci = ci + lnci
	]
resultis ciNil
] // end CiEn


// T L R U   I N C
// 
// and TlruInc(cache) = valof
// [
// let tlru = cache>>CACHE.tlru + 1
// if tlru eq 0 then errhlta(215)
// cache>>CACHE.tlru = tlru
// resultis tlru
// ] // end TlruInc