1 #ifndef TEST_VENDOR_LIB_ASYNC_MANAGER_H_ 2 #define TEST_VENDOR_LIB_ASYNC_MANAGER_H_ 3 4 #include <time.h> 5 #include <cstdint> 6 #include <map> 7 #include <set> 8 #include "errno.h" 9 #include "stdio.h" 10 11 #include "osi/include/log.h" 12 13 #include <chrono> 14 #include <functional> 15 #include <memory> 16 #include <mutex> 17 #include <utility> 18 19 namespace test_vendor_lib { 20 21 using TaskCallback = std::function<void(void)>; 22 using ReadCallback = std::function<void(int)>; 23 using CriticalCallback = std::function<void(void)>; 24 using AsyncTaskId = uint16_t; 25 constexpr uint16_t kInvalidTaskId = 0; 26 27 // Manages tasks that should be done in the future. It can watch file 28 // descriptors to call a given callback when it is certain that a non-blocking 29 // read is possible or can call a callback at a specific time (aproximately) and 30 // (optionally) repeat the call periodically. 31 // The class is thread safe in the sense that all its member functions can be 32 // called simultaneously from different concurrent threads. The exception to 33 // this rule is the class destructor, which is unsafe to call concurrently with 34 // calls to other class member functions. This exception also has its own 35 // exception: it is safe to destroy the object even if some of its callbacks may 36 // call its member functions, because the destructor will make sure all callback 37 // calling threads are stopped before actually destroying anything. Callbacks 38 // that wait for file descriptor always run on the same thread, so there is no 39 // need of additional synchronization between them. The same applies to task 40 // callbacks since they also run on a thread of their own, however it is 41 // possible for a read callback and a task callback to execute at the same time 42 // (they are garanteed to run in different threads) so synchronization is needed 43 // to access common state (other than the internal state of the AsyncManager 44 // class). While not required, it is strongly recommended to use the 45 // Synchronize(const CriticalCallback&) member function to execute code inside 46 // critical sections. Callbacks passed to this method on the same AsyncManager 47 // object from different threads are granted to *NOT* run concurrently. 48 class AsyncManager { 49 public: 50 // Starts watching a file descriptor in a separate thread. The 51 // on_read_fd_ready_callback() will be asynchronously called when it is 52 // guaranteed that a call to read() on the FD will not block. No promise is 53 // made about when in the future the callback will be called, in particular, 54 // it is perfectly possible to have it called before this function returns. A 55 // return of 0 means success, an error code is returned otherwise. 56 int WatchFdForNonBlockingReads(int file_descriptor, 57 const ReadCallback& on_read_fd_ready_callback); 58 59 // If the fd was not being watched before the call will be ignored. 60 void StopWatchingFileDescriptor(int file_descriptor); 61 62 // Schedules an action to occur in the future. Even if the delay given is not 63 // positive the callback will be called asynchronously. 64 AsyncTaskId ExecAsync(std::chrono::milliseconds delay, 65 const TaskCallback& callback); 66 67 // Schedules an action to occur periodically in the future. If the delay given 68 // is not positive the callback will be asynchronously called once for each 69 // time in the past that it should have been called and then scheduled for 70 // future times. 71 AsyncTaskId ExecAsyncPeriodically(std::chrono::milliseconds delay, 72 std::chrono::milliseconds period, 73 const TaskCallback& callback); 74 75 // Cancels the/every future ocurrence of the action specified by this id. It 76 // is guaranteed that the asociated callback will not be called after this 77 // method returns (it could be called during the execution of the method). 78 // The calling thread may block until the scheduling thread acknowledges the 79 // cancelation. 80 bool CancelAsyncTask(AsyncTaskId async_task_id); 81 82 // Execs the given code in a synchronized manner. It is guaranteed that code 83 // given on (possibly)concurrent calls to this member function on the same 84 // AsyncManager object will never be executed simultaneously. It is the 85 // class's user's resposability to ensure that no calls to Synchronize are 86 // made from inside a CriticalCallback, since that would cause a lock to be 87 // acquired twice with unpredictable results. It is strongly recommended to 88 // have very simple CriticalCallbacks, preferably using lambda expressions. 89 void Synchronize(const CriticalCallback&); 90 91 AsyncManager(); 92 93 ~AsyncManager(); 94 95 private: 96 // Implementation of the FD watching part of AsyncManager, extracted to its 97 // own class for clarity purposes. 98 class AsyncFdWatcher; 99 100 // Implementation of the asynchronous tasks part of AsyncManager, extracted to 101 // its own class for clarity purposes. 102 class AsyncTaskManager; 103 104 AsyncManager(const AsyncManager&) = delete; 105 AsyncManager& operator=(const AsyncManager&) = delete; 106 107 // Kept as pointers because we may want to support reseting either without 108 // destroying the other one 109 std::unique_ptr<AsyncFdWatcher> fdWatcher_p_; 110 std::unique_ptr<AsyncTaskManager> taskManager_p_; 111 112 std::mutex synchronization_mutex_; 113 }; 114 } 115 #endif // TEST_VENDOR_LIB_ASYNC_MANAGER_H_ 116