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

Subscribers

People subscribed via source and target branches

to all changes: