Ticket #7608: hang_log.cpp

File hang_log.cpp, 3.5 KB (added by Acer Yang <yangacer@…>, 10 years ago)

Reproduce the bug.

Line 
1#include <boost/asio.hpp>
2#include <boost/thread/thread.hpp>
3#include <boost/bind.hpp>
4#include <boost/date_time/posix_time/posix_time.hpp>
5#include <boost/noncopyable.hpp>
6#include <boost/scoped_ptr.hpp>
7#include <fstream>
8#include <sstream>
9#include <string>
10
11namespace services {
12
13// ----------------- io_service -------------------
14class logger_service
15 : public boost::asio::io_service::service
16{
17public:
18 static boost::asio::io_service::id id;
19
20 struct logger_impl
21 {
22 explicit logger_impl(const std::string& ident) : identifier(ident) {}
23 std::string identifier;
24 };
25
26 typedef logger_impl* impl_type;
27
28 logger_service(boost::asio::io_service& io_service)
29 : boost::asio::io_service::service(io_service),
30 work_io_service_(),
31 work_(new boost::asio::io_service::work(work_io_service_)),
32 work_thread_(new boost::thread(
33 boost::bind(&boost::asio::io_service::run, &work_io_service_)))
34 {}
35
36 ~logger_service()
37 {
38 work_.reset();
39 if (work_thread_)
40 work_thread_->join();
41 }
42
43
44 void shutdown_service()
45 {}
46
47 impl_type null() const
48 {
49 return 0;
50 }
51
52 void create(impl_type& impl, const std::string& identifier)
53 {
54 impl = new logger_impl(identifier);
55 }
56
57 void destroy(impl_type& impl)
58 {
59 delete impl;
60 impl = null();
61 }
62
63 void use_file(impl_type& /*impl*/, const std::string& file)
64 {
65 work_io_service_.post(boost::bind(
66 &logger_service::use_file_impl, this, file));
67 }
68
69 void log(impl_type& impl, const std::string& message)
70 {
71 std::ostringstream os;
72 os << impl->identifier << ": " << message;
73
74 work_io_service_.post(boost::bind(
75 &logger_service::log_impl, this, os.str()));
76 }
77
78private:
79
80 void use_file_impl(const std::string& file)
81 {
82 ofstream_.close();
83 ofstream_.clear();
84 ofstream_.open(file.c_str());
85 }
86
87 void log_impl(const std::string& text)
88 {
89 ofstream_ << text << std::endl;
90 }
91
92 boost::asio::io_service work_io_service_;
93 boost::scoped_ptr<boost::asio::io_service::work> work_;
94 boost::scoped_ptr<boost::thread> work_thread_;
95 std::ofstream ofstream_;
96};
97
98boost::asio::io_service::id logger_service::id;
99
100// ------------- io_object ------------
101template <typename Service>
102class basic_logger
103 : private boost::noncopyable
104{
105public:
106 typedef Service service_type;
107 typedef typename service_type::impl_type impl_type;
108
109 explicit basic_logger(boost::asio::io_service& io_service,
110 const std::string& identifier)
111 : service_(boost::asio::use_service<Service>(io_service)),
112 impl_(service_.null())
113 { service_.create(impl_, identifier); }
114
115 ~basic_logger()
116 { service_.destroy(impl_); }
117
118 boost::asio::io_service& get_io_service()
119 {
120 return service_.get_io_service();
121 }
122
123 void use_file(const std::string& file)
124 {
125 service_.use_file(impl_, file);
126 }
127
128 void log(const std::string& message)
129 {
130 service_.log(impl_, message);
131 }
132
133private:
134 service_type& service_;
135 impl_type impl_;
136};
137
138
139} // namespace services
140
141typedef services::basic_logger<services::logger_service> logger;
142
143int main()
144{
145 boost::asio::io_service io_service;
146 boost::asio::signal_set signals(io_service);
147 logger l(io_service, "test");
148
149 signals.add(SIGINT);
150 signals.async_wait(boost::bind(&boost::asio::io_service::stop, &io_service));
151
152 l.use_file("test.log");
153 l.log("do log");
154
155
156 io_service.run();
157 return 0;
158}