Предлагаю вам использовать:
- неблокирующие операции
poll()
(или select()
или epoll()
) - трубу
Перед тем, как создать поток, вы устанавливаете канал, который будет передавать «сообщение о прерывании». В вашем потоке tfunc
вы устанавливаете poll
так, чтобы он ждал как файловый дескриптор (сокет), с которым вы хотите работать, , так и читаемый конец канала.
Если вы хотите прервать, просто написав «сообщение прерывания» в конец канала записи; и в потоке проверьте при возврате poll
, есть ли в канале данные для чтения.
Небольшая демонстрация, без обработки ошибок, без обработки сигналов, просто чтобы визуализировать, что я имею в виду:
#include <cassert>
#include <iostream>
#include <thread>
#include <poll.h>
#include <unistd.h>
int fd[2];
void the_blocking_thread(void)
{
pollfd pollfds[2];
pollfds[0].fd = fd[0];
pollfds[0].events = POLLIN;
pollfds[1].fd = -99; // add here your socket / fd
pollfds[1].events = POLLIN; // or whatever you need
std::cout << "waiting for \"interrupt message\" or real work on fd" << std::endl;
int ret = poll(pollfds, 2, -1);
assert(ret > 0);
if (pollfds[0].revents != 0) {
std::cout << "cleanup" << std::endl;
return;
}
// Non blocking call on your fd
// Some other stuff
}
int main() {
int ret = pipe(fd);
assert(ret == 0);
std::cout << "Starting thread" << std::endl;
std::thread t(the_blocking_thread);
std::chrono::seconds timespan(1); // or whatever
std::this_thread::sleep_for(timespan);
std::cout << "Sending \"interrupt\" message" << std::endl;
char dummy = 42;
ret = write (fd[1], &dummy, 1);
assert(ret == 1);
t.join();
}
( Живое )