Wayland++  0.2.6
C++ Bindings for Wayland
proxy_wrapper.cpp
1 /*
2  * Copyright (c) 2017-2019, Philipp Kerling
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
35 #include <iostream>
36 #include <thread>
37 #include <unistd.h>
38 
39 #include <wayland-client.hpp>
40 
41 using namespace wayland;
42 
43 class binder
44 {
45 private:
46  display_t display;
47 
48  void bind(bool safe)
49  {
50  registry_t registry;
51  seat_t seat;
52 
53  auto queue = display.create_queue();
54  if(safe)
55  {
56  auto display_wrapper = display.proxy_create_wrapper();
57  display_wrapper.set_queue(queue);
58  registry = display_wrapper.get_registry();
59  }
60  else
61  {
62  registry = display.get_registry();
63  // This is the race: registry will be set to the default queue for a very
64  // short while between get_registry() and set_queue() - events dispatched
65  // in between get stuck in the default queue and ultimately lost.
66  registry.set_queue(queue);
67  }
68 
69  registry.on_global() = [&seat, &registry](std::uint32_t name, std::string interface, std::uint32_t version)
70  {
71  if(interface == seat_t::interface_name)
72  registry.bind(name, seat, version);
73  };
74  display.roundtrip_queue(queue);
75  if(!seat)
76  throw std::runtime_error("Did NOT get seat interface - thread-safety issue!");
77 
78  // Now pretend that again another part of the application wants to use the
79  // seat and get the keyboard from it
80  // Note that it would not be necessary to do this in this example, but
81  // this code is useful for testing proxy wrappers with normal interface
82  // objects (display_t is special)
83  auto queue2 = display.create_queue();
84  if(safe)
85  {
86  seat = seat.proxy_create_wrapper();
87  }
88  seat.set_queue(queue2);
89  keyboard_t kbd = seat.get_keyboard();
90  bool have_keymap = false;
91  kbd.on_keymap() = [&have_keymap](keyboard_keymap_format format, int fd, std::uint32_t size)
92  {
93  close(fd);
94  have_keymap = true;
95  };
96  display.roundtrip_queue(queue2);
97  if(!have_keymap)
98  {
99  throw std::runtime_error("Did NOT get keymap - thread-safety issue!");
100  }
101  }
102 
103  std::thread bind_thread(bool safe)
104  {
105  return std::thread{std::bind(&binder::bind, this, safe)};
106  }
107 
108 public:
109  void run(int thread_count, int round_count, bool safe)
110  {
111  std::atomic<bool> stop{false};
112  std::cout << "Using " << thread_count << " threads, safe: " << safe << std::endl;
113  for(int round = 0; round < round_count; round++)
114  {
115  if(round % 100 == 0)
116  {
117  std::cout << "Round " << round << "/" << round_count << std::endl;
118  }
119  std::vector<std::thread> threads;
120  threads.reserve(thread_count);
121  for(int i = 0; i < thread_count; i++)
122  {
123  threads.emplace_back(bind_thread(safe));
124  }
125  for(auto& thread : threads)
126  {
127  thread.join();
128  }
129  }
130  stop = true;
131  }
132 };
133 
134 int main(int argc, char** argv)
135 {
136  if(argc != 4)
137  {
138  std::cerr << "Usage: " << argv[0] << " <thread count> <run count> <use safe mechanism?>" << std::endl;
139  return -1;
140  }
141  binder b;
142  b.run(std::stoi(argv[1]), std::stoi(argv[2]), std::stoi(argv[3]));
143  return 0;
144 }
wayland::display_t
Represents a connection to the compositor and acts as a proxy to the display singleton object.
Definition: wayland-client.hpp:463
wayland::display_t::get_registry
registry_t get_registry()
get global registry object
wayland::display_t::roundtrip_queue
int roundtrip_queue(event_queue_t queue)
Block until all pending request are processed by the server.
wayland::display_t::proxy_create_wrapper
display_t proxy_create_wrapper()
create proxy wrapper for this display
wayland::registry_t
global registry object
Definition: wayland-client-protocol.hpp:130
wayland::display_t::create_queue
event_queue_t create_queue()
Create a new event queue for this display.
wayland::registry_t::bind
proxy_t bind(uint32_t name, proxy_t &interface, uint32_t version)
bind an object to the display
Definition: wayland-client-protocol.cpp:1560
wayland::seat_t
group of input devices
Definition: wayland-client-protocol.hpp:2334
wayland::proxy_t::set_queue
void set_queue(event_queue_t queue)
Assign a proxy to an event queue.
wayland::seat_t::get_keyboard
keyboard_t get_keyboard()
return keyboard object
Definition: wayland-client-protocol.cpp:2762
wayland::registry_t::on_global
std::function< void(uint32_t, std::string, uint32_t)> & on_global()
announce global object
Definition: wayland-client-protocol.cpp:1567
wayland::keyboard_t
keyboard input device
Definition: wayland-client-protocol.hpp:2896
wayland-client.hpp
wayland::keyboard_t::on_keymap
std::function< void(keyboard_keymap_format, int, uint32_t)> & on_keymap()
keyboard mapping
Definition: wayland-client-protocol.cpp:3018