aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/EmMinimize.h
blob: 44fe7888241821688fbdef6879fe9c55f601cf7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* -*- mode: C++; tab-width: 4 -*- */
/* ===================================================================== *\
	Copyright (c) 2001 Palm, Inc. or its subsidiaries.
	All rights reserved.

	This file is part of the Palm OS Emulator.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
\* ===================================================================== */

#ifndef EmMinimize_h
#define EmMinimize_h

#include "EmStructs.h"			// GremlinEvent

#include "omnithread.h"			// omni_mutex

#include <vector>				// vector

class SessionFile;

class EmMinimize
{
	public:
		static void 			Initialize				(void);
		static void 			Reset					(void);
		static void 			Save					(SessionFile&);
		static void 			Load					(SessionFile&);
		static void 			Dispose 				(void);

		static void				Start					(void);
		static void				Stop					(void);
		static void				TurnOn					(Bool);
		static Bool				IsOn					(void);

		static void				NoErrorOccurred			(void);
		static void				ErrorOccurred			(void);

		static uint32			GetPassNumber			(void);
		static uint32			GetElapsedTime			(void);
		static void				GetCurrentRange			(uint32&, uint32&);
		static uint32			GetNumDiscardedEvents	(void);
		static uint32			GetNumInitialEvents		(void);

	private:
		static void				MinimizationPassComplete(void);
		static void				MinimizationComplete	(void);
		static void				SaveMinimalEvents		(void);
		static void				OutputEventsAsEnglish	(void);
		static Bool				MakeAnotherPass			(long oldNumEvents, long newNumEvents);
		static void				CurrentRange			(long& begin, long& end);
		static void				InitialLevel			(void);
		static Bool				SplitCurrentLevel		(void);
		static void				StartAgain				(void);
		static void				SplitAndStartAgain		(void);
		static void				DisableAndStartAgain	(void);
		static void				NextSubRange			(void);
		static void				LoadInitialState		(void);

	public:
		static void				RealLoadInitialState	(void);

	private:
		static void				LoadEvents				(void);
		static long				FindFirstError			(void);
		static void				GenerateStackCrawl		(StringList&);


	private:
		struct EmMinimizeLevel
		{
			long	fBegin;
			long	fEnd;

			// The following Boolean is used to indicate that the above range
			// has already been checked in some fashion and that we know or
			// strongly suspect that a needed event is in here somewhere.  The
			// practical effect of this is that when finish with one event
			// range and are popping to this event range (as opposed to
			// splitting the range we just finished and testing each of the
			// split ranges), then should we split this new range, too, or
			// should we test the whole thing first.  Knowing whether or not
			// to split a range that we're considering is important, since it
			// reduces the overall number of passes we have to make.
			//
			// fChecked is managed as follows: When the initial event ranges
			// are determined and pushed onto the fLevels stack, fChecked is
			// clear.  This means that each range is checked before
			// determining to keep it or split it and check it further.  If we
			// test a range and find that we don't need it, we discard that
			// range and don't consider it any further.  If, however, we find
			// that we need a range (because removing it cause the crash to go
			// away), then we set fChecked for that range, subdivide it, and
			// start checking the new sub-ranges.  When we create the new
			// sub-ranges, we copy the fChecked setting for the child ranges. 
			// For as long as we subdivide and retest subranges, we copy that
			// bit to the new sub ranges.
			//
			// However, as soon as we get down to the single event level and
			// determine that we need a particular event and can't subdivide
			// any longer, we walk up the stack and clear all fChecked
			// Booleans.  The idea here is that if there was just a single
			// event in the range that we needed to find and mark as
			// important, then we just found it.  We can no longer assume that
			// any other events in the initial range that we've been
			// subdividing are important, and so we need to clear the bit that
			// means that there's an important event within them.

			Bool	fChecked;
		};

		typedef vector<EmMinimizeLevel>	EmMinimizeLevelList;

		struct EmMinimizeState
		{
			EmMinimizeLevelList	fLevels;
		};

		static omni_mutex		fgMutex;
		static EmMinimizeState	fgState;
		static Bool				fgIsOn;
		static uint32			fgStartTime;
		static long				fgInitialNumberOfEvents;
		static long				fgDiscardedNumberOfEvents;
		static long				fgPassNumber;
		static Bool				fgPassEndedInError;
		static StringList		fgLastStackCrawl;
};

#endif // EmMinimize_h