source: launchers/macosx/LoggerWorker.hpp @ a367778

Last change on this file since a367778 was 5a0017a, checked in by meeh <meeh@…>, 23 months ago

Mac OSX Launcher: Adding a logger library I wrote a good while ago, refactored it to work with the launcher.

  • Property mode set to 100644
File size: 4.8 KB
Line 
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
26struct SharedLogWorkerImpl;
27
28
29namespace 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
103class SharedLogWorker {
104public:
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 
133private:
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 */
Note: See TracBrowser for help on using the repository browser.