SocketMonitor.hxx 3.5 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2021 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_SOCKET_MONITOR_HXX
#define MPD_SOCKET_MONITOR_HXX

23
#include "PollGroup.hxx"
24
#include "net/SocketDescriptor.hxx"
25

26
#include <cassert>
27
#include <cstddef>
28 29
#include <type_traits>

30 31
class EventLoop;

32 33 34 35 36
/**
 * Monitor events on a socket.  Call Schedule() to announce events
 * you're interested in, or Cancel() to cancel your subscription.  The
 * #EventLoop will invoke virtual method OnSocketReady() as soon as
 * any of the subscribed events are ready.
37
 *
38 39 40
 * This class does not feel responsible for closing the socket.  Call
 * Close() to do it manually.
 *
41 42 43
 * This class is not thread-safe, all methods must be called from the
 * thread that runs the #EventLoop, except where explicitly documented
 * as thread-safe.
44
 */
45
class SocketMonitor {
46
	SocketDescriptor fd = SocketDescriptor::Undefined();
47
	EventLoop &loop;
48 49 50 51

	/**
	 * A bit mask of events that is currently registered in the EventLoop.
	 */
52
	unsigned scheduled_flags = 0;
53 54

public:
55 56 57 58
	static constexpr unsigned READ = PollGroup::READ;
	static constexpr unsigned WRITE = PollGroup::WRITE;
	static constexpr unsigned ERROR = PollGroup::ERROR;
	static constexpr unsigned HANGUP = PollGroup::HANGUP;
59

60 61 62 63 64 65
	/**
	 * These flags are always reported by epoll_wait() and don't
	 * need to be registered with epoll_ctl().
	 */
	static constexpr unsigned IMPLICIT_FLAGS = ERROR|HANGUP;

66 67
	typedef std::make_signed<size_t>::type ssize_t;

68
	explicit SocketMonitor(EventLoop &_loop) noexcept
69
		:loop(_loop) {}
70

71
	SocketMonitor(SocketDescriptor _fd, EventLoop &_loop) noexcept
72
		:fd(_fd), loop(_loop) {}
73

74
	~SocketMonitor() noexcept;
75

76
	auto &GetEventLoop() const noexcept {
77 78 79
		return loop;
	}

80
	bool IsDefined() const noexcept {
81
		return fd.IsDefined();
82 83
	}

84
	SocketDescriptor GetSocket() const noexcept {
85 86 87 88 89
		assert(IsDefined());

		return fd;
	}

90
	void Open(SocketDescriptor _fd) noexcept;
91

92 93
	/**
	 * "Steal" the socket descriptor.  This abandons the socket
94
	 * and returns it.
95
	 */
96
	SocketDescriptor Steal() noexcept;
97

98
	void Close() noexcept;
99

100
	unsigned GetScheduledFlags() const noexcept {
101 102
		assert(IsDefined());

103
		return scheduled_flags;
104 105
	}

106 107 108 109 110
	/**
	 * @return true on success, false on error (with errno set if
	 * USE_EPOLL is defined)
	 */
	bool Schedule(unsigned flags) noexcept;
111

112
	void Cancel() noexcept {
113
		Schedule(0);
114 115
	}

116
	bool ScheduleRead() noexcept {
117
		return Schedule(GetScheduledFlags() | READ);
118 119
	}

120 121
	bool ScheduleWrite() noexcept {
		return Schedule(GetScheduledFlags() | WRITE);
122 123
	}

124
	void CancelRead() noexcept {
125
		Schedule(GetScheduledFlags() & ~READ);
126 127
	}

128
	void CancelWrite() noexcept {
129
		Schedule(GetScheduledFlags() & ~WRITE);
130 131 132
	}

protected:
133 134 135
	/**
	 * @return false if the socket has been closed
	 */
136
	virtual bool OnSocketReady(unsigned flags) noexcept = 0;
137 138

public:
139
	void Dispatch(unsigned flags) noexcept;
140 141 142
};

#endif