Merge lp:~fpstovall/nrtb/D_tech_demos into lp:nrtb

Proposed by Rick Stovall
Status: Merged
Merged at revision: 13
Proposed branch: lp:~fpstovall/nrtb/D_tech_demos
Merge into: lp:nrtb
Diff against target: 2348 lines (+2303/-0)
8 files modified
D_lang/testing/candidate_libs/splat.d (+1754/-0)
D_lang/testing/candidate_libs/splat.html (+269/-0)
D_lang/testing/str_socket/Makefile (+30/-0)
D_lang/testing/str_socket/SocketStringTransciever.mm (+49/-0)
D_lang/testing/str_socket/socket_test.d (+43/-0)
D_lang/testing/thread_pool/Makefile (+30/-0)
D_lang/testing/thread_pool/thread_pool.d (+81/-0)
D_lang/testing/thread_pool/thread_pool.mm (+47/-0)
To merge this branch: bzr merge lp:~fpstovall/nrtb/D_tech_demos
Reviewer Review Type Date Requested Status
Rick Stovall Approve
Review via email: mp+149745@code.launchpad.net

Description of the change

This branch includes the tech demos we agreed were needed before proceeding with the main alpha thrust in D. All are complete and functional now.

To post a comment you must log in.
Revision history for this message
Rick Stovall (fpstovall) wrote :

Given the non-mainline nature of this merge (proof of principle code, vs. "working" code), I intend to merge this to the alpha stream Friday night or Saturday morning unless I receive commentary indicating I should not.

Revision history for this message
Rick Stovall (fpstovall) wrote :

As noted above, and with no bug and no exceptions noted at this time, I am approving this release because of its lack of mainline code and because the merge is needed to facilitate progress on the Alpha phase.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'D_lang/testing/candidate_libs'
=== added file 'D_lang/testing/candidate_libs/splat.d'
--- D_lang/testing/candidate_libs/splat.d 1970-01-01 00:00:00 +0000
+++ D_lang/testing/candidate_libs/splat.d 2013-02-21 03:06:20 +0000
@@ -0,0 +1,1754 @@
1/*
2 Copyright (C) 2006-2007 Christopher E. Miller
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19*/
20
21/** $(B ) Splat: the socket platform with the lame name. It's full of puns, but it runs!
22 <a href="http://www.dprogramming.com/splat.php">Download Splat</a>.
23 Version 0.7.
24 For both Phobos and Tango; tested with Phobos and Tango 0.99.2.
25**/
26module splat;
27
28
29private
30{
31 version(Windows)
32 {
33 version(Tango)
34 {
35 import tango.sys.win32.UserGdi;
36 }
37 else
38 {
39 import std.c.windows.windows;
40 }
41 }
42
43
44 version(Tango)
45 {
46 import tango.core.Type;
47
48 alias tango.core.Type.Time spdTime;
49 alias tango.core.Type.Time.TicksPerSecond spdTICKS_PER_SECOND;
50
51
52 import tango.util.time.Clock;
53
54 alias Clock.now spdGetCurrentUtcTime;
55
56
57 import tango.net.Socket;
58
59 alias tango.net.Socket.NetHost spdInternetHost;
60
61 alias tango.net.Socket.IPv4Address spdInternetAddress;
62
63 alias tango.net.Socket.timeval spdTimeval;
64
65 struct spdMyTimeval
66 {
67 int seconds;
68 int microseconds;
69 }
70
71
72 import tango.core.Thread;
73 }
74 else
75 {
76 import std.date;
77
78 alias std.date.d_time spdTime;
79 alias std.date.TicksPerSecond spdTICKS_PER_SECOND;
80 alias std.date.getUTCtime spdGetCurrentUtcTime;
81
82
83 import std.socket;
84
85 alias std.socket.InternetHost spdInternetHost;
86
87 alias std.socket.InternetAddress spdInternetAddress;
88
89 alias std.socket.timeval spdMyTimeval;
90
91 alias std.socket.timeval spdTimeval;
92
93
94 import std.thread;
95 }
96
97
98 debug(splat)
99 {
100 version(Tango)
101 import tango.stdc.stdio;
102 else
103 import std.c.stdio;
104 }
105}
106
107static assert(spdMyTimeval.sizeof == spdTimeval.sizeof);
108
109
110/**
111 Run the event loop; wait for timer and socket events.
112 Exceptions that occur in event callbacks break out of run.
113**/
114// It is NOT safe to call run() before a previous call to run() returns.
115void run()
116{
117 /+
118 static bool _running = false;
119 if(_running)
120 return; // ?
121 _running = true;
122 scope(exit)
123 _running = false;
124 +/
125
126 _texit = false;
127
128 Timer tn;
129 spdMyTimeval* ptv;
130 spdMyTimeval tv;
131 spdTime dnow;
132 SocketSet reads = new SocketSet();
133 SocketSet writes = new SocketSet();
134 int i;
135 bool dotimer = false;
136
137 for(;;)
138 {
139 tn = _tnext();
140
141 version(Windows)
142 {
143 if(!_tallEvents.length)
144 {
145 no_socket_events:
146 DWORD ms = INFINITE;
147 if(tn)
148 {
149 dnow = spdGetCurrentUtcTime();
150 if(tn._talarm <= dnow)
151 goto timedout;
152 ms = _tticksToMs(cast(spdTime)(tn._talarm - dnow));
153 }
154
155 if(INFINITE == ms)
156 {
157 if(_areHosts())
158 ms = 200;
159 }
160
161 debug(splat)
162 {
163 if(INFINITE != ms)
164 printf(" {SLEEP} %lu ms\n", cast(uint)ms);
165 //else
166 // printf(" {SLEEP} infinite\n");
167 }
168
169 Sleep(ms);
170 goto timedout;
171 }
172 }
173
174 ptv = null;
175 if(tn)
176 {
177 debug(splattimer)
178 printf("splattimer: diff = %d; dotimer = %s\n",
179 cast(int)(dnow - tn._talarm),
180 dotimer ? "true".ptr : "false".ptr);
181
182 if(tn._talarm <= dnow)
183 {
184 version(Windows)
185 {
186 assert(_tallEvents.length);
187 }
188 else
189 {
190 if(!_tallEvents.length)
191 goto timedout;
192 }
193 if(dotimer)
194 goto timedout;
195 dotimer = true; // Do timer next time around.
196 tv.seconds = 0;
197 tv.microseconds = 0;
198 }
199 else
200 {
201 dnow = spdGetCurrentUtcTime();
202 _tticksToTimeval(tn._talarm - dnow, &tv);
203 if(tv.microseconds < 0)
204 tv.microseconds = 0;
205 //if(tv.microseconds > 32767)
206 // tv.microseconds = 32767;
207 if(tv.seconds < 0)
208 tv.seconds = 0;
209 if(tv.seconds > 60)
210 tv.seconds = 60;
211
212 if(_areHosts())
213 {
214 if(tv.seconds || tv.microseconds > 200_000)
215 {
216 tv.seconds = 0;
217 tv.microseconds = 200_000;
218 }
219 }
220 }
221 ptv = &tv;
222 }
223 else
224 {
225 debug(splattimer)
226 printf("splattimer: no timers\n");
227
228 if(_areHosts())
229 {
230 tv.seconds = 0;
231 tv.microseconds = 200_000;
232 ptv = &tv;
233 }
234 }
235
236 reads.reset();
237 writes.reset();
238
239 uint numadds = 0;
240 foreach(AsyncSocket sock; _tallEvents)
241 {
242 //debug
243 debug(splat)
244 {
245 if(!sock.isAlive())
246 {
247 debug(splat)
248 {
249 printf("Splat warning: dead socket still waiting for events\n");
250 fflush(stdout);
251 }
252 //continue;
253 }
254 }
255
256 if(((sock._events & EventType.READ) && !(sock._events & EventType._CANNOT_READ))
257 || ((sock._events & EventType.ACCEPT) && !(sock._events & EventType._CANNOT_ACCEPT))
258 || ((sock._events & EventType.CLOSE) && !(sock._events & EventType._CANNOT_CLOSE)))
259 {
260 reads.add(sock);
261 numadds++;
262 }
263
264 if(((sock._events & EventType.WRITE) && !(sock._events & EventType._CANNOT_WRITE))
265 || ((sock._events & EventType.CONNECT) && !(sock._events & EventType._CANNOT_CONNECT)))
266 {
267 writes.add(sock);
268 numadds++;
269 }
270 }
271
272 if(_texit)
273 return;
274
275 version(Windows)
276 {
277 if(!numadds)
278 goto no_socket_events;
279
280 //assert(reads.count || writes.count);
281 }
282
283 debug(splat)
284 {
285 if(ptv)
286 {
287 if(0 != ptv.seconds || 0 != ptv.microseconds)
288 printf(" {SELECT} %lu secs, %lu microsecs\n", cast(uint)ptv.seconds, cast(uint)ptv.microseconds);
289 //else
290 // printf(" {SELECT} 0\n");
291 }
292 //else
293 //{
294 // printf(" {SELECT} infinite\n");
295 //}
296 }
297
298 debug(splatselect)
299 printf("Socket.select(%u sockets%s)\n", numadds,
300 ptv ? (((0 != ptv.seconds || 0 != ptv.microseconds)) ? ", timeout".ptr : ", 0 timeout") : ", infinite-wait".ptr);
301 i = Socket.select(reads, writes, null, cast(spdTimeval*)ptv);
302 switch(i)
303 {
304 case -1: // Interruption.
305 continue; // ?
306
307 case 0: // Timeout.
308 goto timedout;
309
310 default: // Socket event(s).
311 foreach(AsyncSocket sock; _tallEvents)
312 {
313 if(_texit)
314 return;
315
316 //if(!sock.isAlive())
317 // continue;
318
319 if(reads.isSet(sock))
320 {
321 if((sock._events & EventType.READ) && !(sock._events & EventType._CANNOT_READ))
322 {
323 switch(sock._peekreceiveclose())
324 {
325 case 0: // Close.
326 if((sock._events & EventType.CLOSE) && !(sock._events & EventType._CANNOT_CLOSE))
327 {
328 goto got_close;
329 }
330 else
331 {
332 //sock._events |= EventType._CANNOT_READ;
333 sock._events |= EventType._CANNOT_CLOSE | EventType._CANNOT_READ; // ?
334 //sock._tgotEvent(EventType.READ, 0); // Should this be an error?
335 }
336 break;
337 case -1: // Error.
338 if((sock._events & EventType.CLOSE) && !(sock._events & EventType._CANNOT_CLOSE))
339 {
340 //sock._events |= EventType._CANNOT_READ;
341 sock._events |= EventType._CANNOT_CLOSE | EventType._CANNOT_READ; // ?
342 sock._tgotEvent(EventType.CLOSE, -1); // ?
343 }
344 else
345 {
346 //sock._events |= EventType._CANNOT_READ;
347 sock._events |= EventType._CANNOT_CLOSE | EventType._CANNOT_READ; // ?
348 sock._tgotEvent(EventType.READ, -1);
349 }
350 break;
351 default: // Good.
352 sock._events |= EventType._CANNOT_READ;
353 sock._tgotEvent(EventType.READ, 0);
354 }
355 }
356 else if((sock._events & EventType.CLOSE) && !(sock._events & EventType._CANNOT_CLOSE))
357 {
358 switch(sock._peekreceiveclose())
359 {
360 case 0: // Close.
361 got_close:
362 //sock._events |= EventType._CANNOT_CLOSE;
363 sock._events |= EventType._CANNOT_CLOSE | EventType._CANNOT_READ; // ?
364 //writes.remove(sock); // ?
365 sock._tgotEvent(EventType.CLOSE, 0);
366 break;
367 case -1: // Error.
368 //sock._events |= EventType._CANNOT_CLOSE;
369 sock._events |= EventType._CANNOT_CLOSE | EventType._CANNOT_READ; // ?
370 //writes.remove(sock); // ?
371 sock._tgotEvent(EventType.CLOSE, -1);
372 break;
373 default: ;
374 }
375 }
376
377 if((sock._events & EventType.ACCEPT) && !(sock._events & EventType._CANNOT_ACCEPT))
378 {
379 sock._events |= EventType._CANNOT_ACCEPT;
380 sock._tgotEvent(EventType.ACCEPT, 0);
381 }
382
383 continue; // Checking for writability (otherwise next) on a closed socket (from any above event) is problematic.
384 }
385
386 //if(_texit)
387 // return;
388
389 if(writes.isSet(sock))
390 {
391 if((sock._events & EventType.CONNECT) && !(sock._events & EventType._CANNOT_CONNECT))
392 {
393 sock._events |= EventType._CANNOT_CONNECT;
394 sock._tgotEvent(EventType.CONNECT, 0);
395 }
396
397 if((sock._events & EventType.WRITE) && !(sock._events & EventType._CANNOT_WRITE))
398 {
399 sock._events |= EventType._CANNOT_WRITE;
400 sock._tgotEvent(EventType.WRITE, 0);
401 }
402 }
403 }
404 //continue;
405 goto do_hosts;
406 }
407
408 // Check timers..
409 timedout: ;
410 dotimer = false;
411 _tdotimers();
412
413 // Check resolved hosts..
414 do_hosts:
415 GetHost gh;
416 while(null !is (gh = _tnextDoneHost()))
417 {
418 gh._tgotEvent();
419
420 if(_texit)
421 return;
422 }
423
424 if(_texit)
425 return;
426 }
427}
428
429
430/// Causes run() to return as soon as it can.
431void exitLoop()
432{
433 _texit = true;
434}
435
436
437private void _tdotimers()
438{
439 size_t nalarms;
440 Timer[4] talarms;
441 spdTime dnow;
442 Timer tn;
443 dnow = spdGetCurrentUtcTime();
444 for(tn = _tfirst; tn; tn = tn._tnext)
445 {
446 if(dnow >= tn._talarm)
447 {
448 if(nalarms < talarms.length)
449 talarms[nalarms] = tn;
450 nalarms++;
451 }
452 }
453 Timer[] nowalarm;
454 if(nalarms <= talarms.length)
455 {
456 nowalarm = talarms[0 .. nalarms];
457 }
458 else
459 {
460 nowalarm = new Timer[nalarms];
461 nalarms = 0;
462 for(tn = _tfirst; tn; tn = tn._tnext)
463 {
464 if(dnow >= tn._talarm)
465 {
466 nowalarm[nalarms] = tn;
467 nalarms++;
468 }
469 }
470 assert(nowalarm.length == nalarms);
471 }
472
473 foreach(Timer t; nowalarm)
474 {
475 if(_texit)
476 return;
477
478 if(t._talarm != t._TALARM_INIT) // Make sure not removed by some other timer event.
479 {
480 t._talarm = cast(spdTime)(dnow + t._ttimeout); // Also update alarm time BEFORE in case of exception (could cause rapid fire otherwise).
481 t._tgotAlarm();
482 if(t._talarm != t._TALARM_INIT) // Maybe removed itself.
483 {
484 // Set new alarm after this alarm due to possible delay AND possible updated timeout/interval.
485 dnow = spdGetCurrentUtcTime(); // In case time lapses in some other timer event.
486 t._talarm = cast(spdTime)(dnow + t._ttimeout);
487 }
488 }
489 }
490}
491
492
493/// Timers; alarms (timeout events) depend on run().
494class Timer
495{
496 /// Property: get and set the timer _interval in milliseconds.
497 final void interval(uint iv) // setter
498 {
499 iv = cast(uint)_tmsToTicks(iv);
500 if(!iv)
501 iv = 1;
502 if(iv != _ttimeout)
503 {
504 _ttimeout = iv;
505
506 if(_talarm != _TALARM_INIT)
507 {
508 stop();
509 start();
510 }
511 }
512 }
513
514 /// ditto
515 final uint interval() // getter
516 {
517 return _tticksToMs(cast(spdTime)_ttimeout);
518 }
519
520
521 /// Start this timer.
522 final void start()
523 {
524 if(_talarm)
525 return;
526
527 assert(_ttimeout > 0);
528
529 _tadd(this);
530
531 debug(splat)
532 {
533 printf(" {ADDTIMER:%p} %lu ms\n", cast(void*)this, interval);
534 }
535 }
536
537
538 /// Stop this timer.
539 final void stop()
540 {
541 if(_talarm)
542 {
543 _tremove(this);
544
545 debug(splat)
546 {
547 printf(" {DELTIMER:%p} %lu ms\n", cast(void*)this, interval);
548 }
549 }
550 }
551
552
553 /// Override to be notified when the time expires. Alarms continue until stop().
554 void onAlarm()
555 {
556 if(_tick)
557 _tick(this);
558 }
559
560
561 /// Construct a timer; can take a delegate that is called back automatically on an alarm.
562 this()
563 {
564 _ttimeout = cast(uint)_tmsToTicks(100);
565 }
566
567 /// ditto
568 this(void delegate(Timer) dg)
569 {
570 this();
571 this._tick = dg;
572 }
573
574
575 private:
576 const spdTime _TALARM_INIT = cast(spdTime)0;
577 spdTime _talarm = _TALARM_INIT; // Time when next event is alarmed.
578 //spdTime _ttimeout; // Ticks per timeout.
579 uint _ttimeout; // Ticks per timeout.
580 Timer _tprev, _tnext;
581 void delegate(Timer) _tick;
582
583
584 void _tgotAlarm()
585 {
586 debug(splat)
587 {
588 printf(" {TIMER:%p}\n", cast(void*)this);
589 }
590
591 onAlarm();
592 }
593}
594
595
596// Can be OR'ed.
597/// Socket event flags.
598enum EventType
599{
600 NONE = 0, ///
601
602 READ = 0x1, ///
603 WRITE = 0x2, /// ditto
604 //OOB = 0x4, /// ditto
605 ACCEPT = 0x8, /// ditto
606 CONNECT = 0x10, /// ditto
607 CLOSE = 0x20, /// ditto
608
609 _CANNOT_READ = READ << 16, // package
610 _CANNOT_WRITE = WRITE << 16, // package
611 //_CANNOT_OOB = OOB << 16, // package
612 _CANNOT_ACCEPT = ACCEPT << 16, // package
613 _CANNOT_CONNECT = CONNECT << 16, // package
614 _CANNOT_CLOSE = CLOSE << 16, // package
615}
616
617private EventType _tEventType_ALL = EventType.READ | EventType.WRITE /+ | EventType.OOB +/
618 | EventType.ACCEPT | EventType.CONNECT | EventType.CLOSE;
619private EventType _tEventType_ALLREADS = EventType.READ | EventType.ACCEPT | EventType.CLOSE;
620private EventType _tEventType_ALLWRITES = EventType.WRITE | EventType.CONNECT;
621
622
623/**
624 Callback type for socket events.
625 Params:
626 sock = the socket
627 type = which event; will be only one of the event flags.
628 err = an error code, or 0 if successful.
629**/
630alias void delegate(Socket sock, EventType type, int err) RegisterEventCallback;
631
632
633/// Asynchronous sockets; socket events depend on run(). Mostly the same as std.socket.Socket.
634class AsyncSocket: Socket
635{
636 version(Tango)
637 {
638 this(AddressFamily family, SocketType type, ProtocolType protocol, bool create = true)
639 {
640 super(family, type, protocol, create);
641 super.blocking = false;
642 }
643 }
644 else
645 {
646 this(AddressFamily af, SocketType type, ProtocolType protocol)
647 {
648 super(af, type, protocol);
649 super.blocking = false;
650 }
651
652
653 this(AddressFamily af, SocketType type)
654 {
655 super(af, type);
656 super.blocking = false;
657 }
658
659
660 this(AddressFamily af, SocketType type, char[] protocolName)
661 {
662 super(af, type, protocolName);
663 super.blocking = false;
664 }
665 }
666
667
668 /**
669 Registers a callback for specified socket events.
670 One or more type flags may be used, or NONE to cancel all.
671 Calling this twice on the same socket cancels out previously registered events for the socket.
672 **/
673 // Requires run() loop.
674 void event(EventType events, RegisterEventCallback callback)
675 {
676 this.blocking = false;
677
678 this._events = EventType.NONE;
679
680 if(!(events & (_tEventType_ALLREADS | _tEventType_ALLWRITES)))
681 return;
682
683 if(isAlive()) // Alive socket already connected or never will.
684 this._events |= EventType._CANNOT_CONNECT;
685
686 if(events & EventType.ACCEPT)
687 events &= ~(EventType.READ | EventType.CLOSE); // Issues in select() if accept and these set.
688
689 this._events = events | _tEventType_ALL;
690 this._callback = callback;
691
692 _tallEvents[this.handle] = this;
693 }
694
695
696 version(Tango)
697 {
698 alias fileHandle handle;
699 }
700
701
702 // For use with accepting().
703 protected this()
704 {
705 }
706
707
708 version(Tango)
709 {
710 override Socket accept()
711 {
712 return accept(new AsyncSocket());
713 }
714
715 // Overload.
716 //alias Socket.accept accept; // Don't overload since I override this one below..
717 }
718 else
719 {
720 protected override AsyncSocket accepting()
721 {
722 return new AsyncSocket();
723 }
724 }
725
726
727 version(Tango)
728 private const bool _IS_TANGO = true;
729 else
730 private const bool _IS_TANGO = false;
731
732 static if(_IS_TANGO && is(typeof(&this.detach)))
733 {
734 override void detach()
735 {
736 _events = EventType.NONE;
737 _tallEvents.remove(this.handle);
738 return super.detach();
739 }
740 }
741 else
742 {
743 override void close()
744 {
745 _events = EventType.NONE;
746 _tallEvents.remove(this.handle);
747 return super.close();
748 }
749 }
750
751
752 override bool blocking() // getter
753 {
754 return false;
755 }
756
757
758 override void blocking(bool byes) // setter
759 {
760 if(byes)
761 assert(0);
762 }
763
764
765 version(Tango)
766 {
767 override int receive(void[] buf, SocketFlags flags = SocketFlags.NONE)
768 {
769 _events &= ~EventType._CANNOT_READ;
770 return super.receive(buf, flags);
771 }
772
773 override int receiveFrom(void[] buf, SocketFlags flags, Address from)
774 {
775 _events &= ~EventType._CANNOT_READ;
776 return super.receiveFrom(buf, flags, from);
777 }
778
779 override int receiveFrom(void[] buf, Address from)
780 {
781 _events &= ~EventType._CANNOT_READ;
782 return super.receiveFrom(buf, from);
783 }
784
785 override int receiveFrom(void[] buf, SocketFlags flags = SocketFlags.NONE)
786 {
787 _events &= ~EventType._CANNOT_READ;
788 return super.receiveFrom(buf, flags);
789 }
790
791
792 override int send(void[] buf, SocketFlags flags = SocketFlags.NONE)
793 {
794 _events &= ~EventType._CANNOT_WRITE;
795 return super.send(buf, flags);
796 }
797
798 override int sendTo(void[] buf, SocketFlags flags, Address to)
799 {
800 _events &= ~EventType._CANNOT_WRITE;
801 return super.sendTo(buf, flags, to);
802 }
803
804 override int sendTo(void[] buf, Address to)
805 {
806 _events &= ~EventType._CANNOT_WRITE;
807 return super.sendTo(buf, to);
808 }
809
810 override int sendTo(void[] buf, SocketFlags flags = SocketFlags.NONE)
811 {
812 _events &= ~EventType._CANNOT_WRITE;
813 return super.sendTo(buf, flags);
814 }
815 }
816 else
817 {
818 override int receive(void[] buf, SocketFlags flags)
819 {
820 _events &= ~EventType._CANNOT_READ;
821 return super.receive(buf, flags);
822 }
823
824 override int receive(void[] buf)
825 {
826 _events &= ~EventType._CANNOT_READ;
827 return super.receive(buf);
828 }
829
830 override int receiveFrom(void[] buf, SocketFlags flags, out Address from)
831 {
832 _events &= ~EventType._CANNOT_READ;
833 return super.receiveFrom(buf, flags, from);
834 }
835
836 override int receiveFrom(void[] buf, out Address from)
837 {
838 _events &= ~EventType._CANNOT_READ;
839 return super.receiveFrom(buf, from);
840 }
841
842 override int receiveFrom(void[] buf, SocketFlags flags)
843 {
844 _events &= ~EventType._CANNOT_READ;
845 return super.receiveFrom(buf, flags);
846 }
847
848 override int receiveFrom(void[] buf)
849 {
850 _events &= ~EventType._CANNOT_READ;
851 return super.receiveFrom(buf);
852 }
853
854
855 override int send(void[] buf, SocketFlags flags)
856 {
857 _events &= ~EventType._CANNOT_WRITE;
858 return super.send(buf, flags);
859 }
860
861 override int send(void[] buf)
862 {
863 _events &= ~EventType._CANNOT_WRITE;
864 return super.send(buf);
865 }
866
867 override int sendTo(void[] buf, SocketFlags flags, Address to)
868 {
869 _events &= ~EventType._CANNOT_WRITE;
870 return super.sendTo(buf, flags, to);
871 }
872
873 override int sendTo(void[] buf, Address to)
874 {
875 _events &= ~EventType._CANNOT_WRITE;
876 return super.sendTo(buf, to);
877 }
878
879 override int sendTo(void[] buf, SocketFlags flags)
880 {
881 _events &= ~EventType._CANNOT_WRITE;
882 return super.sendTo(buf, flags);
883 }
884
885 override int sendTo(void[] buf)
886 {
887 _events &= ~EventType._CANNOT_WRITE;
888 return super.sendTo(buf);
889 }
890 }
891
892
893 version(Tango)
894 {
895 override Socket accept(Socket s)
896 {
897 _events &= ~EventType._CANNOT_ACCEPT;
898 return super.accept(s);
899 }
900 }
901 else
902 {
903 override Socket accept()
904 {
905 _events &= ~EventType._CANNOT_ACCEPT;
906 return super.accept();
907 }
908 }
909
910
911 private:
912
913 EventType _events;
914 RegisterEventCallback _callback;
915
916
917 void _cando(EventType can)
918 {
919 _events &= ~(can << 16);
920 }
921
922 void _cannotdo(EventType cannot)
923 {
924 _events |= (cannot << 16);
925 }
926
927 bool _ifcando(EventType ifcan)
928 {
929 return !(_events & (ifcan << 16));
930 }
931
932
933 int _peekreceiveclose()
934 {
935 byte[1] onebyte;
936 return Socket.receive(onebyte, SocketFlags.PEEK);
937 }
938
939
940 void _tgotEvent(EventType type, int err)
941 {
942 debug(splat)
943 {
944 if(type == EventType.READ)
945 printf(" {READ:%p}\n", cast(void*)this);
946 else if(type == EventType.WRITE)
947 printf(" {WRITE:%p}\n", cast(void*)this);
948 else if(type == EventType.CONNECT)
949 printf(" {CONNECT:%p}\n", cast(void*)this);
950 else if(type == EventType.CLOSE)
951 printf(" {CLOSE:%p}\n", cast(void*)this);
952 else if(type == EventType.ACCEPT)
953 printf(" {ACCEPT:%p}\n", cast(void*)this);
954 }
955
956 if(_callback)
957 _callback(this, type, err);
958 }
959}
960
961
962/// Asynchronous TCP socket shortcut.
963class AsyncTcpSocket: AsyncSocket
964{
965 ///
966 this(AddressFamily family)
967 {
968 super(family, SocketType.STREAM, ProtocolType.TCP);
969 }
970
971 /// ditto
972 this()
973 {
974 this(cast(AddressFamily)AddressFamily.INET);
975 }
976
977 /// ditto
978 // Shortcut.
979 this(EventType events, RegisterEventCallback eventCallback)
980 {
981 this(cast(AddressFamily)AddressFamily.INET);
982 event(events, eventCallback);
983 }
984
985 /// ditto
986 // Shortcut.
987 this(Address connectTo, EventType events, RegisterEventCallback eventCallback)
988 {
989 this(connectTo.addressFamily());
990 event(events, eventCallback);
991 connect(connectTo);
992 }
993}
994
995
996/// Asynchronous UDP socket shortcut.
997class AsyncUdpSocket: AsyncSocket
998{
999 ///
1000 this(AddressFamily family)
1001 {
1002 super(family, SocketType.DGRAM, ProtocolType.UDP);
1003 }
1004
1005 /// ditto
1006 this()
1007 {
1008 this(cast(AddressFamily)AddressFamily.INET);
1009 }
1010
1011 /// ditto
1012 // Shortcut.
1013 this(EventType events, RegisterEventCallback eventCallback)
1014 {
1015 this(cast(AddressFamily)AddressFamily.INET);
1016 event(events, eventCallback);
1017 }
1018}
1019
1020
1021private void _tgetHostErr()
1022{
1023 throw new Exception("Get host failure");
1024}
1025
1026
1027/**
1028 Callback type for host resolve event.
1029 Params:
1030 inetHost = the InternetHost/NetHost of the resolved host, or null.
1031 err = an error code, or 0 if successful; if 0, inetHost will be null.
1032**/
1033alias void delegate(spdInternetHost inetHost, int err) GetHostCallback;
1034
1035
1036/// Returned from asyncGetHost functions.
1037class GetHost
1038{
1039 /// Cancel the get-host operation.
1040 void cancel()
1041 {
1042 _tcallback = null;
1043 }
1044
1045
1046 private:
1047 GetHostCallback _tcallback;
1048 GetHost _tnext;
1049 spdInternetHost _tinetHost;
1050
1051 bool _tbyname; // false == by addr
1052 union
1053 {
1054 uint _taddr;
1055 char[] _tname;
1056 }
1057
1058
1059 void _tgotEvent()
1060 {
1061 if(!_tcallback) // If cancel().
1062 return;
1063
1064 if(!_tinetHost)
1065 {
1066 _tcallback(null, -1); // ?
1067 return;
1068 }
1069
1070 _tcallback(_tinetHost, 0);
1071 }
1072
1073
1074 this()
1075 {
1076 }
1077}
1078
1079
1080/// Asynchronously resolve host information from a hostname; the callback depends on run().
1081GetHost asyncGetHostByName(char[] name, GetHostCallback callback)
1082{
1083 GetHost gh;
1084 gh = new GetHost;
1085 version(NO_THREADS)
1086 {
1087 spdInternetHost ih;
1088 ih = new spdInternetHost;
1089 if(ih.getHostByName(name))
1090 {
1091 gh.inetHost = ih;
1092 }
1093 }
1094 else
1095 {
1096 gh._tcallback = callback;
1097 gh._tbyname = true;
1098 gh._tname = name;
1099 _tgethost(gh);
1100 }
1101 return gh;
1102}
1103
1104
1105/// Asynchronously resolve host information from an IPv4 address; the callback depends on run().
1106GetHost asyncGetHostByAddr(uint addr, GetHostCallback callback)
1107{
1108 GetHost gh;
1109 gh = new GetHost;
1110 version(NO_THREADS)
1111 {
1112 spdInternetHost ih;
1113 ih = new spdInternetHost;
1114 if(ih.getHostByAddr(addr))
1115 {
1116 gh.inetHost = ih;
1117 }
1118 }
1119 else
1120 {
1121 gh._tcallback = callback;
1122 gh._tbyname = false;
1123 gh._taddr = addr;
1124 _tgethost(gh);
1125 }
1126 return gh;
1127}
1128
1129/// ditto
1130GetHost asyncGetHostByAddr(char[] addr, GetHostCallback callback)
1131{
1132 uint uiaddr;
1133 uiaddr = spdInternetAddress.parse(addr);
1134 if(spdInternetAddress.ADDR_NONE == uiaddr)
1135 _tgetHostErr();
1136 return asyncGetHostByAddr(uiaddr, callback);
1137}
1138
1139
1140version = THSLEEP;
1141
1142
1143version(THSLEEP)
1144{
1145 version(Windows)
1146 {
1147 private void _tthsleep()
1148 {
1149 Sleep(200); // 0.2 secs.
1150 }
1151 }
1152 else
1153 {
1154 private extern(C) int usleep(uint microseconds);
1155
1156 private void _tthsleep()
1157 {
1158 usleep(200_000); // 0.2 secs.
1159 }
1160 }
1161}
1162
1163
1164private void _tgethost(GetHost gh)
1165{
1166 debug(splat)
1167 {
1168 printf(" {GETHOST:%p}\n", cast(void*)gh);
1169 }
1170
1171 //synchronized
1172 {
1173 gh._tnext = null;
1174
1175 if(!_ththread)
1176 {
1177 //printf("GETHOST:newthread\n");
1178 version(Tango)
1179 _ththread = new Thread(&_ththreadproc);
1180 else
1181 _ththread = new Thread(&_ththreadproc, null);
1182 _thnext = _thaddto = gh;
1183 _ththread.start();
1184 return;
1185 }
1186
1187 synchronized(_ththread)
1188 {
1189 if(!_thaddto)
1190 {
1191 //printf("GETHOST:!_thaddto\n");
1192 version(SPLAT_HACK_PRINTF)
1193 printf(""); // Without this, the thread never sees this host.
1194 _thnext = _thaddto = gh;
1195
1196 version(THSLEEP)
1197 {
1198 }
1199 else
1200 {
1201 debug(splat)
1202 {
1203 printf(" {RESUMING:_ththreadproc}\n");
1204 }
1205
1206 _ththread.resume();
1207 }
1208 }
1209 else
1210 {
1211 //printf("GETHOST:_thaddto\n");
1212 _thaddto._tnext = gh;
1213 _thaddto = gh;
1214 }
1215 }
1216 }
1217}
1218
1219
1220private void _dothreadproc()
1221{
1222 GetHost gh;
1223 spdInternetHost ih;
1224 for(;;)
1225 {
1226 //synchronized(_ththread)
1227 volatile
1228 {
1229 gh = _thnext;
1230 }
1231
1232 if(!gh)
1233 {
1234 version(THSLEEP)
1235 {
1236 _tthsleep();
1237 }
1238 else
1239 {
1240 debug(splat)
1241 {
1242 printf(" {PAUSE:_ththreadproc}\n");
1243 }
1244
1245 _ththread.pause();
1246
1247 debug(splat)
1248 {
1249 printf(" {RESUMED:_ththreadproc}\n");
1250 }
1251 }
1252 continue;
1253 }
1254
1255 if(gh._tcallback) // If not cancel()..
1256 {
1257 try
1258 {
1259 ih = new spdInternetHost;
1260 if(gh._tbyname)
1261 {
1262 if(ih.getHostByName(gh._tname))
1263 gh._tinetHost = ih;
1264 }
1265 else // byaddr
1266 {
1267 if(ih.getHostByAddr(gh._taddr))
1268 gh._tinetHost = ih;
1269 }
1270
1271 debug(splat)
1272 {
1273 printf(" {GOTHOST:%p} %s\n", cast(void*)gh, gh._tinetHost ? "true".ptr : "false".ptr);
1274 }
1275 }
1276 catch
1277 {
1278 }
1279 }
1280
1281 _thpn(gh);
1282 }
1283}
1284
1285
1286version(Tango)
1287{
1288 /+
1289 private _ththreadproc()
1290 {
1291 _dothreadproc();
1292 }
1293 +/
1294 alias _dothreadproc _ththreadproc;
1295}
1296else
1297{
1298 private int _ththreadproc(void* foo)
1299 {
1300 _dothreadproc();
1301 return 0;
1302 }
1303}
1304
1305
1306// GDC 0.19 segfaults if this isn't in a function; might have to do with synchronized() in a loop.
1307private void _thpn(GetHost gh)
1308{
1309 synchronized(_ththread)
1310 {
1311 assert(gh is _thnext);
1312
1313 debug(splat)
1314 {
1315 printf(" {DONEHOST:%p}\n", cast(void*)gh);
1316 }
1317
1318 _thnext = _thnext._tnext;
1319 if(!_thnext)
1320 _thaddto = null;
1321
1322 gh._tnext = null;
1323 if(_thfinlast)
1324 _thfinlast._tnext = gh;
1325 else
1326 _thfinnext = gh;
1327 _thfinlast = gh;
1328 }
1329}
1330
1331
1332private GetHost _tnextDoneHost()
1333{
1334 GetHost gh;
1335
1336 volatile gh = _thfinnext;
1337 if(!gh)
1338 return null;
1339
1340 synchronized(_ththread)
1341 {
1342 gh = _thfinnext;
1343 if(gh)
1344 {
1345 _thfinnext = _thfinnext._tnext;
1346 if(!_thfinnext)
1347 _thfinlast = null;
1348 gh._tnext = null;
1349 }
1350 }
1351
1352 return gh;
1353}
1354
1355
1356private bool _areHosts()
1357{
1358 return _thnext || _thfinnext;
1359}
1360
1361
1362/// Buffering socket I/O.
1363class SocketQueue
1364{
1365 ///
1366 this(Socket sock)
1367 in
1368 {
1369 assert(sock !is null);
1370 }
1371 body
1372 {
1373 this.sock = sock;
1374 }
1375
1376
1377 /// Property: get the socket of this queue.
1378 final Socket socket() // getter
1379 {
1380 return sock;
1381 }
1382
1383
1384 /// Resets the buffers.
1385 void reset()
1386 {
1387 writebuf = null;
1388 readbuf = null;
1389 }
1390
1391
1392 /+
1393 // DMD 0.92 says error: function toString overrides but is not covariant with toString
1394 override char[] toString()
1395 {
1396 return cast(char[])peek();
1397 }
1398 +/
1399
1400
1401 /// Peek at some or all of the received data but leave it in the queue. May return less than requested.
1402 void[] peek()
1403 {
1404 return readbuf[0 .. rpos];
1405 }
1406
1407 /// ditto
1408 void[] peek(uint len)
1409 {
1410 if(len >= rpos)
1411 return peek();
1412
1413 return readbuf[0 .. len];
1414 }
1415
1416
1417 /// Returns: some or all of the received data and removes this amount from the queue. May return less than requested.
1418 void[] receive()
1419 {
1420 ubyte[] result;
1421
1422 result = readbuf[0 .. rpos];
1423 readbuf = null;
1424 rpos = 0;
1425
1426 return result;
1427 }
1428
1429 /// ditto
1430 void[] receive(uint len)
1431 {
1432 if(len >= rpos)
1433 return receive();
1434
1435 ubyte[] result;
1436
1437 result = readbuf[0 .. len];
1438 readbuf = readbuf[len .. readbuf.length];
1439 rpos -= len;
1440
1441 return result;
1442 }
1443
1444
1445 /// Add data to the queue and send it over this socket.
1446 void send(void[] buf)
1447 {
1448 if(canwrite)
1449 {
1450 assert(!writebuf.length);
1451
1452 int st;
1453 if(buf.length > 4096)
1454 st = 4096;
1455 else
1456 st = buf.length;
1457
1458 st = sock.send(buf[0 .. st]);
1459 if(st > 0)
1460 {
1461 if(buf.length - st)
1462 {
1463 // dup so it can be appended to.
1464 writebuf = (cast(ubyte[])buf)[st .. buf.length].dup;
1465 }
1466 }
1467 else
1468 {
1469 // dup so it can be appended to.
1470 writebuf = (cast(ubyte[])buf).dup;
1471 }
1472
1473 //canwrite = false;
1474 }
1475 else
1476 {
1477 writebuf ~= cast(ubyte[])buf;
1478 }
1479 }
1480
1481
1482 /// Property: get the number of bytes in send buffer.
1483 uint sendBytes()
1484 {
1485 return writebuf.length;
1486 }
1487
1488
1489 /// Property: get the number of bytes in recv buffer.
1490 uint receiveBytes()
1491 {
1492 return rpos;
1493 }
1494
1495
1496 /// Call on a read event so that incoming data may be buffered.
1497 void readEvent()
1498 {
1499 if(readbuf.length - rpos < 1024)
1500 readbuf.length = readbuf.length + 2048;
1501
1502 int rd = sock.receive(readbuf[rpos .. readbuf.length]);
1503 if(rd > 0)
1504 rpos += cast(uint)rd;
1505 }
1506
1507
1508 /// Call on a write event so that buffered outgoing data may be sent.
1509 void writeEvent()
1510 {
1511 if(writebuf.length)
1512 {
1513 ubyte[] buf;
1514
1515 if(writebuf.length > 4096)
1516 buf = writebuf[0 .. 4096];
1517 else
1518 buf = writebuf;
1519
1520 int st = sock.send(buf);
1521 if(st > 0)
1522 writebuf = writebuf[st .. writebuf.length];
1523 }
1524 else
1525 {
1526 //canwrite = true;
1527 }
1528 }
1529
1530
1531 /**
1532 Shortcut function for AsyncSocket.
1533 Automatically calls readEvent and writeEvent as needed.
1534 Same signature as RegisterEventCallback for simplicity.
1535 **/
1536 void event(Socket _sock, EventType type, int err)
1537 in
1538 {
1539 assert(_sock is sock);
1540 }
1541 body
1542 {
1543 switch(type)
1544 {
1545 case EventType.READ:
1546 readEvent();
1547 break;
1548
1549 case EventType.WRITE:
1550 writeEvent();
1551 break;
1552
1553 default: ;
1554 }
1555 }
1556
1557
1558 deprecated
1559 {
1560 alias receiveBytes recvBytes;
1561 alias receive recv;
1562 }
1563
1564
1565 private:
1566 ubyte[] writebuf;
1567 ubyte[] readbuf;
1568 uint rpos;
1569 Socket sock;
1570 //bool canwrite = false;
1571
1572
1573 bool canwrite() // getter
1574 {
1575 return writebuf.length == 0;
1576 }
1577}
1578
1579
1580/// Returns the number of asynchronous sockets waiting for events.
1581size_t getNumberOfAsyncSockets()
1582{
1583 return _tallEvents.length;
1584}
1585
1586
1587/// Returns the number of active timers.
1588size_t getNumberOfTimers()
1589{
1590 return _tcount;
1591}
1592
1593
1594private:
1595
1596Timer _tfirst, _tlast;
1597size_t _tcount = 0;
1598
1599
1600Timer _tnext()
1601{
1602 //spdTime lowest = spdTime.max; // Wrong in Tango 0.99.2.
1603 spdTime lowest = cast(spdTime)((spdTime.init + 0).max); // + 1 converts to the underlying arithmetic type to get the real max.
1604 Timer t, tlowest;
1605 for(t = _tfirst; t; t = t._tnext)
1606 {
1607 if(t._talarm < lowest)
1608 {
1609 tlowest = t;
1610 lowest = t._talarm;
1611 }
1612 }
1613 return tlowest;
1614}
1615
1616
1617void _tadd(Timer t)
1618in
1619{
1620 assert(t !is null);
1621 assert(t._ttimeout);
1622 assert(t._tprev is null);
1623 assert(t._tnext is null);
1624 assert(t._talarm == t._TALARM_INIT);
1625}
1626body
1627{
1628 t._talarm = cast(spdTime)(spdGetCurrentUtcTime() + t._ttimeout);
1629
1630 t._tprev = _tlast;
1631 _tlast = t;
1632 if(!_tfirst)
1633 _tfirst = t;
1634 else
1635 t._tprev._tnext = t;
1636
1637 _tcount++;
1638}
1639
1640
1641void _tremove(Timer t)
1642in
1643{
1644 assert(t !is null);
1645 assert(t._talarm != t._TALARM_INIT);
1646}
1647body
1648{
1649 t._talarm = t._TALARM_INIT;
1650
1651 if(t._tprev)
1652 t._tprev._tnext = t._tnext;
1653 else
1654 _tfirst = t._tnext;
1655
1656 if(t._tnext)
1657 t._tnext._tprev = t._tprev;
1658 else
1659 _tlast = t._tprev;
1660
1661 t._tprev = null;
1662 t._tnext = null;
1663
1664 if(_tcount)
1665 _tcount--;
1666}
1667
1668
1669template _tTicks()
1670{
1671 static if(spdTICKS_PER_SECOND == 1_000)
1672 {
1673 uint _tticksToSecs(spdTime ticks) { return cast(uint)(ticks / spdTICKS_PER_SECOND); }
1674 uint _tticksToMs(spdTime ticks) { return cast(uint)ticks; }
1675 //uint _tticksToNs(spdTime ticks) { return cast(uint)(ticks / spdTICKS_PER_SECOND * 1_000_000_000); }
1676 //uint _tticksToNs(spdTime ticks) { return cast(uint)(cast(double)ticks / cast(double)spdTICKS_PER_SECOND * cast(double)1_000_000_000); }
1677 //uint _tticksToMicrosecs(spdTime ticks) { return cast(uint)(ticks / spdTICKS_PER_SECOND * 1_000_000); }
1678 uint _tticksToMicrosecs(spdTime ticks) { return cast(uint)(cast(double)ticks / cast(double)spdTICKS_PER_SECOND * cast(double)1_000_000); }
1679 spdTime _tsecsToTicks(uint secs) { return cast(spdTime)(secs * spdTICKS_PER_SECOND); }
1680 spdTime _tmsToTicks(uint ms) { return cast(spdTime)ms; }
1681 }
1682 else
1683 {
1684 uint _tticksToSecs(spdTime ticks) { return cast(uint)(cast(double)ticks / cast(double)spdTICKS_PER_SECOND); }
1685 uint _tticksToMs(spdTime ticks) { return cast(uint)(cast(double)ticks / cast(double)spdTICKS_PER_SECOND * cast(double)1_000); }
1686 //uint _tticksToNs(spdTime ticks) { return cast(uint)(cast(double)ticks / cast(double)spdTICKS_PER_SECOND * cast(double)1_000_000_000); }
1687 uint _tticksToMicrosecs(spdTime ticks) { return cast(uint)(cast(double)ticks / cast(double)spdTICKS_PER_SECOND * cast(double)1_000_000); }
1688 spdTime _tsecsToTicks(uint secs) { return cast(spdTime)(cast(double)secs * cast(double)spdTICKS_PER_SECOND); }
1689 spdTime _tmsToTicks(uint ms) { return cast(spdTime)(cast(double)spdTICKS_PER_SECOND / cast(double)1_000 * cast(double)ms); }
1690 }
1691}
1692
1693alias _tTicks!()._tticksToSecs _tticksToSecs;
1694alias _tTicks!()._tticksToMs _tticksToMs;
1695//alias _tTicks!()._tticksToNs _tticksToNs;
1696alias _tTicks!()._tticksToMicrosecs _tticksToMicrosecs;
1697alias _tTicks!()._tsecsToTicks _tsecsToTicks;
1698alias _tTicks!()._tmsToTicks _tmsToTicks;
1699
1700
1701unittest
1702{
1703 assert(_tsecsToTicks(_tticksToSecs(543253)) == _tsecsToTicks(_tticksToSecs(543253)));
1704 assert(_tmsToTicks(_tticksToMs(3445723)) == _tmsToTicks(_tticksToMs(3445723)));
1705}
1706
1707
1708void _tticksToTimeval(spdTime ticks, spdMyTimeval* tv)
1709{
1710 tv.seconds = _tticksToSecs(ticks);
1711 ticks -= _tsecsToTicks(tv.seconds);
1712 tv.microseconds = _tticksToMicrosecs(ticks);
1713}
1714
1715
1716//_tEventInfo[socket_t] _tallEvents;
1717AsyncSocket[socket_t] _tallEvents;
1718
1719Thread _ththread;
1720GetHost _thnext, _thaddto;
1721GetHost _thfinnext, _thfinlast;
1722
1723bool _texit = false;
1724
1725
1726/+
1727// Test.
1728void main()
1729{
1730 new class Timer { this() { interval = 1000; start(); } override void onAlarm() { printf(" * ALARM * \n"); } };
1731 new class Timer { this() { interval = 5000; start(); } override void onAlarm() { printf(" &die 5 spawn 2 & \n"); stop();
1732 new class Timer { this() { interval = 2000; start(); } override void onAlarm() { printf(" x spawn x \n"); } };
1733 } };
1734 new class Timer { this() { interval = 3000; start(); } override void onAlarm() { printf(" &die 3& \n"); stop(); } };
1735 new class Timer { this() { interval = 2500; start(); } override void onAlarm()
1736 {
1737 stop();
1738 asyncGetHostByName("www.google.com", (spdInternetHost ih, int err) { if(!err) { printf(" gGot host %.*s\n", ih.name); } });
1739 }
1740 };
1741 new class Timer { this() { interval = 500; start(); } override void onAlarm()
1742 {
1743 printf(" (slower and slower %lu \n", interval);
1744 interval = interval + 500;
1745 }
1746 };
1747
1748 asyncGetHostByName("www.yahoo.com", (spdInternetHost ih, int err) { if(!err) { printf(" yGot host %.*s\n", ih.name); } });
1749 asyncGetHostByName("www.ask.com", (spdInternetHost ih, int err) { if(!err) { printf(" aGot host %.*s\n", ih.name); } });
1750
1751 run();
1752}
1753+/
1754
01755
=== added file 'D_lang/testing/candidate_libs/splat.html'
--- D_lang/testing/candidate_libs/splat.html 1970-01-01 00:00:00 +0000
+++ D_lang/testing/candidate_libs/splat.html 2013-02-21 03:06:20 +0000
@@ -0,0 +1,269 @@
1<html><head>
2 <META http-equiv="content-type" content="text/html; charset=utf-8">
3 <title>splat</title>
4 </head><body>
5 <h1>splat</h1>
6 <!-- Generated by Ddoc from splat.d -->
7<b></b> Splat: the socket platform with the lame name. It's full of puns, but it runs!
8 <a href="http://www.dprogramming.com/splat.php">Download Splat</a>.
9 Version 0.7.
10 For both Phobos and Tango; tested with Phobos and Tango 0.99.2.
11<br><br>
12
13<dl><dt><big>void <u>run</u>();
14</big></dt>
15<dd>Run the event loop; wait for timer and socket events.
16 Exceptions that occur in event callbacks break out of <u>run</u>.
17<br><br>
18
19</dd>
20<dt><big>void <u>exitLoop</u>();
21</big></dt>
22<dd>Causes run() to return as soon as it can.
23<br><br>
24
25</dd>
26<dt><big>class <u>Timer</u>;
27</big></dt>
28<dd>Timers; alarms (timeout events) depend on run().
29<br><br>
30
31<dl><dt><big>final void <u>interval</u>(uint <i>iv</i>);
32<br>final uint <u>interval</u>();
33</big></dt>
34<dd><b>Property:</b><br>
35get and set the timer interval in milliseconds.
36<br><br>
37
38</dd>
39<dt><big>final void <u>start</u>();
40</big></dt>
41<dd>Start this timer.
42<br><br>
43
44</dd>
45<dt><big>final void <u>stop</u>();
46</big></dt>
47<dd>Stop this timer.
48<br><br>
49
50</dd>
51<dt><big>void <u>onAlarm</u>();
52</big></dt>
53<dd>Override to be notified when the time expires. Alarms continue until stop().
54<br><br>
55
56</dd>
57<dt><big>this();
58<br>this(void delegate(Timer) <i>dg</i>);
59</big></dt>
60<dd>Construct a timer; can take a delegate that is called back automatically on an alarm.
61<br><br>
62
63</dd>
64</dl>
65</dd>
66<dt><big>enum <u>EventType</u>;
67</big></dt>
68<dd>Socket event flags.
69<br><br>
70
71<dl><dt><big><u>NONE</u></big></dt>
72<dd><br><br>
73</dd>
74<dt><big><u>READ</u><br><u>WRITE</u><br><u>ACCEPT</u><br><u>CONNECT</u><br><u>CLOSE</u></big></dt>
75<dd><br><br>
76</dd>
77</dl>
78</dd>
79<dt><big>alias <u>RegisterEventCallback</u>;
80</big></dt>
81<dd>Callback type for socket events.
82<br><br>
83<b>Params:</b><br>
84<table><tr><td>sock</td>
85<td>the socket</td></tr>
86<tr><td>type</td>
87<td>which event; will be only one of the event flags.</td></tr>
88<tr><td>err</td>
89<td>an error code, or 0 if successful.</td></tr>
90</table><br>
91
92</dd>
93<dt><big>class <u>AsyncSocket</u>: std.socket.Socket;
94</big></dt>
95<dd>Asynchronous sockets; socket events depend on run(). Mostly the same as std.socket.Socket.
96<br><br>
97
98<dl><dt><big>void <u>event</u>(EventType <i>events</i>, void delegate(Socket sock, EventType type, int err) <i>callback</i>);
99</big></dt>
100<dd>Registers a <i>callback</i> for specified socket <i>events</i>.
101 One or more type flags may be used, or NONE to cancel all.
102 Calling this twice on the same socket cancels out previously registered <i>events</i> for the socket.
103
104<br><br>
105
106</dd>
107</dl>
108</dd>
109<dt><big>class <u>AsyncTcpSocket</u>: splat.AsyncSocket;
110</big></dt>
111<dd>Asynchronous TCP socket shortcut.
112<br><br>
113
114<dl><dt><big>this(AddressFamily <i>family</i>);
115<br>this();
116<br>this(EventType <i>events</i>, void delegate(Socket sock, EventType type, int err) <i>eventCallback</i>);
117<br>this(Address <i>connectTo</i>, EventType <i>events</i>, void delegate(Socket sock, EventType type, int err) <i>eventCallback</i>);
118</big></dt>
119<dd><br><br>
120</dd>
121</dl>
122</dd>
123<dt><big>class <u>AsyncUdpSocket</u>: splat.AsyncSocket;
124</big></dt>
125<dd>Asynchronous UDP socket shortcut.
126<br><br>
127
128<dl><dt><big>this(AddressFamily <i>family</i>);
129<br>this();
130<br>this(EventType <i>events</i>, void delegate(Socket sock, EventType type, int err) <i>eventCallback</i>);
131</big></dt>
132<dd><br><br>
133</dd>
134</dl>
135</dd>
136<dt><big>alias <u>GetHostCallback</u>;
137</big></dt>
138<dd>Callback type for host resolve event.
139<br><br>
140<b>Params:</b><br>
141<table><tr><td>inetHost</td>
142<td>the InternetHost/NetHost of the resolved host, or <b>null</b>.</td></tr>
143<tr><td>err</td>
144<td>an error code, or 0 if successful; if 0, inetHost will be <b>null</b>.</td></tr>
145</table><br>
146
147</dd>
148<dt><big>class <u>GetHost</u>;
149</big></dt>
150<dd>Returned from asyncGetHost functions.
151<br><br>
152
153<dl><dt><big>void <u>cancel</u>();
154</big></dt>
155<dd>Cancel the get-host operation.
156<br><br>
157
158</dd>
159</dl>
160</dd>
161<dt><big>GetHost <u>asyncGetHostByName</u>(char[] <i>name</i>, void delegate(InternetHost inetHost, int err) <i>callback</i>);
162</big></dt>
163<dd>Asynchronously resolve host information from a hostname; the <i>callback</i> depends on run().
164<br><br>
165
166</dd>
167<dt><big>GetHost <u>asyncGetHostByAddr</u>(uint <i>addr</i>, void delegate(InternetHost inetHost, int err) <i>callback</i>);
168<br>GetHost <u>asyncGetHostByAddr</u>(char[] <i>addr</i>, void delegate(InternetHost inetHost, int err) <i>callback</i>);
169</big></dt>
170<dd>Asynchronously resolve host information from an IPv4 address; the <i>callback</i> depends on run().
171<br><br>
172
173</dd>
174<dt><big>class <u>SocketQueue</u>;
175</big></dt>
176<dd>Buffering socket I/O.
177<br><br>
178
179<dl><dt><big>this(Socket <i>sock</i>);
180</big></dt>
181<dd><br><br>
182</dd>
183<dt><big>final Socket <u>socket</u>();
184</big></dt>
185<dd><b>Property:</b><br>
186get the <u>socket</u> of this queue.
187<br><br>
188
189</dd>
190<dt><big>void <u>reset</u>();
191</big></dt>
192<dd>Resets the buffers.
193<br><br>
194
195</dd>
196<dt><big>void[] <u>peek</u>();
197<br>void[] <u>peek</u>(uint <i>len</i>);
198</big></dt>
199<dd>Peek at some or all of the received data but leave it in the queue. May return less than requested.
200<br><br>
201
202</dd>
203<dt><big>void[] <u>receive</u>();
204<br>void[] <u>receive</u>(uint <i>len</i>);
205</big></dt>
206<dd><b>Returns:</b><br>
207some or all of the received data and removes this amount from the queue. May return less than requested.
208<br><br>
209
210</dd>
211<dt><big>void <u>send</u>(void[] <i>buf</i>);
212</big></dt>
213<dd>Add data to the queue and <u>send</u> it over this socket.
214<br><br>
215
216</dd>
217<dt><big>uint <u>sendBytes</u>();
218</big></dt>
219<dd><b>Property:</b><br>
220get the number of bytes in send buffer.
221<br><br>
222
223</dd>
224<dt><big>uint <u>receiveBytes</u>();
225</big></dt>
226<dd><b>Property:</b><br>
227get the number of bytes in recv buffer.
228<br><br>
229
230</dd>
231<dt><big>void <u>readEvent</u>();
232</big></dt>
233<dd>Call on a read event so that incoming data may be buffered.
234<br><br>
235
236</dd>
237<dt><big>void <u>writeEvent</u>();
238</big></dt>
239<dd>Call on a write event so that buffered outgoing data may be sent.
240<br><br>
241
242</dd>
243<dt><big>void <u>event</u>(Socket <i>_sock</i>, EventType <i>type</i>, int <i>err</i>);
244</big></dt>
245<dd>Shortcut function for AsyncSocket.
246 Automatically calls readEvent and writeEvent as needed.
247 Same signature as RegisterEventCallback for simplicity.
248
249<br><br>
250
251</dd>
252</dl>
253</dd>
254<dt><big>uint <u>getNumberOfAsyncSockets</u>();
255</big></dt>
256<dd>Returns the number of asynchronous sockets waiting for events.
257<br><br>
258
259</dd>
260<dt><big>uint <u>getNumberOfTimers</u>();
261</big></dt>
262<dd>Returns the number of active timers.
263<br><br>
264
265</dd>
266</dl>
267
268 <hr><small>Page generated by <a href="http://www.digitalmars.com/d/ddoc.html">Ddoc</a>. </small>
269 </body></html>
0270
=== added file 'D_lang/testing/candidate_libs/splat07.zip'
1Binary files D_lang/testing/candidate_libs/splat07.zip 1970-01-01 00:00:00 +0000 and D_lang/testing/candidate_libs/splat07.zip 2013-02-21 03:06:20 +0000 differ271Binary files D_lang/testing/candidate_libs/splat07.zip 1970-01-01 00:00:00 +0000 and D_lang/testing/candidate_libs/splat07.zip 2013-02-21 03:06:20 +0000 differ
=== added directory 'D_lang/testing/str_socket'
=== added file 'D_lang/testing/str_socket/Makefile'
--- D_lang/testing/str_socket/Makefile 1970-01-01 00:00:00 +0000
+++ D_lang/testing/str_socket/Makefile 2013-02-21 03:06:20 +0000
@@ -0,0 +1,30 @@
1#***********************************************
2# This file is part of the NRTB project (https://launchpad.net/nrtb).
3#
4# NRTB is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# NRTB is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
16#
17#***********************************************
18
19lib: socket_test
20 @./socket_test
21 @echo build complete
22
23socket_test: socket_test.d Makefile
24 @rm -f socket_test
25 @dmd socket_test.d
26
27clean:
28 @rm -vf *.o socket_test
29 @echo all objects and executables have been erased.
30
031
=== added file 'D_lang/testing/str_socket/SocketStringTransciever.mm'
--- D_lang/testing/str_socket/SocketStringTransciever.mm 1970-01-01 00:00:00 +0000
+++ D_lang/testing/str_socket/SocketStringTransciever.mm 2013-02-21 03:06:20 +0000
@@ -0,0 +1,49 @@
1<map version="0.9.0">
2<!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net -->
3<node CREATED="1353288395487" ID="ID_1403329192" MODIFIED="1353512093507" TEXT="Socket string transciever.">
4<node CREATED="1353288596251" ID="ID_1636926895" MODIFIED="1353512095611" POSITION="right" TEXT="Connect(address)">
5<node CREATED="1353289092215" ID="ID_1097805018" MODIFIED="1353289099292" TEXT="Resolves address"/>
6<node CREATED="1353289100126" ID="ID_912894431" MODIFIED="1353289144348" TEXT="Connects to address"/>
7<node CREATED="1353289145245" ID="ID_1737995458" MODIFIED="1353289159019" TEXT="Starts reciever thread"/>
8<node CREATED="1353290958729" ID="ID_1494063472" MODIFIED="1353291040119" TEXT="Expects the callbacks to set at call time"/>
9<node CREATED="1353289166189" ID="ID_244950625" MODIFIED="1353289174227" TEXT="throws on any error"/>
10</node>
11<node CREATED="1353288616481" ID="ID_845783483" MODIFIED="1353512095614" POSITION="right" TEXT="close()">
12<node CREATED="1353289189501" ID="ID_142698792" MODIFIED="1353289197939" TEXT="Shutdown reciever thread"/>
13<node CREATED="1353289198757" ID="ID_771780490" MODIFIED="1353289263410" TEXT="close socket"/>
14<node CREATED="1353289271773" ID="ID_357264070" MODIFIED="1353289293595" TEXT="discard any other resources allocated"/>
15</node>
16<node CREATED="1353288702488" ID="ID_1885052703" MODIFIED="1353512095619" POSITION="right" TEXT="regeister_receiver(funtion(newStr))">
17<node CREATED="1353289372692" ID="ID_1797818997" MODIFIED="1353289421498" TEXT="Replace existing reciever callback"/>
18<node CREATED="1353289422811" ID="ID_716021446" MODIFIED="1353289467577" TEXT="The callback has the signiture function(string)"/>
19<node CREATED="1353289476939" ID="ID_1689880619" MODIFIED="1353290199100" TEXT="The callback will be called whenever an ASCII 10 is recieved."/>
20<node CREATED="1353290138311" ID="ID_48990930" MODIFIED="1353290251764" TEXT="The argument &quot;newStr&quot; will contain any bytes recieved before the ASCII 10"/>
21<node CREATED="1353289528395" ID="ID_1457236482" MODIFIED="1353290179636" TEXT="ASCII 10s and 13s will be discarded"/>
22</node>
23<node CREATED="1353288756648" ID="ID_1776338151" MODIFIED="1353288803357" POSITION="right" TEXT="register_event_hander(funciton(event))">
24<node CREATED="1353289687346" ID="ID_146527388" MODIFIED="1353289714640" TEXT="Replace existing event handler"/>
25<node CREATED="1353289715586" ID="ID_1957454409" MODIFIED="1353289748151" TEXT="The callback has the signiture function(string)"/>
26<node CREATED="1353289749753" ID="ID_1524918841" MODIFIED="1353289768918" TEXT="The callback will be called whenever an event occurs"/>
27<node CREATED="1353289775721" ID="ID_698482207" MODIFIED="1353289785327" TEXT="Available events">
28<node CREATED="1353495351509" ID="ID_1988403096" MODIFIED="1353495373615" TEXT="connect"/>
29<node CREATED="1353495374592" ID="ID_1082092706" MODIFIED="1353495385858" TEXT="overflow"/>
30<node CREATED="1353495387001" ID="ID_1818531252" MODIFIED="1353495391356" TEXT="underflow"/>
31<node CREATED="1353495392662" ID="ID_236107112" MODIFIED="1353495399980" TEXT="dropped"/>
32<node CREATED="1353495400962" ID="ID_909770107" MODIFIED="1353495403143" TEXT="disconnect"/>
33</node>
34</node>
35<node CREATED="1353288811903" ID="ID_1354285471" MODIFIED="1353512095621" POSITION="right" TEXT="send(string)">
36<node CREATED="1353289903920" ID="ID_293305230" MODIFIED="1353290032885" TEXT="Sends the argument on the socket"/>
37<node CREATED="1353290036647" ID="ID_1916879506" MODIFIED="1353290061148" TEXT="An ASCII 10 will be postixed to the string"/>
38<node CREATED="1353290092071" ID="ID_1214127336" MODIFIED="1353290125572" TEXT="Blocks until the send is complete."/>
39</node>
40<node CREATED="1353290448717" ID="ID_1736651166" MODIFIED="1353512095625" POSITION="right" TEXT="worker_thread()">
41<node CREATED="1353290466204" ID="ID_1117113952" MODIFIED="1353290517609" TEXT="Responible for incoming bytes"/>
42<node CREATED="1353290741723" ID="ID_910559431" MODIFIED="1353290766920" TEXT="discards ASCII 10 and 13"/>
43<node CREATED="1353290769963" ID="ID_1282285823" MODIFIED="1353290798568" TEXT="places all other bytes in the buffer"/>
44<node CREATED="1353290518900" ID="ID_216777552" MODIFIED="1353291656818" TEXT="calls the receiver callback with the buffer on recept of an EOM (ASCII 10)"/>
45<node CREATED="1353290869346" ID="ID_823816252" MODIFIED="1353290886168" TEXT="Clears the buffer when the callback returns"/>
46<node CREATED="1353291445518" ID="ID_578045982" MODIFIED="1353291464356" TEXT="Loops infinitely until closed."/>
47</node>
48</node>
49</map>
050
=== added file 'D_lang/testing/str_socket/socket_test.d'
--- D_lang/testing/str_socket/socket_test.d 1970-01-01 00:00:00 +0000
+++ D_lang/testing/str_socket/socket_test.d 2013-02-21 03:06:20 +0000
@@ -0,0 +1,43 @@
1/*********************
2Multithreaded message passing example in D
3*********************/
4
5// import the concurrency and standard IO modules
6import std.concurrency, std.stdio;
7import std.string, std.conv, std.stream, std.stdio;
8import std.socket, std.socketstream;
9
10// main is just like main in C++
11void main(string[] args)
12{
13 writeln("D Socket Send/Receive Test.");
14
15 if (args.length < 2)
16 {
17 writeln("Usage:");
18 writeln(" ",args[0]," httpd_IP");
19 return;
20 }
21
22 string IP = args[1];
23 ushort port = 80;
24
25 writefln(" Connecting to host %s:%d....",IP,port);
26
27 // connect to the server
28 Socket sock = new TcpSocket(new InternetAddress(IP, port));
29 scope(exit) sock.close();
30 Stream ss = new SocketStream(sock);
31
32 ss.writeString("GET / HTTP/1.0\r\nHost: " ~ IP ~ "\r\n\r\n");
33
34 while (!ss.eof())
35 {
36 auto line = ss.readLine();
37 writeln(line);
38 }
39
40 writeln("** main() is complete **");
41
42}
43
044
=== added directory 'D_lang/testing/thread_pool'
=== added file 'D_lang/testing/thread_pool/Makefile'
--- D_lang/testing/thread_pool/Makefile 1970-01-01 00:00:00 +0000
+++ D_lang/testing/thread_pool/Makefile 2013-02-21 03:06:20 +0000
@@ -0,0 +1,30 @@
1#***********************************************
2# This file is part of the NRTB project (https://launchpad.net/nrtb).
3#
4# NRTB is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# NRTB is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
16#
17#***********************************************
18
19lib: thread_pool
20 @./thread_pool
21 @echo build complete
22
23thread_pool: thread_pool.d Makefile
24 @rm -f thread_pool
25 @dmd thread_pool.d
26
27clean:
28 @rm -vf *.o thread_pool
29 @echo all objects and executables have been erased.
30
031
=== added file 'D_lang/testing/thread_pool/thread_pool.d'
--- D_lang/testing/thread_pool/thread_pool.d 1970-01-01 00:00:00 +0000
+++ D_lang/testing/thread_pool/thread_pool.d 2013-02-21 03:06:20 +0000
@@ -0,0 +1,81 @@
1/*********************
2Multithreaded message passing example in D
3*********************/
4
5// import the concurrency and standard IO modules
6import std.concurrency, std.stdio, core.thread;
7
8struct thread_pool(wp_t, alias task)
9{
10 // Housekeeping variables
11 private Tid listener_tid;
12
13 // Does nothing but start the listener.
14 public this(int queue_size) {
15 listener_tid = spawn(&listener_thread!(wp_t,task),queue_size);
16 };
17
18 // submit a work, packet for processing.
19 public void submit(wp_t wp) {
20 listener_tid.send(thisTid, wp);
21 };
22
23}
24
25void worker_thread(wpt, alias task)() {
26 bool running = true;
27 while (running) {
28 receive (
29 (Tid t, wpt d) { task(t,d); },
30 (OwnerTerminated e) { running = false; }
31 );
32 };
33}
34
35void listener_thread(wpt, alias task)(int queue_size) {
36
37 Tid worker_list[];
38 ulong next = 0;
39
40 void submit(Tid t, wpt d) {
41 worker_list[next].send(t,d);
42 next = (++next) % worker_list.length;
43 }
44
45 // initial setup.
46 for(int i = 0; i< queue_size; i++) {
47 worker_list ~= spawn(&worker_thread!(wpt,task));
48 }
49
50 // service loop
51 bool running = true;
52 while (running) {
53 receive (
54 (Tid t, wpt d) { submit(t,d); },
55 (OwnerTerminated e) { running = false; }
56 );
57 };
58};
59
60//==== code starts here
61
62void mytask(Tid t, int i) {
63 writeln("Task ",thisTid," processed ",i);
64 Thread.sleep(dur!("msecs") (20));
65};
66
67
68// main is just like main in C++
69void main()
70{
71 writeln("D Message Driven Work Queue Example.");
72 auto myqueue = thread_pool!(int,mytask)(10);
73
74 for (auto i=0; i<100; i++) {
75 myqueue.submit(i);
76 };
77
78 Thread.sleep(dur!("seconds") (3));
79 writeln("Run complete");
80
81};
0\ No newline at end of file82\ No newline at end of file
183
=== added file 'D_lang/testing/thread_pool/thread_pool.mm'
--- D_lang/testing/thread_pool/thread_pool.mm 1970-01-01 00:00:00 +0000
+++ D_lang/testing/thread_pool/thread_pool.mm 2013-02-21 03:06:20 +0000
@@ -0,0 +1,47 @@
1<map version="0.9.0">
2<!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net -->
3<node CREATED="1199190455281" ID="ID_1574918623" MODIFIED="1199190480522" TEXT="thread_pool">
4<node CREATED="1360253779843" ID="ID_432711866" MODIFIED="1360261129036" POSITION="right" TEXT="class task_pool(t)">
5<node CREATED="1360267525267" ID="ID_760440288" MODIFIED="1360267533846" TEXT="this()">
6<node CREATED="1360268024517" ID="ID_1334050998" MODIFIED="1360328468829" TEXT="starts task_pool_manager(t)(low,high,,increment,task)"/>
7</node>
8<node CREATED="1360081590643" ID="ID_1324728" MODIFIED="1360081668955" TEXT="struct work_packet(t)"/>
9<node CREATED="1360081723340" ID="ID_1492950840" MODIFIED="1360081762970" TEXT="struct limits"/>
10<node CREATED="1360081739372" ID="ID_452972575" MODIFIED="1360081747882" TEXT="struct run_ctl"/>
11<node CREATED="1360254280681" ID="ID_778719726" MODIFIED="1360261274927" TEXT="void submit(t data)"/>
12<node CREATED="1360254367731" ID="ID_1043224962" MODIFIED="1360261286496" TEXT="uint set_limits(low, high, increment)"/>
13</node>
14<node CREATED="1360082136187" ID="ID_181135344" MODIFIED="1360328486894" POSITION="right" TEXT="task pool manager(t)(low, high, increment,task)">
15<node CREATED="1360254670685" ID="ID_1823995507" MODIFIED="1360254677048" TEXT="Free running thread"/>
16<node CREATED="1360254680507" ID="ID_291925315" MODIFIED="1360255051860" TEXT="On startup">
17<node CREATED="1360254687714" ID="ID_415174674" MODIFIED="1360254704683" TEXT="Registers with the global pool manager"/>
18<node CREATED="1360254714285" ID="ID_1841317578" MODIFIED="1360544160805" TEXT="starts default set of task_thread(t)(thisTid,task)"/>
19</node>
20<node CREATED="1360254933031" ID="ID_683968420" MODIFIED="1360255382530" TEXT="Service loop">
21<node CREATED="1360255079468" ID="ID_1559510237" MODIFIED="1360255176424" TEXT="rcv Tid, t">
22<node CREATED="1360255261482" ID="ID_29306120" MODIFIED="1360255307209" TEXT="Verify there spare thread count"/>
23<node CREATED="1360255312567" ID="ID_662023772" MODIFIED="1360255333731" TEXT="submit Tid, t to next task thread"/>
24</node>
25<node CREATED="1360255179495" ID="ID_548612491" MODIFIED="1360334567427" TEXT="rcv Tid, limits">
26<node CREATED="1360255428431" ID="ID_1067723780" MODIFIED="1360255499958" TEXT="Reset pool parameters"/>
27<node CREATED="1360255501795" ID="ID_943031629" MODIFIED="1360255516011" TEXT="Add/remove worker threads as needed"/>
28</node>
29<node CREATED="1360334567882" ID="ID_1909911450" MODIFIED="1360334583842" TEXT="rvc Tid, run_ctl">
30<node CREATED="1360334583845" ID="ID_882927298" MODIFIED="1360336402561" TEXT="shutdown"/>
31</node>
32</node>
33</node>
34<node CREATED="1360081583633" ID="ID_1103044446" MODIFIED="1360328522599" POSITION="right" TEXT="task_thread(t)(Tid task_pool_manager,task)">
35<node CREATED="1360281228443" ID="ID_1814378750" MODIFIED="1360281259435" TEXT="Free running thread"/>
36<node CREATED="1360334423885" ID="ID_1136327708" MODIFIED="1360334431123" TEXT="On startup"/>
37<node CREATED="1360334432374" ID="ID_516047719" MODIFIED="1360334444665" TEXT="Service Loop">
38<node CREATED="1360334444667" ID="ID_1239866205" MODIFIED="1360334469683" TEXT="receive tid, t">
39<node CREATED="1360334469685" ID="ID_1854740647" MODIFIED="1360334485839" TEXT="Call task(tid,t)"/>
40</node>
41<node CREATED="1360334493738" ID="ID_1132173280" MODIFIED="1360334530760" TEXT="receive tid, run_ctl">
42<node CREATED="1360334530762" ID="ID_1133543570" MODIFIED="1360334542293" TEXT="shutdown"/>
43</node>
44</node>
45</node>
46</node>
47</map>

Subscribers

People subscribed via source and target branches

to all changes: