00001 #ifndef toast_log_hpp_INCLUDED
00002 #define toast_log_hpp_INCLUDED
00003
00004 #include <toast/concept_check.hpp>
00005
00006 #include <toast/log/verbosity_policies.hpp>
00007 #include <toast/log/output_policies.hpp>
00008 #include <toast/log/thread_policies.hpp>
00009 #include <toast/log_handle.hpp>
00010
00011 #include <boost/utility/enable_if.hpp>
00012 #include <boost/type_traits/is_base_of.hpp>
00013
00021 namespace toast {
00022
00023 template <typename VerbosityPolicy,
00024 typename OutputPolicy,
00025 typename ThreadPolicy>
00026 class logger;
00027
00028 namespace detail {
00029
00030 template<class logger_t, class Enable = void>
00031 class consume_if_possible;
00032
00033 template<class logger_t>
00034 class consume_if_possible<logger_t, typename boost::enable_if< boost::is_base_of<log::ConsumingOutputPolicy, logger_t> >::type >
00035 {
00036 public:
00037 static typename logger_t::char_type* do_it(logger_t& target,
00038 typename logger_t::char_type *m,
00039 log::severity severity)
00040 {
00041 static_cast<typename logger_t::output_policy&>(target).consume_message(m, severity);
00042 return NULL;
00043 }
00044
00045 private:
00046 consume_if_possible();
00047 };
00048
00049 template<class logger_t>
00050 class consume_if_possible<logger_t, typename boost::disable_if< boost::is_base_of<log::ConsumingOutputPolicy, logger_t> >::type >
00051 {
00052 public:
00053 static typename logger_t::char_type* do_it(logger_t& target,
00054 typename logger_t::char_type* m,
00055 log::severity severity)
00056 {
00057 static_cast<typename logger_t::output_policy&>(target).message(m, severity);
00058 return m;
00059 }
00060
00061 private:
00062 consume_if_possible();
00063 };
00064
00065 }
00066
00087 template <typename VerbosityPolicy = log::check_verbosity,
00088 typename OutputPolicy = log::to_stderr_buffered<>,
00089 typename ThreadPolicy = log::neutral>
00090 class logger
00091 : public VerbosityPolicy,
00092 public OutputPolicy,
00093 public ThreadPolicy
00094 {
00095 TOAST_CLASS_REQUIRE(VerbosityPolicy, toast::log, VerbosityPolicyConcept);
00096 TOAST_CLASS_REQUIRE(OutputPolicy, toast::log, OutputPolicyConcept);
00097 TOAST_CLASS_REQUIRE(ThreadPolicy, toast::log, ThreadPolicyConcept);
00098
00099 public:
00100
00106 typedef typename ThreadPolicy::scoped_lock scoped_lock;
00107
00108 typedef typename OutputPolicy::char_type char_type;
00109
00110 typedef OutputPolicy output_policy;
00111
00112 typedef logger this_type;
00113
00120 void message(char_type const *m, log::severity severity = log::DEFAULT) {
00121 message_hook(m, severity);
00122 }
00123
00130 template <typename Traits, typename Alloc>
00131 void message(std::basic_string<char_type, Traits, Alloc> const &m,
00132 log::severity severity = log::DEFAULT) {
00133 message_hook(m.c_str(), severity);
00134 }
00135
00144 void consume_message(char_type *m,
00145 log::severity severity = log::DEFAULT) {
00146 consume_message_hook(m, severity);
00147 }
00148
00158 void forced_message(char_type const *m,
00159 log::severity severity = log::DEFAULT) {
00160 forced_message_hook(m, severity);
00161 }
00162
00175 void consume_forced_message(char_type const *m,
00176 log::severity severity = log::DEFAULT) {
00177 consume_forced_message_hook(m, severity);
00178 }
00179
00189 template <typename Traits, typename Alloc>
00190 void forced_message(std::basic_string<char_type, Traits, Alloc> const &m,
00191 log::severity severity = log::DEFAULT) {
00192 forced_message_hook(m.c_str(), severity);
00193 }
00194 private:
00195 void message_hook(char_type const *m, log::severity severity) {
00196 scoped_lock guard(*this);
00197 if(VerbosityPolicy::check(severity)) {
00198 OutputPolicy::message(m, severity);
00199 }
00200 }
00201
00202 char_type* consume_message_hook(char_type *m, log::severity severity) {
00203 scoped_lock guard(*this);
00204 if(VerbosityPolicy::check(severity)) {
00205 return detail::consume_if_possible<this_type>::do_it(*this, m, severity);
00206 }
00207
00208 return m;
00209 }
00210
00211 void forced_message_hook(char_type const *m, log::severity severity) {
00212 scoped_lock guard(*this);
00213 OutputPolicy::message(m, severity);
00214 }
00215
00216 char_type* consume_forced_message_hook(char_type *m, log::severity severity) {
00217 scoped_lock guard(*this);
00218 return detail::consume_if_possible<this_type>::do_it(*this, m, severity);
00219 }
00220
00221
00222 friend class basic_log_handle<char_type>;
00223 };
00224
00227 namespace log {
00228
00229 using ::toast::logger;
00230 }
00231 }
00232
00233
00327 #endif // toast_log_hpp_INCLUDED
00328