]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // logger_service.hpp | |
3 | // ~~~~~~~~~~~~~~~~~~ | |
4 | // | |
b32b8144 | 5 | // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #ifndef SERVICES_LOGGER_SERVICE_HPP | |
12 | #define SERVICES_LOGGER_SERVICE_HPP | |
13 | ||
14 | #include <boost/asio.hpp> | |
15 | #include <boost/thread/thread.hpp> | |
16 | #include <boost/bind.hpp> | |
17 | #include <boost/date_time/posix_time/posix_time.hpp> | |
18 | #include <boost/noncopyable.hpp> | |
19 | #include <boost/scoped_ptr.hpp> | |
20 | #include <fstream> | |
21 | #include <sstream> | |
22 | #include <string> | |
23 | ||
24 | namespace services { | |
25 | ||
26 | /// Service implementation for the logger. | |
27 | class logger_service | |
b32b8144 | 28 | : public boost::asio::io_context::service |
7c673cae FG |
29 | { |
30 | public: | |
31 | /// The unique service identifier. | |
b32b8144 | 32 | static boost::asio::io_context::id id; |
7c673cae FG |
33 | |
34 | /// The backend implementation of a logger. | |
35 | struct logger_impl | |
36 | { | |
37 | explicit logger_impl(const std::string& ident) : identifier(ident) {} | |
38 | std::string identifier; | |
39 | }; | |
40 | ||
41 | /// The type for an implementation of the logger. | |
42 | typedef logger_impl* impl_type; | |
43 | ||
b32b8144 FG |
44 | /// Constructor creates a thread to run a private io_context. |
45 | logger_service(boost::asio::io_context& io_context) | |
46 | : boost::asio::io_context::service(io_context), | |
47 | work_io_context_(), | |
48 | work_(boost::asio::make_work_guard(work_io_context_)), | |
7c673cae | 49 | work_thread_(new boost::thread( |
b32b8144 | 50 | boost::bind(&boost::asio::io_context::run, &work_io_context_))) |
7c673cae FG |
51 | { |
52 | } | |
53 | ||
b32b8144 | 54 | /// Destructor shuts down the private io_context. |
7c673cae FG |
55 | ~logger_service() |
56 | { | |
b32b8144 FG |
57 | /// Indicate that we have finished with the private io_context. Its |
58 | /// io_context::run() function will exit once all other work has completed. | |
7c673cae FG |
59 | work_.reset(); |
60 | if (work_thread_) | |
61 | work_thread_->join(); | |
62 | } | |
63 | ||
64 | /// Destroy all user-defined handler objects owned by the service. | |
65 | void shutdown_service() | |
66 | { | |
67 | } | |
68 | ||
69 | /// Return a null logger implementation. | |
70 | impl_type null() const | |
71 | { | |
72 | return 0; | |
73 | } | |
74 | ||
75 | /// Create a new logger implementation. | |
76 | void create(impl_type& impl, const std::string& identifier) | |
77 | { | |
78 | impl = new logger_impl(identifier); | |
79 | } | |
80 | ||
81 | /// Destroy a logger implementation. | |
82 | void destroy(impl_type& impl) | |
83 | { | |
84 | delete impl; | |
85 | impl = null(); | |
86 | } | |
87 | ||
88 | /// Set the output file for the logger. The current implementation sets the | |
89 | /// output file for all logger instances, and so the impl parameter is not | |
90 | /// actually needed. It is retained here to illustrate how service functions | |
91 | /// are typically defined. | |
92 | void use_file(impl_type& /*impl*/, const std::string& file) | |
93 | { | |
94 | // Pass the work of opening the file to the background thread. | |
b32b8144 | 95 | boost::asio::post(work_io_context_, boost::bind( |
7c673cae FG |
96 | &logger_service::use_file_impl, this, file)); |
97 | } | |
98 | ||
99 | /// Log a message. | |
100 | void log(impl_type& impl, const std::string& message) | |
101 | { | |
102 | // Format the text to be logged. | |
103 | std::ostringstream os; | |
104 | os << impl->identifier << ": " << message; | |
105 | ||
b32b8144 FG |
106 | // Pass the work of writing to the file to the background thread. |
107 | boost::asio::post(work_io_context_, boost::bind( | |
7c673cae FG |
108 | &logger_service::log_impl, this, os.str())); |
109 | } | |
110 | ||
111 | private: | |
112 | /// Helper function used to open the output file from within the private | |
b32b8144 | 113 | /// io_context's thread. |
7c673cae FG |
114 | void use_file_impl(const std::string& file) |
115 | { | |
116 | ofstream_.close(); | |
117 | ofstream_.clear(); | |
118 | ofstream_.open(file.c_str()); | |
119 | } | |
120 | ||
b32b8144 | 121 | /// Helper function used to log a message from within the private io_context's |
7c673cae FG |
122 | /// thread. |
123 | void log_impl(const std::string& text) | |
124 | { | |
125 | ofstream_ << text << std::endl; | |
126 | } | |
127 | ||
b32b8144 FG |
128 | /// Private io_context used for performing logging operations. |
129 | boost::asio::io_context work_io_context_; | |
7c673cae | 130 | |
b32b8144 FG |
131 | /// Work for the private io_context to perform. If we do not give the |
132 | /// io_context some work to do then the io_context::run() function will exit | |
7c673cae | 133 | /// immediately. |
b32b8144 FG |
134 | boost::asio::executor_work_guard< |
135 | boost::asio::io_context::executor_type> work_; | |
7c673cae | 136 | |
b32b8144 | 137 | /// Thread used for running the work io_context's run loop. |
7c673cae FG |
138 | boost::scoped_ptr<boost::thread> work_thread_; |
139 | ||
140 | /// The file to which log messages will be written. | |
141 | std::ofstream ofstream_; | |
142 | }; | |
143 | ||
144 | } // namespace services | |
145 | ||
146 | #endif // SERVICES_LOGGER_SERVICE_HPP |