Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 465 lines (400 sloc) 15.913 kb
663f68c @rcaputo Initial revision
authored
1 $Id$
2
bfdcb0e @rcaputo pointless...
authored
3 A brief, pointless history of POE's evolution.
663f68c @rcaputo Initial revision
authored
4
5 -------------------------------------------------------------------------------
6
7 Received: from sinistar.idle.com (sinistar.idle.com [198.109.160.36])
8 by anshar.shadow.net (8.7.3/8.7.3) with ESMTP id JAA05315
9 for <troc@shadow.net>; Fri, 7 Feb 1997 09:59:05 -0500 (EST)
10 Received: (from slist@localhost) by sinistar.idle.com (8.7.5/8.7.3)
11 id JAA12501; Fri, 7 Feb 1997 09:00:15 -0500 (EST)
12 Resent-Date: Fri, 7 Feb 1997 09:00:15 -0500 (EST)
13 Message-Id: <199702071400.JAA00295@anshar.shadow.net>
14 From: "Rocco Caputo" <troc@shadow.net>
15 To: "Felix Gallo" <fgallo@wellspring.us.dg.com>,
16 "perl5-porters@perl.org" <perl5-porters@perl.org>
17 Date: Fri, 07 Feb 97 08:54:23 -0400
18 Reply-To: "Rocco Caputo" <troc@shadow.net>
19 Priority: Normal
20 Subject: portable multithreading
21 Resent-Message-ID: <"O2kshC.A.W5C.lTz-y"@sinistar>
22 Resent-From: perl5-porters@perl.org
23 X-Mailing-List: <perl5-porters@perl.org> archive/latest/135
24 X-Loop: perl5-porters@perl.org
25 Precedence: list
26 Resent-Sender: perl5-porters-request@perl.org
27 Content-Type: text
28 Content-Length: 3989
29 Status:
30
31 On Thu, 06 Feb 1997 12:52:56 +0000, Felix Gallo wrote:
32
33 >Felix's Perl-related Metaproblems:
34 >
35 >1. Perl is not event-driven, so programs which wish
36 >to make objects available to the network must manually
37 >interrupt their control flow to determine if a remote
38 >object transaction request is pending.
39
40 I'm writing a MUD in perl. The object language faces
41 some of the same issues as perl, but I think there are
42 ways around them (in the MUD language and in perl). In
43 the MUD server, objects' methods must be compiled into
44 perl bytecode. They must be multitasked/multithreaded
45 so that bad code won't hang the server, and object
46 authors usually should not have to think about events.
47
48 For example, this "bad" MUD code will be legal. Don't
49 worry, I move on to perl in just a minute.
50
51 count = 10000000
52 while count--
53 say "hello, world! enter some text: "
54 getline some_text
55 if some_text eq 'quit'
56 last
57 endif
58 endwhile
59 say "\ngoodbye, world!\n"
60
61 This needs to be compiled to perl bytecode at runtime.
62 The MUD bytecode compiler first parses and syntax
63 checks an object's source. If everything passes, it
64 builds a perl sub definition in a string. This
65 sub-in-a-string is treated as an assembly language for
66 perl bytecode. The server runs eval() to assemble the
67 string-o-perl into bytecodes, and then the resulting sub
68 can be called over and over without additional eval()
69 overhead. (Thanks, Silmaril!)
70
71 Making that bad loop work in an event-driven server is
72 a little harder than making bytecodes. The MUD compiler
73 will build perl assembly as event-driven state machines.
74 It can do this by noting the locations of branch
75 destinations and returns from blocking calls. Each of
76 these locations starts a new atomic "state", and an
77 "instruction pointer" determines which state to run next.
78
79 Here's the event-driven perl "assembly" for that sample
80 MUD code. It's not very efficient, but it serves for
81 illustration.
82
83 sub aaaaa {
84 # assumes the existence of a tasking/event kernel
85 my $task = shift;
86 my $namespace = $task->{"namespace"};
87 my $ip = $task->{'instruction pointer'}; # state
88
89 # initial entry point
90 if ($ip == 0) {
91 $namespace->{'count'} = 10000000 ;
92 $task->{'instruction pointer'} = 1;
93 }
94 # top of while loop
95 elsif ($ip == 1) {
96 if ( $namespace->{'count'} -- ) {
97 $task->say( qq(hello, world! enter some text: ) ) ;
98 # soft block on 'getline'
99 $task->{'blocking'} = 'getline';
100 $task->{'instruction pointer'} = 2;
101 }
102 else {
103 $task->{'instruction pointer'} = 3;
104 }
105 }
106 # "return" from getline
107 elsif ($ip == 2) {
108 $namespace->{'some_text'} = $task->getline();
109 if ( $namespace->{'some_text'} eq q(quit) ) {
110 $task->{'instruction pointer'} = 3;
111 }
112 else {
113 $task->{'instruction pointer'} = 1;
114 }
115 }
116 # after endwhile
117 elsif ($ip == 3) {
118 $task->say( qq(\ngoodbye, world!\n) ) ;
119 $task->{'instruction pointer'} = -1; # signals end
120 }
121 }
122
123 The main select/event loop would have some code to run tasks
124 round-robin. Something like this, but probably including code
125 to deal with priorities.
126
127 if ($next = shift(@task_queue)) {
128 if (($next->{'blocking'}) || ($next->run() != -1)) {
129 push(@task_queue, $next);
130 }
131 else {
132 undef $next;
133 }
134 }
135
136 And starting a new task might look like this:
137
138 $task = new Task($tasking_kernel, "count = ... world!\n");
139 if ($task->has_errors()) {
140 $task->display_errors();
141 undef $task;
142 }
143 # otherwise the task has been compiled and registered
144 # with the $tasking_kernel
145
146 Anyway, that's how I'm writing portable multitasking for a
147 syntactically simple MUD language. To make this work for
148 perl, there would be a standard tasking package, and perl's
149 bytecode compiler would need to modify its output to work
150 with the package. Sort of like how the perl debugger works.
151
152 Just some ideas to ponder.
153
154 Rocco
155 <troc@shadow.net>
156
157 -------------------------------------------------------------------------------
158
159 Received: from sinistar.idle.com ([198.109.160.36])
160 by anshar.shadow.net (8.8.5/8.7.3) with ESMTP id VAA13861
161 for <troc@shadow.net>; Mon, 14 Apr 1997 21:04:07 -0400 (EDT)
162 Received: (from slist@localhost) by sinistar.idle.com (8.7.5/8.7.3)
163 id UAA24149; Mon, 14 Apr 1997 20:37:16 -0400 (EDT)
164 Resent-Date: Mon, 14 Apr 1997 20:37:16 -0400 (EDT)
165 Message-Id: <199704150040.UAA11517@anshar.shadow.net>
166 From: "Rocco Caputo" <troc@shadow.net>
167 To: "Gary Howland" <gary@systemics.com>,
168 "Tom Christiansen" <tchrist@jhereg.perl.com>
169 Cc: "Gary Howland" <gary@systemics.com>, "Hugo van der Sanden" <hv@iii.co.uk>,
170 "hv@tyree.iii.co.uk" <hv@tyree.iii.co.uk>,
171 "perl5-porters@perl.org" <perl5-porters@perl.org>
172 Date: Mon, 14 Apr 97 20:34:01 -0500
173 Reply-To: "Rocco Caputo" <troc@shadow.net>
174 Priority: Normal
175 MIME-Version: 1.0
176 Content-Transfer-Encoding: 7bit
177 Subject: Re: Perl5.005 wish list (event loop)
178 Resent-Message-ID: <"99mWD.A.PzF.i0sUz"@sinistar>
179 Resent-From: perl5-porters@idle.com
180 X-Mailing-List: <perl5-porters@idle.com> archive/latest/6171
181 X-Loop: perl5-porters@idle.com
182 Precedence: list
183 Resent-Sender: perl5-porters-request@idle.com
184 Content-Type: text/plain; charset="iso-8859-1"
185 Content-Length: 1119
186 Status:
187
188 Gary, et al,
189
190 Almost a year ago, I quietly announced something called "Serv + Face".
191 Maybe my announcement was a little too quiet.
192
193 Serv is a fork-less, select-based framework of event server classes.
194 It provides a high level interface to select(), and a very high level
195 interface to TCP client and server socket operations. It does not fork.
196
197 Face is the start of a curses-based UI framework that can run alone
198 or use Serv as its main loop.
199
200 The code and a rough draft of the documentation are available from
201 <http://www.shadow.net/~troc/perlstuff.html>. If this code is useful
202 to anyone, I'd sure like to know.
203
204 Rocco
205 <troc@shadow.net>
206
207 On Tue, 15 Apr 1997 01:36:35 +0200, Gary Howland wrote:
208 >
209 >Select is fine. What we (the "event evangelists") want is a "level above"
210 >select. When we have a chunk of data to send to x streams, we don't want to
211 >have to call select, see which stream is ready for writing, work out how
212 >many bytes we can send, send those bytes, shorten our buffers by that amount
213 >of bytes, and loop back to select. We just want to send the data. And we
214 >want to do this without forking.
215
216 -------------------------------------------------------------------------------
217
218 Received: from sinistar.idle.com (sinistar.idle.com [198.109.160.36])
219 by anshar.shadow.net (8.7.3/8.7.3) with ESMTP id JAA04948
220 for <troc@shadow.net>; Fri, 7 Feb 1997 09:54:31 -0500 (EST)
221 Received: (from slist@localhost) by sinistar.idle.com (8.7.5/8.7.3)
222 id JAA12519; Fri, 7 Feb 1997 09:00:19 -0500 (EST)
223 Resent-Date: Fri, 7 Feb 1997 09:00:19 -0500 (EST)
224 Message-Id: <199702071400.JAA00339@anshar.shadow.net>
225 From: "Rocco Caputo" <troc@shadow.net>
226 To: "Felix Gallo" <fgallo@wellspring.us.dg.com>,
227 "perl5-porters@perl.org" <perl5-porters@perl.org>
228 Date: Fri, 07 Feb 97 08:54:31 -0400
229 Reply-To: "Rocco Caputo" <troc@shadow.net>
230 Priority: Normal
231 Subject: polytheistic perl references
232 Resent-Message-ID: <"1y3hHB.A.w5C.sTz-y"@sinistar>
233 Resent-From: perl5-porters@perl.org
234 X-Mailing-List: <perl5-porters@perl.org> archive/latest/136
235 X-Loop: perl5-porters@perl.org
236 Precedence: list
237 Resent-Sender: perl5-porters-request@perl.org
238 Content-Type: text
239 Content-Length: 1502
240 Status:
241
242 On Thu, 06 Feb 1997 12:52:56 +0000, Felix Gallo wrote:
243
244 >Felix's Perl-related Metaproblems:
245 >
246 >3. Perl references are monotheistic. One fancies that saying
247 >$x = \{ http://perl.com/myperlobject }; would do the right thing,
248 >but the established structure of Perl seems to make this difficult.
249
250 There are tied hash packages that implement object naming
251 and message passing between named objects within the same
252 process. The packages allow invocations like:
253
254 $msg{'desktop,paint'} = 1;
255 $msg{'name entry,value'} = 'J. K. Cohen';
256 $active_flag = $msg{'active checkbox,value'};
257
258 The packages also do broadcasting to subsets of the object
259 dictionary. Hash stores and fetches are sent to or taken
260 from all the objects that match the supplied name. So to
261 clear the value of all objects that have 'entry' in their
262 names:
263
264 $msg{'entry,value'} = '';
265
266 That clears 'name entry' and 'age entry' and 'salary entry'
267 and ....
268
269 Anyway, the names could be extended to work across sockets
270 in the presence of a standard select/event loop:
271
272 $gnats_queue = $msg{'//somewhere.com:4242/stickynote/gnat?count'};
273 print "gnat has $gnats_queue unread sticky notes.\n";
274
275 $message = 'hello, world!';
276 $msg{'//somewhere.org:4242/stickynote/merlyn?queue'} = $message;
277
278 Man pages for ObjDict::Names and ObjDict::Messages are
279 on-line at <http://www.nexi.com/troc>. The code is inside
280 a larger package, Serv+Face, at
281 <http://www.shadow.net/~troc/perlstuff.html>.
282
283 Just some ideas to ponder.
284
285 Rocco
286 <troc@shadow.net>
287
288 -------------------------------------------------------------------------------
289
9e1cd8e @rcaputo explained UberSys a little
authored
290 This is a header from a program I was writing before I discovered Perl.
291
663f68c @rcaputo Initial revision
authored
292 // =========================================================================
293 // UBERSYS.H
294 // UberSys definitions and classes.
295 // =========================================================================
296
297 #include <io.h>
298 #include <dir.h>
299 #include <dos.h>
300 #include <math.h>
301 #include <time.h>
302 #include <alloc.h>
303 #include <conio.h>
304 #include <ctype.h>
305 #include <fcntl.h>
306 #include <share.h>
307 #include <stdio.h>
308 #include <setjmp.h>
309 #include <stdarg.h>
310 #include <stddef.h>
311 #include <stdlib.h>
312 #include <string.h>
313 #include <values.h>
314 #include <fstream.h>
315 #include <iomanip.h>
316 #include <iostream.h>
317 #include <sys\stat.h>
318
319 // -------------------------------------------------------------------------
320 // Constants, limits, and the like.
321
322 #define SIZE_UID 9 // including NULL terminator
323 #define SIZE_PWD 26 // including NULL terminator
324 #define SIZE_MAXSTR 0x1000 // 4k string sizes (max)
325 #define SIZE_MAXPATH 0x0050 // 160 chars for max path
326 #define SIZE_MAXLINE 0x00A0 // 160 characters per line
327 #define COUNT_LINES 0x0200 // 512 editor lines
328
329 #define USREV 0x0200 // version 02.00
330
331 #define DRV "D:" // drive it runs on
332
333 // -------------------------------------------------------------------------
334 // Helper macros.
335 // build a 20-bit address from segoff
336 #define A20(x) (((ULI)FP_SEG(x)<<4)+(ULI)FP_OFF(x))
337 // make a normalized pointer from A20
338 #define A32(x) MK_FP((UINT)((x)>>4), (UINT)((x)&0x0F))
339 // normalize a far pointer using A20
340 #define NORM(x) A32(A20(x))
341 // maximum of two values
342 template <class T>
343 T max(T x, T y)
344 {
345 return((x>y)?x:y);
346 };
347 // minimum of two values
348 template <class T>
349 T min(T x, T y)
350 {
351 return((x<y)?x:y);
352 };
353 // inline assembly shorthand
354 #define I asm
355
356 #define FATAL fatalerr(thisFile,__LINE__)
357 #define FATALH(x) fatalerr(x,__LINE__)
358
359 #if defined(DEBUG)
360 # define ERRS if(errorstream)*errorstream<<setiosflags(ios::uppercase)<<hex
361 # define CRV(x) if((x)==RV_FAILURE)FATAL
362 # define CNE(x) if((x)==-1)FATAL
363 # define CZE(x) if(!(x))FATAL
364 # define FLINE ,thisFile,__LINE__
365 # define FLINC thisFile,__LINE__
366 # define FLINP , char *file, int line
367 # define FLINQ char *file, int line
368 # define FLINI ,file,line
369 # define FLINJ file,line
370 # define FLINS thisFile,__LINE__,
371 # define FLINT char *file, int line,
372 # define FLI dec<<");\t\t// f:"<<setw(12)<<file<<" @ l:"<<setw(4)<<line
373 # define BOTH(x) A20(x)<<" ["<<A20(*(x))<<"]"
374 # define DEB(x) x
375 # define DEB2(x,y) x,y
376 # define NEW ERRS<<dec<<"\nCall to new.\t\t\t\t\t// f:"<<setw(12)<<thisFile<<" @ l:"<<setw(4)<<__LINE__;
377 # define DEL ERRS<<dec<<"\nCall to delete.\t\t\t\t\t// f:"<<setw(12)<<thisFile<<" @ l:"<<setw(4)<<__LINE__;
378 # define WHEREAMI ERRS<<dec<<"\nInside file "<<thisFile<<" @ line "<<__LINE__;
379 # define ORPHANS { ERRS<<dec<<"\nOrphan check in "<<thisFile<<" @ line "<<__LINE__<<". "; CRV(aOrphans(FLINC)); }
380 # define VALID(dp) CZE(aValid(aHeader(dp)));
381 # define DUMP aDump(FLINC);
382 #else
383 # define ERRS cerr
384 # define CRV(x) x
385 # define CNE(x) x
386 # define FLINE
387 # define FLINC
388 # define FLINP
389 # define FLINQ void
390 # define FLINI
391 # define FLINJ
392 # define FLINS
393 # define FLINT
394 # define DEB(x)
395 # define DEB2(x,y)
396 # define NEW
397 # define DEL
398 # define WHEREAMI
399 # define ORPHANS
400 # define VALID(dp)
401 # define DUMP
402 #endif
403
404 #define FALSE 0
405 #define TRUE (~FALSE)
406
407 // -------------------------------------------------------------------------
408
409 void fatalerr(char *file, int line);
410
411 extern char *buildbuf;
412
413 // -------------------------------------------------------------------------
414 // Paradox Engine header
415 #include "pxengine.h"
416 // Error stream if debugging.
417 DEB(extern ofstream *errorstream;)
418 // Message file header.
419 #include "general.h"
420 // Type definitions.
421 #include "mytypes.h"
422 // Database functions.
423 #include "pxe.h"
424 #include "users.h"
425 #include "ipx.h"
426 // Code groups.
427 #include "pcodes.h"
428 #include "gsbl.h"
429 #include "arena.h"
430 #include "interrup.h"
431 #include "port.h"
432 #include "msgfile.h"
433 #include "task.h"
434 #include "tam.h"
435 #include "qualpath.h"
436 #include "xmm.h"
437 #include "var.h"
438 #include "safepxi.h"
439 #include "template.h"
440 #include "token.h"
441 #include "stack.h"
442 #include "objfile.h"
443 #include "ofm.h"
444 #include "srcfile.h"
445 #include "pmachine.h"
446 // BBS modules.
447 #include "hangup.h"
448 #include "idle.h"
449 #include "login.h"
450 #include "editor.h"
451 #include "cmdline.h"
452 #include "console.h"
453 #include "dirlist.h"
454 #include "compiler.h"
455 #include "disasm.h"
456 #include "runtime.h"
457
458 // -------------------------------------------------------------------------
459
460 extern TAM *tam;
461
462 -------------------------------------------------------------------------------
463
464 Light was let be.
Something went wrong with that request. Please try again.