1 | // |
---|
2 | // LoggerWorker.hpp |
---|
3 | // I2PLauncher |
---|
4 | // |
---|
5 | // Created by Mikal Villa on 27/09/2018. |
---|
6 | // Copyright © 2018 The I2P Project. All rights reserved. |
---|
7 | // Imported/Refactored from earlier C++ project of Meeh |
---|
8 | // |
---|
9 | |
---|
10 | #ifndef LoggerWorker_hpp |
---|
11 | #define LoggerWorker_hpp |
---|
12 | |
---|
13 | #ifdef __cplusplus |
---|
14 | |
---|
15 | #include <memory> |
---|
16 | #include <thread> |
---|
17 | #include <mutex> |
---|
18 | #include <future> |
---|
19 | #include <string> |
---|
20 | #include <condition_variable> |
---|
21 | #include <functional> |
---|
22 | |
---|
23 | #include "include/sharedqueue.h" |
---|
24 | #include "Logger.h" |
---|
25 | |
---|
26 | struct SharedLogWorkerImpl; |
---|
27 | |
---|
28 | |
---|
29 | namespace MeehLog { |
---|
30 | typedef std::function<void()> Callback; |
---|
31 | |
---|
32 | class Active { |
---|
33 | private: |
---|
34 | Active(const Active&); |
---|
35 | Active& operator=(const Active&); |
---|
36 | Active(); // Construction ONLY through factory createActive(); |
---|
37 | void doDone(){mDone = true;} |
---|
38 | void run(); |
---|
39 | |
---|
40 | shared_queue<Callback> mMq; |
---|
41 | std::thread mThd; |
---|
42 | bool mDone; // finished flag to be set through msg queue by ~Active |
---|
43 | |
---|
44 | |
---|
45 | public: |
---|
46 | virtual ~Active(); |
---|
47 | void send(Callback msg_); |
---|
48 | static std::unique_ptr<Active> createActive(); // Factory: safe construction & thread start |
---|
49 | }; |
---|
50 | |
---|
51 | |
---|
52 | |
---|
53 | // A straightforward technique to move around packaged_tasks. |
---|
54 | // Instances of std::packaged_task are MoveConstructible and MoveAssignable, but |
---|
55 | // not CopyConstructible or CopyAssignable. To put them in a std container they need |
---|
56 | // to be wrapped and their internals "moved" when tried to be copied. |
---|
57 | template<typename Moveable> |
---|
58 | struct MoveOnCopy { |
---|
59 | mutable Moveable _move_only; |
---|
60 | |
---|
61 | explicit MoveOnCopy(Moveable&& m) : _move_only(std::move(m)) {} |
---|
62 | MoveOnCopy(MoveOnCopy const& t) : _move_only(std::move(t._move_only)) {} |
---|
63 | MoveOnCopy(MoveOnCopy&& t) : _move_only(std::move(t._move_only)) {} |
---|
64 | |
---|
65 | MoveOnCopy& operator=(MoveOnCopy const& other) { |
---|
66 | _move_only = std::move(other._move_only); |
---|
67 | return *this; |
---|
68 | } |
---|
69 | |
---|
70 | MoveOnCopy& operator=(MoveOnCopy&& other) { |
---|
71 | _move_only = std::move(other._move_only); |
---|
72 | return *this; |
---|
73 | } |
---|
74 | |
---|
75 | void operator()() { _move_only(); } |
---|
76 | Moveable& get() { return _move_only; } |
---|
77 | Moveable release() { return std::move(_move_only); } |
---|
78 | }; |
---|
79 | |
---|
80 | // Generic helper function to avoid repeating the steps for managing |
---|
81 | // asynchronous task job (by active object) that returns a future results |
---|
82 | // could of course be made even more generic if done more in the way of |
---|
83 | // std::async, ref: http://en.cppreference.com/w/cpp/thread/async |
---|
84 | // |
---|
85 | // Example usage: |
---|
86 | // std::unique_ptr<Active> bgWorker{Active::createActive()}; |
---|
87 | // ... |
---|
88 | // auto msg_call=[=](){return ("Hello from the Background");}; |
---|
89 | // auto future_msg = g2::spawn_task(msg_lambda, bgWorker.get()); |
---|
90 | |
---|
91 | template <typename Func> |
---|
92 | std::future<typename std::result_of<Func()>::type> spawn_task(Func func, Active* worker) { |
---|
93 | typedef typename std::result_of<Func()>::type result_type; |
---|
94 | typedef std::packaged_task<result_type()> task_type; |
---|
95 | task_type task(std::move(func)); |
---|
96 | std::future<result_type> result = task.get_future(); |
---|
97 | |
---|
98 | worker->send(MoveOnCopy<task_type>(std::move(task))); |
---|
99 | return std::move(result); |
---|
100 | } |
---|
101 | } |
---|
102 | |
---|
103 | class SharedLogWorker { |
---|
104 | public: |
---|
105 | /** |
---|
106 | * \param log_prefix is the 'name' of the binary, this give the log name 'LOG-'name'-... |
---|
107 | * \param log_directory gives the directory to put the log files */ |
---|
108 | SharedLogWorker(const std::string& log_prefix, const std::string& log_directory); |
---|
109 | virtual ~SharedLogWorker(); |
---|
110 | |
---|
111 | /// pushes in background thread (asynchronously) input messages to log file |
---|
112 | void save(const MeehLog::internal::LogEntry& entry); |
---|
113 | |
---|
114 | /// Will push a fatal message on the queue, this is the last message to be processed |
---|
115 | /// this way it's ensured that all existing entries were flushed before 'fatal' |
---|
116 | /// Will abort the application! |
---|
117 | void fatal(MeehLog::internal::FatalMessage fatal_message); |
---|
118 | |
---|
119 | /// Attempt to change the current log file to another name/location. |
---|
120 | /// returns filename with full path if successful, else empty string |
---|
121 | std::future<std::string> changeLogFile(const std::string& log_directory); |
---|
122 | |
---|
123 | /// Does an independent action in FIFO order, compared to the normal LOG statements |
---|
124 | /// Example: auto threadID = [] { std::cout << "thread id: " << std::this_thread::get_id() << std::endl; }; |
---|
125 | /// auto call = logger.genericAsyncCall(threadID); |
---|
126 | /// // this will print out the thread id of the background worker |
---|
127 | std::future<void> genericAsyncCall(std::function<void()> f); |
---|
128 | |
---|
129 | /// Probably only needed for unit-testing or specific log management post logging |
---|
130 | /// request to get log name is processed in FIFO order just like any other background job. |
---|
131 | std::future<std::string> logFileName(); |
---|
132 | |
---|
133 | private: |
---|
134 | std::unique_ptr<SharedLogWorkerImpl> pimpl; |
---|
135 | const std::string logFileWithPath; |
---|
136 | |
---|
137 | SharedLogWorker(const SharedLogWorker&); |
---|
138 | SharedLogWorker& operator=(const SharedLogWorker&); |
---|
139 | }; |
---|
140 | |
---|
141 | #endif // __cplusplus |
---|
142 | |
---|
143 | #endif /* LoggerWorker_hpp */ |
---|