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