1 | // |
---|---|
2 | // AsyncChannel.cpp |
3 | // |
4 | // Library: Foundation |
5 | // Package: Logging |
6 | // Module: AsyncChannel |
7 | // |
8 | // Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/AsyncChannel.h" |
16 | #include "Poco/Notification.h" |
17 | #include "Poco/Message.h" |
18 | #include "Poco/Formatter.h" |
19 | #include "Poco/AutoPtr.h" |
20 | #include "Poco/LoggingRegistry.h" |
21 | #include "Poco/Exception.h" |
22 | |
23 | |
24 | namespace Poco { |
25 | |
26 | |
27 | class MessageNotification: public Notification |
28 | { |
29 | public: |
30 | MessageNotification(const Message& msg): |
31 | _msg(msg) |
32 | { |
33 | } |
34 | |
35 | ~MessageNotification() |
36 | { |
37 | } |
38 | |
39 | const Message& message() const |
40 | { |
41 | return _msg; |
42 | } |
43 | |
44 | private: |
45 | Message _msg; |
46 | }; |
47 | |
48 | |
49 | AsyncChannel::AsyncChannel(Channel* pChannel, Thread::Priority prio): |
50 | _pChannel(pChannel), |
51 | _thread("AsyncChannel") |
52 | { |
53 | if (_pChannel) _pChannel->duplicate(); |
54 | _thread.setPriority(prio); |
55 | } |
56 | |
57 | |
58 | AsyncChannel::~AsyncChannel() |
59 | { |
60 | try |
61 | { |
62 | close(); |
63 | if (_pChannel) _pChannel->release(); |
64 | } |
65 | catch (...) |
66 | { |
67 | poco_unexpected(); |
68 | } |
69 | } |
70 | |
71 | |
72 | void AsyncChannel::setChannel(Channel* pChannel) |
73 | { |
74 | FastMutex::ScopedLock lock(_channelMutex); |
75 | |
76 | if (_pChannel) _pChannel->release(); |
77 | _pChannel = pChannel; |
78 | if (_pChannel) _pChannel->duplicate(); |
79 | } |
80 | |
81 | |
82 | Channel* AsyncChannel::getChannel() const |
83 | { |
84 | return _pChannel; |
85 | } |
86 | |
87 | |
88 | void AsyncChannel::open() |
89 | { |
90 | FastMutex::ScopedLock lock(_threadMutex); |
91 | |
92 | if (!_thread.isRunning()) |
93 | _thread.start(*this); |
94 | } |
95 | |
96 | |
97 | void AsyncChannel::close() |
98 | { |
99 | if (_thread.isRunning()) |
100 | { |
101 | while (!_queue.empty()) Thread::sleep(100); |
102 | |
103 | do |
104 | { |
105 | _queue.wakeUpAll(); |
106 | } |
107 | while (!_thread.tryJoin(100)); |
108 | } |
109 | } |
110 | |
111 | |
112 | void AsyncChannel::log(const Message& msg) |
113 | { |
114 | open(); |
115 | |
116 | _queue.enqueueNotification(new MessageNotification(msg)); |
117 | } |
118 | |
119 | |
120 | void AsyncChannel::setProperty(const std::string& name, const std::string& value) |
121 | { |
122 | if (name == "channel") |
123 | setChannel(LoggingRegistry::defaultRegistry().channelForName(value)); |
124 | else if (name == "priority") |
125 | setPriority(value); |
126 | else |
127 | Channel::setProperty(name, value); |
128 | } |
129 | |
130 | |
131 | void AsyncChannel::run() |
132 | { |
133 | AutoPtr<Notification> nf = _queue.waitDequeueNotification(); |
134 | while (nf) |
135 | { |
136 | MessageNotification* pNf = dynamic_cast<MessageNotification*>(nf.get()); |
137 | { |
138 | FastMutex::ScopedLock lock(_channelMutex); |
139 | |
140 | if (pNf && _pChannel) _pChannel->log(pNf->message()); |
141 | } |
142 | nf = _queue.waitDequeueNotification(); |
143 | } |
144 | } |
145 | |
146 | |
147 | void AsyncChannel::setPriority(const std::string& value) |
148 | { |
149 | Thread::Priority prio = Thread::PRIO_NORMAL; |
150 | |
151 | if (value == "lowest") |
152 | prio = Thread::PRIO_LOWEST; |
153 | else if (value == "low") |
154 | prio = Thread::PRIO_LOW; |
155 | else if (value == "normal") |
156 | prio = Thread::PRIO_NORMAL; |
157 | else if (value == "high") |
158 | prio = Thread::PRIO_HIGH; |
159 | else if (value == "highest") |
160 | prio = Thread::PRIO_HIGHEST; |
161 | else |
162 | throw InvalidArgumentException("thread priority", value); |
163 | |
164 | _thread.setPriority(prio); |
165 | } |
166 | |
167 | |
168 | } // namespace Poco |
169 |