1 module unit_threaded.writer_thread;
2 
3 import unit_threaded.io;
4 import std.concurrency;
5 import std.stdio;
6 import std.conv;
7 
8 
9 package void utWrite(T...)(T args) {
10     WriterThread.get().write(args);
11 }
12 
13 package void utWriteln(T...)(T args) {
14     WriterThread.get().writeln(args);
15 }
16 
17 package void utWritelnGreen(T...)(T args) {
18     WriterThread.get().writelnGreen(args);
19 }
20 
21 package void utWritelnRed(T...)(T args) {
22     WriterThread.get().writelnRed(args);
23 }
24 
25 
26 /**
27  * Thread to output to stdout
28  */
29 class WriterThread {
30     static WriterThread get() {
31         if(!_instantiated) {
32             synchronized {
33                 if (_instance is null) {
34                     _instance = new WriterThread;
35                 }
36                 _instantiated = true;
37             }
38         }
39         return _instance;
40     }
41 
42     void write(T...)(T args) {
43         _tid.send(text(args));
44     }
45 
46     void writeln(T...)(T args) {
47         write(args, "\n");
48     }
49 
50     void writelnGreen(T...)(T args) {
51         _tid.send(green(text(args) ~ "\n"));
52     }
53 
54     void writelnRed(T...)(T args) {
55         _tid.send(red(text(args) ~ "\n"));
56     }
57 
58     void join() {
59         _tid.send(thisTid); //tell it to join
60         receiveOnly!Tid(); //wait for it to join
61     }
62 
63 private:
64 
65     this() {
66         _tid = spawn(&threadWriter);
67     }
68 
69     Tid _tid;
70 
71     static bool _instantiated; // Thread local
72     __gshared WriterThread _instance;
73 }
74 
75 private void threadWriter() {
76     auto done = false;
77     Tid tid;
78 
79     auto saveStdout = stdout;
80     auto saveStderr = stderr;
81 
82     if(!isDebugOutputEnabled()) {
83         stdout = File("/dev/null", "w");
84         stderr = File("/dev/null", "w");
85     }
86 
87     while(!done) {
88         string output;
89         receive(
90             (string msg) {
91                 output ~= msg;
92             },
93             (Tid i) {
94                 done = true;
95                 tid = i;
96             },
97             (OwnerTerminated trm) {
98                 done = true;
99             }
100         );
101         saveStdout.write(output);
102     }
103     saveStdout.flush();
104     stdout = saveStdout;
105     stderr = saveStderr;
106     if(tid != Tid.init) tid.send(thisTid);
107 }