File: IOHandle.h

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (131 lines) | stat: -rw-r--r-- 3,094 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once
#include "OS/Handle.h"
#include "OS/FdMap.h"
#include "OS/LinuxIO.h"
#include "Utils/Lock.h"
#if defined(POSIX)
#include <poll.h>
#endif

namespace os {

	class ThreadData;
	class IORequest;

	/**
	 * IO handle. Encapsulates an OS specific handle to some kind of synchronizing object that the
	 * OS will notify when IO requests have been completed.
	 *
	 * TODO: We could use epoll on Linux for better performance when using many file descriptors.
	 */
#if defined(WINDOWS)

	class IOHandle {
	public:
		IOHandle();
		IOHandle(HANDLE h);

		// Get the underlying handle (if any).
		HANDLE v() const;

		// Associate a handle to this IO handle.
		void add(Handle h, const ThreadData *id);

		// Remove association with this IO handle.
		void remove(Handle h, const ThreadData *id);

		// Process all messages for this IO handle.
		void notifyAll(const ThreadData *id) const;

		// Close this handle.
		void close();

		// Attach/detach IO requests.
		void attach();
		void detach();

	private:
		HANDLE handle;

		// # of requests pending.
		mutable size_t pending;
	};

#elif defined(POSIX)

	/**
	 * Note: The io_uring implementation is compatible with the interface of the generic POSIX
	 * interface.
	 */
	class IOHandle {
	public:
		IOHandle();
		~IOHandle();

		// Associate a handle to this IOHandle.
		void add(Handle h, const ThreadData *id);

		// Remove association of a handle.
		void remove(Handle h, const ThreadData *id);

		// Attach to this IO handle.
		void attach(Handle h, IORequest *request);

		// Attach to this IO handle, but call 'remove' on handle afterwards.
		void attachAndRemove(Handle h, IORequest *request);

		// Detach from this IO handle.
		void detach(Handle h, IORequest *request);

		// Process all messages for this IO handle.
		void notifyAll(const ThreadData *id);

		// Close this handle.
		void close();

		// Get an array of pollfd:s describing the threads waiting currently.  Note: The first
		// element is empty and available for use by the IOCondition (it puts itself first to wait
		// for the IO condition also).
		struct Desc {
			struct pollfd *fds;
			size_t count;
		};
		Desc desc();

		// Additional interface when using io_uring.
#ifdef LINUX_IO_URING
		// Cancel a request.
		void cancel(IORequest *request);
#endif

	private:
		// Lock, just in case.
		mutable util::Lock lock;

#ifdef LINUX_IO_URING
		// Linux IO object.
		mutable LinuxIO linuxIO;

		// File descriptor to an eventfd that will get notified by the LinuxIO object.
		int eventfd;

		// pollfd-array to return from 'desc'.
		struct pollfd pollfds[2];

		// Remember the set of requests that are active currently. We use this to make sure that we
		// don't accidentally mess up the stack of threads if we ever get multiple notifications for
		// the same fd.
		std::unordered_set<IORequest *> activeRequests;
		std::multiset<std::pair<int, IORequest *>> activeFDs;
#else
		// All handles currently associated with us.
		typedef FdMap<IORequest, 1> HandleMap;
		HandleMap handles;
#endif
	};

#else
#error "Implement IOHandle for your platform!"
#endif

}