1 #ifndef ANDROID_PDX_SERVICE_DISPATCHER_H_
2 #define ANDROID_PDX_SERVICE_DISPATCHER_H_
3 
4 #include <memory>
5 #include <mutex>
6 #include <unordered_map>
7 #include <vector>
8 
9 #include <pdx/file_handle.h>
10 
11 namespace android {
12 namespace pdx {
13 
14 class Service;
15 
16 /*
17  * ServiceDispatcher manages a list of Service instances and handles message
18  * reception and dispatch to the services. This makes repetitive dispatch tasks
19  * easier to implement.
20  */
21 class ServiceDispatcher {
22  public:
23   // Get a new instance of ServiceDispatcher, or return nullptr if init failed.
24   static std::unique_ptr<ServiceDispatcher> Create();
25 
26   ~ServiceDispatcher();
27 
28   /*
29    * Adds a service to the list of services handled by this dispatcher. This
30    * will fail if any threads are blocked waiting for messages in this
31    * dispatcher.
32    *
33    * Returns 0 on success; -EEXIST if the service was already added.
34    */
35   int AddService(const std::shared_ptr<Service>& service);
36 
37   /*
38    * Removes a service from this dispatcher. This will fail if any threads are
39    * blocked waiting for messages in this dispatcher.
40    *
41    * Returns 0 on success; -ENOENT if the service was not previously added;
42    * -EBUSY if there are threads in the dispatcher.
43    */
44   int RemoveService(const std::shared_ptr<Service>& service);
45 
46   /*
47    * Receive and dispatch one set of messages. Multiple threads may enter this
48    * method to create an implicit thread pool, as described for
49    * enterDispatchLoop() below, however this method exits after one dispatch
50    * cycle, requiring an external loop. This is useful when other work needs
51    * to be done in the service dispatch loop.
52    */
53   int ReceiveAndDispatch();
54 
55   /*
56    * Same as above with timeout in milliseconds. A negative value means
57    * infinite timeout, while a value of 0 means return immediately if no
58    * messages are available to receive.
59    */
60   int ReceiveAndDispatch(int timeout);
61 
62   /*
63    * Receive and dispatch messages until canceled. When more than one thread
64    * enters this method it creates an implicit thread pool to dispatch messages.
65    * Explicit thread pools may be created by using a single dispatch thread that
66    * hands Message instances (via move assignment) over to a queue of threads
67    * (or perhaps one of several) to handle.
68    */
69   int EnterDispatchLoop();
70 
71   /*
72    * Sets the canceled state of the dispatcher. When canceled is true, any
73    * threads blocked waiting for messages will return. This method waits until
74    * all dispatch threads have exited the dispatcher.
75    */
76   void SetCanceled(bool cancel);
77 
78   /*
79    * Gets the canceled state of the dispatcher.
80    */
81   bool IsCanceled() const;
82 
83  private:
84   ServiceDispatcher();
85 
86   // Internal thread accounting.
87   int ThreadEnter();
88   void ThreadExit();
89 
90   std::mutex mutex_;
91   std::condition_variable condition_;
92   std::atomic<bool> canceled_{false};
93 
94   std::vector<std::shared_ptr<Service>> services_;
95 
96   int thread_count_ = 0;
97   LocalHandle event_fd_;
98   LocalHandle epoll_fd_;
99 
100   ServiceDispatcher(const ServiceDispatcher&) = delete;
101   void operator=(const ServiceDispatcher&) = delete;
102 };
103 
104 }  // namespace pdx
105 }  // namespace android
106 
107 #endif  // ANDROID_PDX_SERVICE_DISPATCHER_H_
108