(* :Title: Memory Conservation Utilities *)

(* :Context: Utilities`MemoryConserve` *)

(* :Copyright: Copyright 1992-1999, Wolfram Research, Inc.*)

(* :Author: Tom Wickham-Jones *)

(* :Summary:
This package implements automatic calls to Share[] when MemoryInUse[]
has increased by a set amount.   Sharing the storage of
common subexpressions may reduce the amount of memory which
has been used so far in the session.
*)

(* :Package Version: 1.0 *)

(* :Mathematica Version: 2.1 *)

(* :History:
	V. 1.0, Nov. 1992, by Tom Wickham-Jones
*)


(* :Discussion:
	MemoryConserve is the name of a function which is set to $Pre.
	This function evaluates MemoryInUse[] and when this value
	increases by $MemoryIncrement Share[] will be called.  
	It then sends the input expression to the evaluator
	and the system will work normally.
	The package will save an older version of $Pre which has been
	set.   If you reassign $Pre after loading the package, it
	will be necessary to enable memory conservation again with
	On[ MemoryConserve].
*)



BeginPackage["Utilities`MemoryConserve`"]

MemoryConserve::usage = "MemoryConserve will reduce memory use with the
	Share function when memory used has increased by $MemoryIncrement.  
	On[ MemoryConserve] will use $Pre to make this happen automatically." 

$MemoryIncrement::usage = "$MemoryIncrement sets the amount by which memory
	must increase for MemoryConserve to call Share[]."

MemoryConserve::start = "Running Share[] to conserve memory."

MemoryConserve::end = "Finished running Share[]; `1` bytes of memory freed."

MemoryConserve::twice = "MemoryConserve is already on."
MemoryConserve::off = "MemoryConserve is not in effect."

Begin["`Private`"]

oldPre = Identity        (* user's value of $Pre *)
ison = False       (* whether ShowTime is currently turned on *)

Attributes[MemoryConserve] = HoldFirst

LastMemoryUsed = MemoryInUse[]
$MemoryIncrement = 100000

MemoryConserve[expr_] :=
	Block[{res},
		If[ MemoryInUse[] - LastMemoryUsed > $MemoryIncrement,
			Message[ MemoryConserve::start] ;
			res = Share[];
			Message[ MemoryConserve::end, res];
			LastMemoryUsed = MemoryInUse[]] ;
		If[ !ison, $Pre = oldPre] ;
		oldPre[ expr]
	]

MemoryConserve/: On[MemoryConserve] := (
	If[ ison,
		Message[MemoryConserve::twice],
		oldPre = If[ ValueQ[$Pre], $Pre, Identity ];
		$Pre = MemoryConserve;
		ison = True
	];)

MemoryConserve/: Off[MemoryConserve] := (
	If[ ison,
		ison = False;
		$Pre = oldPre,
	(* else *)
		Message[MemoryConserve::off]
	]; )

End[]

EndPackage[]

On[MemoryConserve]

Null
