OSDN Git Service

post WM_NULL to attached threads on yamy exit to unmap mayu{32,64}.dll
[yamy/yamy.git] / msgstream.h
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // msgstream.h\r
3 \r
4 \r
5 #ifndef _MSGSTREAM_H\r
6 #  define _MSGSTREAM_H\r
7 \r
8 #  include "misc.h"\r
9 #  include "stringtool.h"\r
10 #  include "multithread.h"\r
11 \r
12 \r
13 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
14 // msgstream\r
15 \r
16 /** msgstream.\r
17 \r
18     <p>Before writing to omsgstream, you must acquire lock by calling\r
19     <code>acquire()</code>.  Then after completion of writing, you\r
20     must call <code>release()</code>.</p>\r
21 \r
22     <p>Omsgbuf calls <code>PostMessage(hwnd, messageid, 0,\r
23     (LPARAM)omsgbuf)</code> to notify that string is ready to get.\r
24     When the window (<code>hwnd</code>) get the message, you can get\r
25     the string containd in the omsgbuf by calling\r
26     <code>acquireString()</code>.  After calling\r
27     <code>acquireString()</code>, you must / call releaseString().</p>\r
28 \r
29 */\r
30 \r
31 template<class T, size_t SIZE = 1024,\r
32 class TR = std::char_traits<T>, class A = std::allocator<T> >\r
33 class basic_msgbuf : public std::basic_streambuf<T, TR>, public SyncObject\r
34 {\r
35 public:\r
36         typedef std::basic_string<T, TR, A> String;     ///\r
37         typedef std::basic_streambuf<T, TR> Super;      ///\r
38 \r
39 private:\r
40         HWND m_hwnd;                                    /** window handle for\r
41                                                     notification */\r
42         UINT m_messageId;                               /// messageid for notification\r
43         T *m_buf;                                       /// for streambuf\r
44         String m_str;                                   /// for notification\r
45         CriticalSection m_cs;                           /// lock\r
46         A m_allocator;                          /// allocator\r
47 \r
48         /** debug level.\r
49             if ( m_msgDebugLevel &lt;= m_debugLevel ), message is displayed\r
50         */\r
51         int m_debugLevel;\r
52         int m_msgDebugLevel;                            ///\r
53 \r
54 private:\r
55         basic_msgbuf(const basic_msgbuf &);             /// disable copy constructor\r
56 \r
57 public:\r
58         ///\r
59         basic_msgbuf(UINT i_messageId, HWND i_hwnd = 0)\r
60                         : m_hwnd(i_hwnd),\r
61                         m_messageId(i_messageId),\r
62                         m_buf(m_allocator.allocate(SIZE, 0)),\r
63                         m_debugLevel(0),\r
64                         m_msgDebugLevel(0) {\r
65                 ASSERT(m_buf);\r
66                 setp(m_buf, m_buf + SIZE);\r
67         }\r
68 \r
69         ///\r
70         ~basic_msgbuf() {\r
71                 sync();\r
72                 m_allocator.deallocate(m_buf, SIZE);\r
73         }\r
74 \r
75         /// attach/detach a window\r
76         basic_msgbuf* attach(HWND i_hwnd) {\r
77                 Acquire a(&m_cs);\r
78                 ASSERT( !m_hwnd && i_hwnd );\r
79                 m_hwnd = i_hwnd;\r
80                 if (!m_str.empty())\r
81                         PostMessage(m_hwnd, m_messageId, 0, (LPARAM)this);\r
82                 return this;\r
83         }\r
84 \r
85         ///\r
86         basic_msgbuf* detach() {\r
87                 Acquire a(&m_cs);\r
88                 sync();\r
89                 m_hwnd = 0;\r
90                 return this;\r
91         }\r
92 \r
93         /// get window handle\r
94         HWND getHwnd() const {\r
95                 return m_hwnd;\r
96         }\r
97 \r
98         /// is a window attached ?\r
99         int is_open() const {\r
100                 return !!m_hwnd;\r
101         }\r
102 \r
103         /// acquire string and release the string\r
104         const String &acquireString() {\r
105                 m_cs.acquire();\r
106                 return m_str;\r
107         }\r
108 \r
109         ///\r
110         void releaseString() {\r
111                 m_str.resize(0);\r
112                 m_cs.release();\r
113         }\r
114 \r
115         /// set debug level\r
116         void setDebugLevel(int i_debugLevel) {\r
117                 m_debugLevel = i_debugLevel;\r
118         }\r
119 \r
120         ///\r
121         int getDebugLevel() const {\r
122                 return m_debugLevel;\r
123         }\r
124 \r
125         // for stream\r
126         typename Super::int_type overflow(typename Super::int_type i_c = TR::eof()) {\r
127                 if (sync() == TR::eof()) // sync before new buffer created below\r
128                         return TR::eof();\r
129 \r
130                 if (i_c != TR::eof()) {\r
131                         *pptr() = TR::to_char_type(i_c);\r
132                         pbump(1);\r
133                         sync();\r
134                 }\r
135                 return TR::not_eof(i_c); // return something other than EOF if successful\r
136         }\r
137 \r
138         // for stream\r
139         int sync() {\r
140                 T *begin = pbase();\r
141                 T *end = pptr();\r
142                 T *i;\r
143                 for (i = begin; i < end; ++ i)\r
144                         if (_istlead(*i))\r
145                                 ++ i;\r
146                 if (i == end) {\r
147                         if (m_msgDebugLevel <= m_debugLevel)\r
148                                 m_str += String(begin, end - begin);\r
149                         setp(m_buf, m_buf + SIZE);\r
150                 } else { // end < i\r
151                         if (m_msgDebugLevel <= m_debugLevel)\r
152                                 m_str += String(begin, end - begin - 1);\r
153                         m_buf[0] = end[-1];\r
154                         setp(m_buf, m_buf + SIZE);\r
155                         pbump(1);\r
156                 }\r
157                 return TR::not_eof(0);\r
158         }\r
159 \r
160         // sync object\r
161 \r
162         /// begin writing\r
163         virtual void acquire() {\r
164                 m_cs.acquire();\r
165         }\r
166 \r
167         /// begin writing\r
168         virtual void acquire(int i_msgDebugLevel) {\r
169                 m_cs.acquire();\r
170                 m_msgDebugLevel = i_msgDebugLevel;\r
171         }\r
172 \r
173         /// end writing\r
174         virtual void release() {\r
175                 if (!m_str.empty())\r
176                         PostMessage(m_hwnd, m_messageId, 0, reinterpret_cast<LPARAM>(this));\r
177                 m_msgDebugLevel = m_debugLevel;\r
178                 m_cs.release();\r
179         }\r
180 };\r
181 \r
182 \r
183 ///\r
184 template<class T, size_t SIZE = 1024,\r
185 class TR = std::char_traits<T>, class A = std::allocator<T> >\r
186 class basic_omsgstream : public std::basic_ostream<T, TR>, public SyncObject\r
187 {\r
188 public:\r
189         typedef std::basic_ostream<T, TR> Super;        ///\r
190         typedef basic_msgbuf<T, SIZE, TR, A> StreamBuf; ///\r
191         typedef std::basic_string<T, TR, A> String;     ///\r
192 \r
193 private:\r
194         StreamBuf m_streamBuf;                  ///\r
195 \r
196 public:\r
197         ///\r
198         explicit basic_omsgstream(UINT i_messageId, HWND i_hwnd = 0)\r
199                         : Super(&m_streamBuf), m_streamBuf(i_messageId, i_hwnd) {\r
200         }\r
201 \r
202         ///\r
203         virtual ~basic_omsgstream() {\r
204         }\r
205 \r
206         ///\r
207         StreamBuf *rdbuf() const {\r
208                 return const_cast<StreamBuf *>(&m_streamBuf);\r
209         }\r
210 \r
211         /// attach a msg control\r
212         void attach(HWND i_hwnd) {\r
213                 m_streamBuf.attach(i_hwnd);\r
214         }\r
215 \r
216         /// detach a msg control\r
217         void detach() {\r
218                 m_streamBuf.detach();\r
219         }\r
220 \r
221         /// get window handle of the msg control\r
222         HWND getHwnd() const {\r
223                 return m_streamBuf.getHwnd();\r
224         }\r
225 \r
226         /// is the msg control attached ?\r
227         int is_open() const {\r
228                 return m_streamBuf.is_open();\r
229         }\r
230 \r
231         /// set debug level\r
232         void setDebugLevel(int i_debugLevel) {\r
233                 m_streamBuf.setDebugLevel(i_debugLevel);\r
234         }\r
235 \r
236         ///\r
237         int getDebugLevel() const {\r
238                 return m_streamBuf.getDebugLevel();\r
239         }\r
240 \r
241         /// acquire string and release the string\r
242         const String &acquireString() {\r
243                 return m_streamBuf.acquireString();\r
244         }\r
245 \r
246         ///\r
247         void releaseString() {\r
248                 m_streamBuf->releaseString();\r
249         }\r
250 \r
251         // sync object\r
252 \r
253         /// begin writing\r
254         virtual void acquire() {\r
255                 m_streamBuf.acquire();\r
256         }\r
257 \r
258         /// begin writing\r
259         virtual void acquire(int i_msgDebugLevel) {\r
260                 m_streamBuf.acquire(i_msgDebugLevel);\r
261         }\r
262 \r
263         /// end writing\r
264         virtual void release() {\r
265                 m_streamBuf.release();\r
266         }\r
267 };\r
268 \r
269 ///\r
270 typedef basic_omsgstream<_TCHAR> tomsgstream;\r
271 \r
272 \r
273 #endif // !_MSGSTREAM_H\r