#include <assert.h>
#include <limits.h>
#include <stdio.h>
+#include <sys/eventfd.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <algorithm>
using namespace std;
using namespace std::placeholders;
+ALSAPool::ALSAPool()
+{
+ should_quit_fd = eventfd(/*initval=*/0, /*flags=*/0);
+ assert(should_quit_fd != -1);
+}
+
ALSAPool::~ALSAPool()
{
for (Device &device : devices) {
}
}
should_quit = true;
+ const uint64_t one = 1;
+ write(should_quit_fd, &one, sizeof(one));
inotify_thread.join();
+
+ while (retry_threads_running > 0) {
+ this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
}
std::vector<ALSAPool::Device> ALSAPool::get_devices()
// then start it ourselves.
fprintf(stderr, "Trying %s again in one second...\n", address);
add_device_tries_left[address] = num_retries;
+ ++retry_threads_running;
thread(&ALSAPool::probe_device_retry_thread_func, this, card_index, dev_index).detach();
}
// See if there are any retries left.
lock_guard<mutex> lock(add_device_mutex);
- if (!add_device_tries_left.count(address) ||
+ if (should_quit ||
+ !add_device_tries_left.count(address) ||
add_device_tries_left[address] == 0) {
add_device_tries_left.erase(address);
fprintf(stderr, "Giving up probe of %s.\n", address);
- return;
+ break;
}
// Seemingly there were. Give it a try (we still hold the mutex).
if (result == ProbeResult::SUCCESS) {
add_device_tries_left.erase(address);
fprintf(stderr, "Probe of %s succeeded.\n", address);
- return;
+ break;
} else if (result == ProbeResult::FAILURE || --add_device_tries_left[address] == 0) {
add_device_tries_left.erase(address);
fprintf(stderr, "Giving up probe of %s.\n", address);
- return;
+ break;
}
// Failed again.
fprintf(stderr, "Trying %s again in one second (%d tries left)...\n",
address, add_device_tries_left[address]);
}
+
+ --retry_threads_running;
}
ALSAPool::ProbeResult ALSAPool::probe_device_once(unsigned card_index, unsigned dev_index)
int size = sizeof(inotify_event) + NAME_MAX + 1;
unique_ptr<char[]> buf(new char[size]);
while (!should_quit) {
- pollfd fds;
- fds.fd = inotify_fd;
- fds.events = POLLIN;
- fds.revents = 0;
-
- int ret = poll(&fds, 1, 100);
+ pollfd fds[2];
+ fds[0].fd = inotify_fd;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ fds[1].fd = should_quit_fd;
+ fds[1].events = POLLIN;
+ fds[1].revents = 0;
+
+ int ret = poll(fds, 2, -1);
if (ret == -1) {
if (errno == EINTR) {
continue;
continue;
}
+ if (fds[1].revents) break; // should_quit_fd asserted.
+
ret = read(inotify_fd, buf.get(), size);
if (ret == -1) {
if (errno == EINTR) {
}
close(watch_fd);
close(inotify_fd);
+ close(should_quit_fd);
}
void ALSAPool::reset_device(unsigned index)