Line data Source code
1 : /*
2 : * LocalStream.cxx
3 : * ERS
4 : *
5 : * Created by Serguei Kolos on 21.01.05.
6 : * Copyright 2005 CERN. All rights reserved.
7 : *
8 : */
9 : #include <ers/LocalStream.hpp>
10 : #include <ers/StreamManager.hpp>
11 : #include <ers/internal/SingletonCreator.hpp>
12 :
13 : /** This method returns the singleton instance.
14 : * It should be used for every operation on the factory.
15 : * \return a reference to the singleton instance
16 : */
17 : ers::LocalStream &
18 39 : ers::LocalStream::instance()
19 : {
20 : /**Singleton instance
21 : */
22 39 : static ers::LocalStream * instance = ers::SingletonCreator<ers::LocalStream>::create();
23 :
24 39 : return *instance;
25 : }
26 :
27 : /** Private constructor - can not be called by user code, use the \c instance() method instead
28 : * \see instance()
29 : */
30 13 : ers::LocalStream::LocalStream( )
31 13 : : m_terminated( false )
32 13 : { }
33 :
34 0 : ers::LocalStream::~LocalStream( )
35 : {
36 0 : remove_issue_catcher();
37 0 : }
38 :
39 : void
40 0 : ers::LocalStream::remove_issue_catcher( )
41 : {
42 0 : std::unique_ptr<std::thread> catcher;
43 0 : {
44 0 : std::unique_lock lock( m_mutex );
45 0 : if ( !m_issue_catcher_thread.get() )
46 : {
47 0 : return ;
48 : }
49 0 : m_terminated = true;
50 0 : m_condition.notify_one();
51 0 : catcher.swap(m_issue_catcher_thread);
52 0 : }
53 :
54 0 : catcher -> join();
55 0 : }
56 :
57 : void
58 0 : ers::LocalStream::thread_wrapper()
59 : {
60 0 : std::unique_lock lock( m_mutex );
61 0 : m_catcher_thread_id = std::this_thread::get_id();
62 0 : while( !m_terminated )
63 : {
64 0 : m_condition.wait( lock, [this](){return !m_issues.empty() || m_terminated;} );
65 :
66 0 : while( !m_terminated && !m_issues.empty() )
67 : {
68 0 : ers::Issue * issue = m_issues.front();
69 0 : m_issues.pop();
70 :
71 0 : lock.unlock();
72 0 : m_issue_catcher( *issue );
73 0 : delete issue;
74 0 : lock.lock();
75 : }
76 : }
77 0 : m_catcher_thread_id = {};
78 0 : m_terminated = false;
79 0 : }
80 :
81 : ers::IssueCatcherHandler *
82 0 : ers::LocalStream::set_issue_catcher( const std::function<void ( const ers::Issue & )> & catcher )
83 : {
84 0 : std::unique_lock lock( m_mutex );
85 0 : if ( m_issue_catcher_thread.get() )
86 : {
87 0 : throw ers::IssueCatcherAlreadySet( ERS_HERE );
88 : }
89 0 : m_issue_catcher = catcher;
90 0 : m_issue_catcher_thread.reset( new std::thread( std::bind( &ers::LocalStream::thread_wrapper, this ) ) );
91 :
92 0 : return new ers::IssueCatcherHandler;
93 0 : }
94 :
95 : void
96 39 : ers::LocalStream::report_issue( ers::severity type, const ers::Issue & issue )
97 : {
98 39 : if ( m_issue_catcher_thread.get() && m_catcher_thread_id != std::this_thread::get_id() )
99 : {
100 0 : ers::Issue * clone = issue.clone();
101 0 : clone->set_severity( type );
102 0 : std::unique_lock lock( m_mutex );
103 0 : m_issues.push( clone );
104 0 : m_condition.notify_one();
105 0 : }
106 : else
107 : {
108 39 : StreamManager::instance().report_issue( type, issue );
109 : }
110 39 : }
111 :
112 : void
113 27 : ers::LocalStream::error( const ers::Issue & issue )
114 : {
115 27 : report_issue( ers::Error, issue );
116 27 : }
117 :
118 : void
119 0 : ers::LocalStream::fatal( const ers::Issue & issue )
120 : {
121 0 : report_issue( ers::Fatal, issue );
122 0 : }
123 :
124 : void
125 12 : ers::LocalStream::warning( const ers::Issue & issue )
126 : {
127 12 : report_issue( ers::Warning, issue );
128 12 : }
|