blob: bd27000dc9091e735b73508c4918230d712e56f9 [file] [log] [blame]
#ifndef ANDROID_PDX_SERVICE_DISPATCHER_H_
#define ANDROID_PDX_SERVICE_DISPATCHER_H_
#include <memory>
#include <mutex>
#include <unordered_map>
#include <vector>
#include <pdx/file_handle.h>
namespace android {
namespace pdx {
class Service;
/*
* ServiceDispatcher manages a list of Service instances and handles message
* reception and dispatch to the services. This makes repetitive dispatch tasks
* easier to implement.
*/
class ServiceDispatcher {
public:
// Get a new instance of ServiceDispatcher, or return nullptr if init failed.
static std::unique_ptr<ServiceDispatcher> Create();
~ServiceDispatcher();
/*
* Adds a service to the list of services handled by this dispatcher. This
* will fail if any threads are blocked waiting for messages in this
* dispatcher.
*
* Returns 0 on success; -EEXIST if the service was already added.
*/
int AddService(const std::shared_ptr<Service>& service);
/*
* Removes a service from this dispatcher. This will fail if any threads are
* blocked waiting for messages in this dispatcher.
*
* Returns 0 on success; -ENOENT if the service was not previously added;
* -EBUSY if there are threads in the dispatcher.
*/
int RemoveService(const std::shared_ptr<Service>& service);
/*
* Receive and dispatch one set of messages. Multiple threads may enter this
* method to create an implicit thread pool, as described for
* enterDispatchLoop() below, however this method exits after one dispatch
* cycle, requiring an external loop. This is useful when other work needs
* to be done in the service dispatch loop.
*/
int ReceiveAndDispatch();
/*
* Same as above with timeout in milliseconds. A negative value means
* infinite timeout, while a value of 0 means return immediately if no
* messages are available to receive.
*/
int ReceiveAndDispatch(int timeout);
/*
* Receive and dispatch messages until canceled. When more than one thread
* enters this method it creates an implicit thread pool to dispatch messages.
* Explicit thread pools may be created by using a single dispatch thread that
* hands Message instances (via move assignment) over to a queue of threads
* (or perhaps one of several) to handle.
*/
int EnterDispatchLoop();
/*
* Sets the canceled state of the dispatcher. When canceled is true, any
* threads blocked waiting for messages will return. This method waits until
* all dispatch threads have exited the dispatcher.
*/
void SetCanceled(bool cancel);
/*
* Gets the canceled state of the dispatcher.
*/
bool IsCanceled() const;
private:
ServiceDispatcher();
// Internal thread accounting.
int ThreadEnter();
void ThreadExit();
std::mutex mutex_;
std::condition_variable condition_;
std::atomic<bool> canceled_{false};
std::vector<std::shared_ptr<Service>> services_;
int thread_count_ = 0;
LocalHandle event_fd_;
LocalHandle epoll_fd_;
ServiceDispatcher(const ServiceDispatcher&) = delete;
void operator=(const ServiceDispatcher&) = delete;
};
} // namespace pdx
} // namespace android
#endif // ANDROID_PDX_SERVICE_DISPATCHER_H_