2
* Copyright © 2015 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
19
#include "mir/dispatch/multiplexing_dispatchable.h"
20
#include "mir/dispatch/simple_dispatch_thread.h"
30
namespace md = mir::dispatch;
32
class TestDispatchable : public md::Dispatchable
35
TestDispatchable(uint64_t limit)
36
: dispatch_limit{limit}
39
if (pipe(pipefds) < 0)
41
throw std::system_error{errno, std::system_category(), "Failed to create pipe"};
44
read_fd = mir::Fd{pipefds[0]};
45
write_fd = mir::Fd{pipefds[1]};
48
if (::write(write_fd, &dummy, sizeof(dummy)) != sizeof(dummy))
50
throw std::system_error{errno, std::system_category(), "Failed to mark dispatchable"};
54
mir::Fd watch_fd() const override
58
bool dispatch(md::FdEvents) override
61
return (dispatch_count < dispatch_limit);
63
md::FdEvents relevant_events() const override
65
return md::FdEvent::readable;
69
static thread_local uint64_t dispatch_count;
70
uint64_t const dispatch_limit;
71
mir::Fd read_fd, write_fd;
74
thread_local uint64_t TestDispatchable::dispatch_count = 0;
76
bool fd_is_readable(int fd)
78
struct pollfd poller {
83
return poll(&poller, 1, 0);
86
int main(int argc, char** argv)
90
std::cout<<"Usage: "<<argv[0]<<" <number of threads> <dispatch count>"<<std::endl;
94
int const thread_count = std::atoi(argv[1]);
95
uint64_t const dispatch_count = std::atoll(argv[2]);
97
auto dispatcher = std::make_shared<md::MultiplexingDispatchable>();
98
dispatcher->add_watch(std::make_shared<TestDispatchable>(dispatch_count / thread_count), md::DispatchReentrancy::reentrant);
100
auto start = std::chrono::steady_clock::now();
102
std::vector<std::thread> thread_loops;
103
for (int i = 0; i < thread_count; ++i)
105
thread_loops.emplace_back([](md::Dispatchable& dispatch)
107
while(fd_is_readable(dispatch.watch_fd()))
109
dispatch.dispatch(md::FdEvent::readable);
111
}, std::ref(*dispatcher));
114
for (auto& thread : thread_loops)
119
auto duration = std::chrono::steady_clock::now() - start;
120
std::cout<<"Dispatching "<<dispatch_count<<" times took "<<std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count()<<"ns"<<std::endl;