// M E T E R
// errors 690
//
//Code for "metering" things.
//
//MeterInit()
//	Turns on metering, sets up file for same.
//MeterClose()
//	Finishes out metering.
//MeterBlock(type,adr,cnt)
//	Writes a block of stuff on meter file.
//MeterTime()
//	Returns a 1-word time measurement
//

get "PDInternals.d"

// outgoing procedures
external
	[
	MeterInit
	MeterClose
	MeterBlock
	MeterTime
	]

// outgoing statics
//external
//	[
//	]
//static
//	[
//	]

// incoming procedures
external
	[
	WindowInit
	WindowClose
	WindowFlush
	WindowWrite
	WindowWriteBlock
	WindowReadBlock
	WindowSetPosition
	WindowGetPosition
	PDError
	]

// incoming statics
external
	[
	MeterFile
	DoFileMeter
	DPzero
	]

// internal statics
static
	[
	MeterWindow
	Metering=false
	MeterTime0
	]

// File-wide structure and manifest declarations.

// Procedures


let MeterInit() be
 [
   MeterWindow=WindowInit(MeterFile)
//First 2 words are current end position:
   let v=vec 1
   WindowReadBlock(MeterWindow, v, 2)
   WindowSetPosition(MeterWindow, v)
   MeterTime0=@#430
   Metering=true
 ]

and MeterClose() be
 [
   if Metering then
	[
	MeterBlock(METEREnd)
	Metering=false
	let v=vec 1
	WindowGetPosition(MeterWindow, v)
	WindowSetPosition(MeterWindow, DPzero)
	WindowWriteBlock(MeterWindow, v, 2)	//Save new length
	WindowSetPosition(MeterWindow, v)
	WindowFlush(MeterWindow)
	]
 ]

and MeterBlock(type,adr,cnt; numargs n) be
 [
   if Metering then
	[
	if (type eq METERRead % type eq METERWrite) & DoFileMeter eq false
		then return
	Metering=false	//Do not record page writes or recurse!
	let f=nil
	if n eq 1 then cnt=0
	f<<METERH.Type=type
	if cnt gr (1 lshift (size METERH.Count))-1 then PDError(690)
	f<<METERH.Count=cnt+1
	WindowWrite(MeterWindow, f)	//Header
	WindowWriteBlock(MeterWindow, adr, cnt)
	Metering=true
	]
 ]

and MeterTime() = (@#430)-MeterTime0