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"
29
namespace md = mir::dispatch;
31
class TestDispatchable : public md::Dispatchable
34
TestDispatchable(uint64_t limit)
35
: dispatch_limit{limit}
38
if (pipe(pipefds) < 0)
40
throw std::system_error{errno, std::system_category(), "Failed to create pipe"};
43
read_fd = mir::Fd{pipefds[0]};
44
write_fd = mir::Fd{pipefds[1]};
47
if (::write(write_fd, &dummy, sizeof(dummy)) != sizeof(dummy))
49
throw std::system_error{errno, std::system_category(), "Failed to mark dispatchable"};
53
mir::Fd watch_fd() const override
57
bool dispatch(md::FdEvents) override
60
return (dispatch_count < dispatch_limit);
62
md::FdEvents relevant_events() const override
64
return md::FdEvent::readable;
68
static thread_local uint64_t dispatch_count;
69
uint64_t const dispatch_limit;
70
mir::Fd read_fd, write_fd;
73
thread_local uint64_t TestDispatchable::dispatch_count = 0;
75
bool fd_is_readable(int fd)
77
struct pollfd poller {
82
return poll(&poller, 1, 0);
85
int main(int argc, char** argv)
89
std::cout<<"Usage: "<<argv[0]<<" <number of threads> <dispatch count>"<<std::endl;
93
int const thread_count = std::atoi(argv[1]);
94
uint64_t const dispatch_count = std::atoll(argv[2]);
96
auto dispatcher = std::make_shared<md::MultiplexingDispatchable>();
97
dispatcher->add_watch(std::make_shared<TestDispatchable>(dispatch_count / thread_count), md::DispatchReentrancy::reentrant);
99
auto start = std::chrono::steady_clock::now();
101
std::vector<std::thread> thread_loops;
102
for (int i = 0; i < thread_count; ++i)
104
thread_loops.emplace_back([](md::Dispatchable& dispatch)
106
while(fd_is_readable(dispatch.watch_fd()))
108
dispatch.dispatch(md::FdEvent::readable);
110
}, std::ref(*dispatcher));
113
for (auto& thread : thread_loops)
118
auto duration = std::chrono::steady_clock::now() - start;
119
std::cout<<"Dispatching "<<dispatch_count<<" times took "<<std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count()<<"ns"<<std::endl;