This is an example of how to use the Wayland C++ bindings with multiple threads binding to globals on one shared connection using proxy wrappers.
It can run in two modes: safe or unsafe mode. In safe mode, proxy wrappers are correctly used. In unsafe mode, proxy wrappers are not used, and a race occurs that will lead to failures when ran often enough.
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace wayland;
class binder
{
private:
void bind(bool safe)
{
if(safe)
{
registry = display_wrapper.get_registry();
}
else
{
}
registry.
on_global() = [&seat, ®istry](std::uint32_t name, std::string interface, std::uint32_t version)
{
if(interface == seat_t::interface_name)
registry.
bind(name, seat, version);
};
if(!seat)
throw std::runtime_error("Did NOT get seat interface - thread-safety issue!");
if(safe)
{
seat = seat.
proxy_create_wrapper();
}
bool have_keymap = false;
kbd.
on_keymap() = [&have_keymap](keyboard_keymap_format format,
int fd, std::uint32_t size)
{
close(fd);
have_keymap = true;
};
if(!have_keymap)
{
throw std::runtime_error("Did NOT get keymap - thread-safety issue!");
}
}
std::thread bind_thread(bool safe)
{
return std::thread{std::bind(&binder::bind, this, safe)};
}
public:
void run(int thread_count, int round_count, bool safe)
{
std::atomic<bool> stop{false};
std::cout << "Using " << thread_count << " threads, safe: " << safe << std::endl;
for(int round = 0; round < round_count; round++)
{
if(round % 100 == 0)
{
std::cout << "Round " << round << "/" << round_count << std::endl;
}
std::vector<std::thread> threads;
threads.reserve(thread_count);
for(int i = 0; i < thread_count; i++)
{
threads.emplace_back(bind_thread(safe));
}
for(auto& thread : threads)
{
thread.join();
}
}
stop = true;
}
};
int main(int argc, char** argv)
{
if(argc != 4)
{
std::cerr << "Usage: " << argv[0] << " <thread count> <run count> <use safe mechanism?>" << std::endl;
return -1;
}
binder b;
b.run(std::stoi(argv[1]), std::stoi(argv[2]), std::stoi(argv[3]));
return 0;
}