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::Ptr pChannel, Thread::Priority prio): |
50 | _pChannel(pChannel), |
51 | _thread("AsyncChannel") |
52 | { |
53 | _thread.setPriority(prio); |
54 | } |
55 | |
56 | |
57 | AsyncChannel::~AsyncChannel() |
58 | { |
59 | try |
60 | { |
61 | close(); |
62 | } |
63 | catch (...) |
64 | { |
65 | poco_unexpected(); |
66 | } |
67 | } |
68 | |
69 | |
70 | void AsyncChannel::setChannel(Channel::Ptr pChannel) |
71 | { |
72 | FastMutex::ScopedLock lock(_channelMutex); |
73 | |
74 | _pChannel = pChannel; |
75 | } |
76 | |
77 | |
78 | Channel::Ptr AsyncChannel::getChannel() const |
79 | { |
80 | return _pChannel; |
81 | } |
82 | |
83 | |
84 | void AsyncChannel::open() |
85 | { |
86 | FastMutex::ScopedLock lock(_threadMutex); |
87 | |
88 | if (!_thread.isRunning()) _thread.start(*this); |
89 | } |
90 | |
91 | |
92 | void AsyncChannel::close() |
93 | { |
94 | if (_thread.isRunning()) |
95 | { |
96 | while (!_queue.empty()) Thread::sleep(100); |
97 | |
98 | do |
99 | { |
100 | _queue.wakeUpAll(); |
101 | } |
102 | while (!_thread.tryJoin(100)); |
103 | } |
104 | } |
105 | |
106 | |
107 | void AsyncChannel::log(const Message& msg) |
108 | { |
109 | open(); |
110 | |
111 | _queue.enqueueNotification(new MessageNotification(msg)); |
112 | } |
113 | |
114 | |
115 | void AsyncChannel::setProperty(const std::string& name, const std::string& value) |
116 | { |
117 | if (name == "channel") |
118 | setChannel(LoggingRegistry::defaultRegistry().channelForName(value)); |
119 | else if (name == "priority") |
120 | setPriority(value); |
121 | else |
122 | Channel::setProperty(name, value); |
123 | } |
124 | |
125 | |
126 | void AsyncChannel::run() |
127 | { |
128 | AutoPtr<Notification> nf = _queue.waitDequeueNotification(); |
129 | while (nf) |
130 | { |
131 | MessageNotification* pNf = dynamic_cast<MessageNotification*>(nf.get()); |
132 | { |
133 | FastMutex::ScopedLock lock(_channelMutex); |
134 | |
135 | if (pNf && _pChannel) _pChannel->log(pNf->message()); |
136 | } |
137 | nf = _queue.waitDequeueNotification(); |
138 | } |
139 | } |
140 | |
141 | |
142 | void AsyncChannel::setPriority(const std::string& value) |
143 | { |
144 | Thread::Priority prio = Thread::PRIO_NORMAL; |
145 | |
146 | if (value == "lowest") |
147 | prio = Thread::PRIO_LOWEST; |
148 | else if (value == "low") |
149 | prio = Thread::PRIO_LOW; |
150 | else if (value == "normal") |
151 | prio = Thread::PRIO_NORMAL; |
152 | else if (value == "high") |
153 | prio = Thread::PRIO_HIGH; |
154 | else if (value == "highest") |
155 | prio = Thread::PRIO_HIGHEST; |
156 | else |
157 | throw InvalidArgumentException("thread priority", value); |
158 | |
159 | _thread.setPriority(prio); |
160 | } |
161 | |
162 | |
163 | } // namespace Poco |
164 |