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
24namespace Poco {
25
26
27class MessageNotification: public Notification
28{
29public:
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
44private:
45 Message _msg;
46};
47
48
49AsyncChannel::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
58AsyncChannel::~AsyncChannel()
59{
60 try
61 {
62 close();
63 if (_pChannel) _pChannel->release();
64 }
65 catch (...)
66 {
67 poco_unexpected();
68 }
69}
70
71
72void 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
82Channel* AsyncChannel::getChannel() const
83{
84 return _pChannel;
85}
86
87
88void AsyncChannel::open()
89{
90 FastMutex::ScopedLock lock(_threadMutex);
91
92 if (!_thread.isRunning())
93 _thread.start(*this);
94}
95
96
97void 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
112void AsyncChannel::log(const Message& msg)
113{
114 open();
115
116 _queue.enqueueNotification(new MessageNotification(msg));
117}
118
119
120void 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
131void 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
147void 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