1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_PDX_SERVICE_DISPATCHER_H_ 2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_PDX_SERVICE_DISPATCHER_H_ 3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <memory> 55a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko#include <mutex> 65a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko#include <unordered_map> 75a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko#include <vector> 85a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 95a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko#include <pdx/file_handle.h> 10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android { 12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx { 13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass Service; 15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko/* 17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * ServiceDispatcher manages a list of Service instances and handles message 18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * reception and dispatch to the services. This makes repetitive dispatch tasks 19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * easier to implement. 20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ServiceDispatcher { 22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public: 235a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko // Get a new instance of ServiceDispatcher, or return nullptr if init failed. 245a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko static std::unique_ptr<ServiceDispatcher> Create(); 255a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 265a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko ~ServiceDispatcher(); 27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko /* 29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Adds a service to the list of services handled by this dispatcher. This 30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * will fail if any threads are blocked waiting for messages in this 31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * dispatcher. 32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * 33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Returns 0 on success; -EEXIST if the service was already added. 34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 355a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko int AddService(const std::shared_ptr<Service>& service); 36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko /* 38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Removes a service from this dispatcher. This will fail if any threads are 39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * blocked waiting for messages in this dispatcher. 40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * 41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Returns 0 on success; -ENOENT if the service was not previously added; 42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * -EBUSY if there are threads in the dispatcher. 43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 445a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko int RemoveService(const std::shared_ptr<Service>& service); 45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko /* 47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Receive and dispatch one set of messages. Multiple threads may enter this 48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * method to create an implicit thread pool, as described for 49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * enterDispatchLoop() below, however this method exits after one dispatch 50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * cycle, requiring an external loop. This is useful when other work needs 51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * to be done in the service dispatch loop. 52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 535a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko int ReceiveAndDispatch(); 54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko /* 56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Same as above with timeout in milliseconds. A negative value means 57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * infinite timeout, while a value of 0 means return immediately if no 58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * messages are available to receive. 59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 605a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko int ReceiveAndDispatch(int timeout); 61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko /* 63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Receive and dispatch messages until canceled. When more than one thread 64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * enters this method it creates an implicit thread pool to dispatch messages. 65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Explicit thread pools may be created by using a single dispatch thread that 66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * hands Message instances (via move assignment) over to a queue of threads 67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * (or perhaps one of several) to handle. 68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 695a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko int EnterDispatchLoop(); 70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko /* 72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Sets the canceled state of the dispatcher. When canceled is true, any 73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * threads blocked waiting for messages will return. This method waits until 74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * all dispatch threads have exited the dispatcher. 75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 765a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko void SetCanceled(bool cancel); 77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko /* 79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko * Gets the canceled state of the dispatcher. 80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko */ 815a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko bool IsCanceled() const; 825a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 835a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko private: 845a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko ServiceDispatcher(); 855a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 865a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko // Internal thread accounting. 875a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko int ThreadEnter(); 885a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko void ThreadExit(); 895a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 905a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko std::mutex mutex_; 915a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko std::condition_variable condition_; 925a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko std::atomic<bool> canceled_{false}; 935a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 945a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko std::vector<std::shared_ptr<Service>> services_; 955a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 965a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko int thread_count_ = 0; 975a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko LocalHandle event_fd_; 985a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko LocalHandle epoll_fd_; 995a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko 1005a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko ServiceDispatcher(const ServiceDispatcher&) = delete; 1015a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko void operator=(const ServiceDispatcher&) = delete; 102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}; 103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace pdx 105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko} // namespace android 106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko 107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif // ANDROID_PDX_SERVICE_DISPATCHER_H_ 108