8 #include <marnav/io/device.hpp>
9 #include <marnav/io/selectable.hpp>
11 namespace marnav_example
13 /// A named pipe, implementing device and selectable for demonstration purposes.
15 /// @note The created FIFO will not be removed.
16 class pipe
: public marnav::io::device
, virtual public marnav::io::selectable
18 friend class selector
;
21 pipe(std::string filename
)
27 virtual ~pipe() { close(); }
29 void create() { ::mkfifo(filename
.c_str(), 0666); }
35 fd
= ::open(filename
.c_str(), O_RDONLY
| O_NONBLOCK
);
42 fd
= ::open(filename
.c_str(), O_WRONLY
| O_NONBLOCK
);
45 void open_read_write()
49 fd
= ::open(filename
.c_str(), O_RDWR
| O_NONBLOCK
);
52 virtual void close() override
60 virtual int read(char * buffer
, uint32_t size
) override
63 throw std::invalid_argument
{"buffer"};
65 throw std::runtime_error
{"pipe not open"};
67 return ::read(fd
, buffer
, size
);
70 virtual int write(const char * buffer
, uint32_t size
) override
73 throw std::invalid_argument
{"buffer"};
75 throw std::runtime_error
{"pipe not open"};
77 return ::write(fd
, buffer
, size
);
81 virtual void open() override
{}
82 virtual int get_fd() const override
{ return fd
; }
92 std::vector
<std::shared_ptr
<marnav::io::selectable
>> operator()(
93 const std::vector
<std::shared_ptr
<marnav::io::selectable
>> & devices
)
95 return select(devices
);
98 static std::vector
<std::shared_ptr
<marnav::io::selectable
>> select(
99 const std::vector
<std::shared_ptr
<marnav::io::selectable
>> & devices
)
101 std::vector
<std::shared_ptr
<marnav::io::selectable
>> result
;
103 if (devices
.size() == 0)
106 // fill filedescriptor set for reading
110 for (auto const & dev
: devices
) {
111 auto fd
= dev
->get_fd();
118 auto rc
= ::select(max_fd
+ 1, &rfds
, 0, 0, 0);
120 throw std::runtime_error
{"select"};
122 // find out which device has caused the wakeup
124 for (auto const & dev
: devices
) {
125 if (FD_ISSET(dev
->get_fd(), &rfds
)) {
126 result
.push_back(dev
);
134 int main(int, char **)
136 // create a named pipe
137 auto dev0
= std::make_shared
<marnav_example::pipe
>("/tmp/foobar");
141 // open it a second time as different device
142 auto dev1
= std::make_shared
<marnav_example::pipe
>("/tmp/foobar");
143 dev1
->open_read_write();
146 dev1
->write("foo\0", 4);
148 // wait on named pipe, receive and print data
149 auto devs
= marnav_example::selector::select({dev0
});
150 if (devs
.size() == 0) {
151 std::cout
<< "no devices ready for read, probably timeout\n";
155 for (auto & dev
: devs
) {
160 rc
= dev0
->read(buffer
, sizeof(buffer
));
163 rc
= dev1
->read(buffer
, sizeof(buffer
));
167 std::cout
<< "received: " << buffer
<< "\n";