source: branches/textos/UKernel.pas

Last change on this file was 53, checked in by chronos, 6 months ago
  • Added: Experimental textos computer.
File size: 6.1 KB
Line 
1unit UKernel;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, Forms, Generics.Collections, UApp, UApi, UTextBuffer;
9
10type
11 TKernel = class;
12 TAppContext = class;
13
14 { TKernelApi }
15
16 TKernelApi = class(TApi)
17 Kernel: TKernel;
18 AppContext: TAppContext;
19 procedure Sleep(Time: TDateTime); override;
20 function GetMessage: TApiMessage; override;
21 function InputText: string; override;
22 procedure OutputText(Text: string); override;
23 procedure Terminate; override;
24 procedure ExecuteApp(Name: string); override;
25 end;
26
27 { TAppThread }
28
29 TAppThread = class(TThread)
30 AppContext: TAppContext;
31 procedure Execute; override;
32 end;
33
34 TAppState = (asSleep, asRunning, asTerminated);
35
36 { TAppContext }
37
38 TAppContext = class
39 AppState: TAppState;
40 App: TApp;
41 AppDescription: TAppDescription;
42 InputBuffer: TTextBuffer;
43 OutputBuffer: TTextBuffer;
44 Messages: TList<TApiMessage>;
45 Thread: TAppThread;
46 procedure Start;
47 procedure Stop;
48 constructor Create;
49 destructor Destroy; override;
50 end;
51
52 TOutputTextEvent = procedure (Text: string) of object;
53
54 { TKernel }
55
56 TKernel = class
57 private
58 FOnOutputText: TOutputTextEvent;
59 FAppContexts: TObjectList<TAppContext>;
60 FCurrentApp: TAppContext;
61 FAppDescriptions: TAppDescriptions;
62 procedure Schedule;
63 function AddAppContext(AppDescription: TAppDescription): TAppContext;
64 procedure DoOutputText(Text: string);
65 procedure RemoveTerminated;
66 public
67 Terminated: Boolean;
68 function AddApp(Name: string; AppClass: TAppClass): TAppDescription;
69 procedure Start;
70 procedure Input(Text: string);
71 procedure InputKey(Key: Word);
72 constructor Create;
73 destructor Destroy; override;
74 property OnOutputText: TOutputTextEvent read FOnOutputText write FOnOutputText;
75 end;
76
77
78implementation
79
80{ TAppThread }
81
82procedure TAppThread.Execute;
83begin
84 while not Terminated do begin
85 AppContext.App.Run;
86 end;
87 AppContext.AppState := asTerminated;
88end;
89
90{ TAppContext }
91
92procedure TAppContext.Start;
93begin
94 Thread.Resume;
95end;
96
97procedure TAppContext.Stop;
98begin
99 Thread.Terminate;
100end;
101
102constructor TAppContext.Create;
103begin
104 InputBuffer := TTextBuffer.Create;
105 OutputBuffer := TTextBuffer.Create;
106 Messages := TList<TApiMessage>.Create;
107 Thread := TAppThread.Create(True);
108 Thread.AppContext := Self;
109end;
110
111destructor TAppContext.Destroy;
112begin
113 FreeAndNil(Thread);
114 FreeAndNil(Messages);
115 FreeAndNil(InputBuffer);
116 FreeAndNil(OutputBuffer);
117 inherited;
118end;
119
120{ TKernelApi }
121
122procedure TKernelApi.Sleep(Time: TDateTime);
123begin
124
125end;
126
127function TKernelApi.GetMessage: TApiMessage;
128begin
129 while AppContext.AppState <> asTerminated do begin
130 if AppContext.AppState = asTerminated then begin
131 Result := amTerminate;
132 Break;
133 end else begin
134 if AppContext.InputBuffer.Size > 0 then begin
135 Result := amInputText;
136 Break;
137 end;
138 end;
139 Sleep(1);
140 end;
141end;
142
143function TKernelApi.InputText: string;
144begin
145 Result := AppContext.InputBuffer.Read;
146end;
147
148procedure TKernelApi.OutputText(Text: string);
149begin
150 AppContext.OutputBuffer.Write(Text);
151end;
152
153procedure TKernelApi.Terminate;
154begin
155 AppContext.AppState := asTerminated;
156 AppContext.Thread.Terminate;
157end;
158
159procedure TKernelApi.ExecuteApp(Name: string);
160var
161 AppDescription: TAppDescription;
162 AppContext: TAppContext;
163begin
164 AppDescription := Kernel.FAppDescriptions.SearchByName(Name);
165 if Assigned(AppDescription) then begin
166 AppContext := Kernel.AddAppContext(AppDescription);
167 AppContext.Start;
168 Kernel.FCurrentApp := Kernel.FAppContexts[Kernel.FAppContexts.Count - 1];
169 end;
170end;
171
172{ TKernel }
173
174procedure TKernel.Schedule;
175var
176 I: Integer;
177begin
178 I := FAppContexts.IndexOf(FCurrentApp);
179 if FAppContexts.Count > 0 then begin
180 I := (I + 1) mod FAppContexts.Count;
181 FCurrentApp := FAppContexts[I];
182 end else FCurrentApp := nil;
183end;
184
185function TKernel.AddAppContext(AppDescription: TAppDescription): TAppContext;
186var
187 App: TApp;
188begin
189 App := AppDescription.AppClass.Create;
190 Result := TAppContext.Create;
191 Result.App := App;
192 Result.AppDescription := AppDescription;
193 App.Api.Parent := TKernelApi.Create;
194 TKernelApi(App.Api.Parent).AppContext := Result;
195 TKernelApi(App.Api.Parent).Kernel := Self;
196 FAppContexts.Add(Result);
197end;
198
199procedure TKernel.DoOutputText(Text: string);
200begin
201 if Assigned(FOnOutputText) then FOnOutputText(Text);
202end;
203
204procedure TKernel.RemoveTerminated;
205var
206 I: Integer;
207begin
208 for I := FAppContexts.Count - 1 downto 0 do begin
209 if FAppContexts[I].AppState = asTerminated then begin
210 FAppContexts.Delete(I);
211 if FAppContexts.Count > 0 then
212 FCurrentApp := FAppContexts[I mod FAppContexts.Count]
213 else FCurrentApp := nil;
214 end;
215 end;
216 if FAppContexts.Count = 0 then Terminated := True;
217end;
218
219function TKernel.AddApp(Name: string; AppClass: TAppClass): TAppDescription;
220begin
221 Result := TAppDescription.Create;
222 Result.Name := Name;
223 Result.AppClass := AppClass;
224 FAppDescriptions.Add(Result);
225end;
226
227procedure TKernel.Start;
228var
229 Text: string;
230begin
231 if FAppDescriptions.Count > 0 then begin
232 FCurrentApp := AddAppContext(FAppDescriptions[0]);
233 FCurrentApp.Start;
234 repeat
235 RemoveTerminated;
236 Application.ProcessMessages;
237 Sleep(1);
238
239 if Assigned(FCurrentApp) then begin
240 Text := FCurrentApp.OutputBuffer.Read;
241 if Text <> '' then begin
242 DoOutputText(Text);
243 end;
244 end;
245 until Terminated;
246 end;
247end;
248
249procedure TKernel.Input(Text: string);
250begin
251 if Assigned(FCurrentApp) then begin
252 FCurrentApp.InputBuffer.Write(Text);
253 end;
254end;
255
256procedure TKernel.InputKey(Key: Word);
257begin
258 if Key = 9 then begin
259 if FAppContexts.Count > 1 then begin
260 FCurrentApp := FAppContexts[(FAppContexts.IndexOf(FCurrentApp) + 1 ) mod FAppContexts.Count];
261 DoOutputText('Switched to ' + FCurrentApp.AppDescription.Name + LineEnding);
262 end;
263 end;
264end;
265
266constructor TKernel.Create;
267begin
268 FAppContexts := TObjectList<TAppContext>.Create;
269 FAppDescriptions := TAppDescriptions.Create;
270end;
271
272destructor TKernel.Destroy;
273begin
274 FreeAndNil(FAppContexts);
275 FreeAndNil(FAppDescriptions);
276 inherited;
277end;
278
279end.
280
Note: See TracBrowser for help on using the repository browser.