1 /*
2  *
3  *  Copyright (C) 2000-2010, OFFIS e.V.
4  *  All rights reserved.  See COPYRIGHT file for details.
5  *
6  *  This software and supporting documentation were developed by
7  *
8  *    OFFIS e.V.
9  *    R&D Division Health
10  *    Escherweg 2
11  *    D-26121 Oldenburg, Germany
12  *
13  *
14  *  Module:  ofstd
15  *
16  *  Author:  Marco Eichelberg
17  *
18  *  Purpose: Define alias for cout, cerr and clog
19  *
20  */
21 
22 #include "dcmtk/config/osconfig.h"
23 #include "dcmtk/ofstd/ofconsol.h"
24 #include "dcmtk/ofstd/ofthread.h"
25 
26 #define INCLUDE_CASSERT
27 #include "dcmtk/ofstd/ofstdinc.h"
28 
29 
30 #ifdef DCMTK_GUI
31   OFOStringStream COUT;
32   OFOStringStream CERR;
33 #endif
34 
OFConsole()35 OFConsole::OFConsole()
36 #ifdef DCMTK_GUI
37 : currentCout(&COUT)
38 , currentCerr(&CERR)
39 #else
40 : currentCout(&STD_NAMESPACE cout)
41 , currentCerr(&STD_NAMESPACE cerr)
42 #endif
43 , joined(0)
44 #ifdef WITH_THREADS
45 , coutMutex()
46 , cerrMutex()
47 #endif
48 {
49 }
50 
setCout(STD_NAMESPACE ostream * newCout)51 STD_NAMESPACE ostream *OFConsole::setCout(STD_NAMESPACE ostream *newCout)
52 {
53   lockCout();
54   STD_NAMESPACE ostream *tmpCout = currentCout;
55 #ifdef DCMTK_GUI
56   if (newCout) currentCout = newCout; else currentCout = &COUT;
57 #else
58   if (newCout) currentCout = newCout; else currentCout = &STD_NAMESPACE cout;
59 #endif
60   unlockCout();
61   return tmpCout;
62 }
63 
setCerr(STD_NAMESPACE ostream * newCerr)64 STD_NAMESPACE ostream *OFConsole::setCerr(STD_NAMESPACE ostream *newCerr)
65 {
66   lockCerr();
67   STD_NAMESPACE ostream *tmpCerr = currentCerr;
68 #ifdef DCMTK_GUI
69   if (newCerr) currentCerr = newCerr; else currentCerr = &CERR;
70 #else
71   if (newCerr) currentCerr = newCerr; else currentCerr = &STD_NAMESPACE cerr;
72 #endif
73   unlockCerr();
74   return tmpCerr;
75 }
76 
join()77 void OFConsole::join()
78 {
79   lockCerr();
80   if (!joined)
81   {
82     // changing the state of "joined" requires that both mutexes are locked.
83     // Mutexes must always be locked in the same order to avoid deadlocks.
84     lockCout();
85     joined = 1;
86   }
87 
88   // now status is joined, so unlockCerr implicitly unlocks both mutexes
89   unlockCerr();
90   return;
91 }
92 
split()93 void OFConsole::split()
94 {
95   lockCerr();
96   if (joined)
97   {
98     // since status is joined, lockCerr() has locked both mutexes
99     joined = 0;
100 
101     // now status is unjoined, we have to unlock both mutexes manually
102     unlockCout();
103   }
104   unlockCerr();
105   return;
106 }
107 
isJoined()108 OFBool OFConsole::isJoined()
109 {
110   lockCerr();
111   // nobody will change "joined" if we have locked either mutex
112   int result = joined;
113   unlockCerr();
114   if (result) return OFTrue; else return OFFalse;
115 }
116 
instance()117 OFConsole& OFConsole::instance()
118 {
119   static OFConsole instance_;
120   return instance_;
121 }
122 
123 
124 class OFConsoleInitializer
125 {
126 public:
OFConsoleInitializer()127   OFConsoleInitializer()
128   {
129     OFConsole::instance();
130   }
131 };
132 
133 /* the constructor of this global object makes sure
134  * that ofConsole is initialized before main starts.
135  * Required to make ofConsole thread-safe.
136  */
137 OFConsoleInitializer ofConsoleInitializer;
138