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::Ptr pChannel, Thread::Priority prio):
50 _pChannel(pChannel),
51 _thread("AsyncChannel")
52{
53 _thread.setPriority(prio);
54}
55
56
57AsyncChannel::~AsyncChannel()
58{
59 try
60 {
61 close();
62 }
63 catch (...)
64 {
65 poco_unexpected();
66 }
67}
68
69
70void AsyncChannel::setChannel(Channel::Ptr pChannel)
71{
72 FastMutex::ScopedLock lock(_channelMutex);
73
74 _pChannel = pChannel;
75}
76
77
78Channel::Ptr AsyncChannel::getChannel() const
79{
80 return _pChannel;
81}
82
83
84void AsyncChannel::open()
85{
86 FastMutex::ScopedLock lock(_threadMutex);
87
88 if (!_thread.isRunning()) _thread.start(*this);
89}
90
91
92void 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
107void AsyncChannel::log(const Message& msg)
108{
109 open();
110
111 _queue.enqueueNotification(new MessageNotification(msg));
112}
113
114
115void 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
126void 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
142void 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