LINUX.ORG.RU

История изменений

Исправление pavlick, (текущая версия) :

Разобрался, можно послать процессу сингал SIGALARM все потоки в блокирующих операциях пробудятся. Просто для теста набросал, также будит и поток, который ожидает ввода с консоли.

#include <thread>
#include <signal.h>
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <endian.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <chrono>
using namespace std;

const char *iface_ip = "127.0.0.1";
unsigned short port = 10500;


void f() {
	int tcp_listener = socket(AF_INET, SOCK_STREAM, 0);
	if(tcp_listener == -1)
		return;

	in_addr fip{};
	if( inet_aton(iface_ip, &fip) != 1)
		return;
	sockaddr_in my_addr{};
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htobe16(port);
	my_addr.sin_addr = fip;
	if( bind(tcp_listener, (sockaddr*)(&my_addr), sizeof(my_addr) ) != 0)
		return;

	if( listen(tcp_listener, 1) != 0)
		return;

	int tcp_socket = accept(tcp_listener, NULL, NULL);
	if(tcp_socket == -1)
		return;

}
int main() {
	thread t(f);
	this_thread::sleep_for(2s);
	kill(getpid(), SIGALRM);
	t.join();
}

По поводу sleep_for() - естественно, что в боевом варианте не применяю (не впадаю в join() псле 2 сек), потоки завершаются и декрементируют счетчик, когда он равен нулю - все потоки завершились

class Run_tag  // передается аргументом в каждый созданный поток через Thread pool
{
	friend class Thread_pool;
	std::atomic_uint &m_counter;
	Run_tag &operator=(const Run_tag &) = delete;
	Run_tag(std::atomic_uint &counter): m_counter(counter)
	{
		this->m_counter.fetch_add(1, std::memory_order_relaxed);
	}
public:
	~Run_tag() {this->m_counter.fetch_sub(1, std::memory_order_release);}
	Run_tag(const Run_tag &other_tag): m_counter(other_tag.m_counter)
	{
		this->m_counter.fetch_add(1, std::memory_order_relaxed);
	}
};

inline Thread_pool::~Thread_pool()
{
	this->request_stop();
	while (this->m_counter.load(std::memory_order_acquire) != 0) {
                // здесь можно слать сигнал потокам хоть до посинения
		using namespace std;
		std::this_thread::sleep_for(50ms);
	}
	for (auto &t : this->m_th)
		t.join();
}

ЗЫ: спасибо.

Исправление pavlick, :

Разобрался, можно послать процессу сингал SIGALARM все потоки в блокирующих операциях пробудятся. Просто для теста набросал, также будит и поток, который ожидает ввода с консоли.

#include <thread>
#include <signal.h>
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <endian.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <chrono>
using namespace std;

const char *iface_ip = "127.0.0.1";
unsigned short port = 10500;


void f() {
	int tcp_listener = socket(AF_INET, SOCK_STREAM, 0);
	if(tcp_listener == -1)
		return;

	in_addr fip{};
	if( inet_aton(iface_ip, &fip) != 1)
		return;
	sockaddr_in my_addr{};
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htobe16(port);
	my_addr.sin_addr = fip;
	if( bind(tcp_listener, (sockaddr*)(&my_addr), sizeof(my_addr) ) != 0)
		return;

	if( listen(tcp_listener, 1) != 0)
		return;

	int tcp_socket = accept(tcp_listener, NULL, NULL);
	if(tcp_socket == -1)
		return;

}
int main() {
	thread t(f);
	this_thread::sleep_for(2s);
	kill(getpid(), SIGALRM);
	t.join();
}

По поводу sleep_for() - естественно, что в боевом варианте не применяю (не впадаю в join() псле 2 сек), потоки завершаются и декрементируют счетчик, когда он равен нулю - все потоки завершились

class Run_tag  // передается аргументом в каждый созданный поток через Thread pool
{
	friend class Thread_pool;
	std::atomic_uint &m_counter;
	Run_tag &operator=(const Run_tag &) = delete;
	Run_tag(std::atomic_uint &counter): m_counter(counter)
	{
		this->m_counter.fetch_add(1, std::memory_order_relaxed);
	}
public:
	~Run_tag() {this->m_counter.fetch_sub(1, std::memory_order_release);}
	Run_tag(const Run_tag &other_tag): m_counter(other_tag.m_counter)
	{
		this->m_counter.fetch_add(1, std::memory_order_relaxed);
	}
};

inline Thread_pool::~Thread_pool()
{
	this->request_stop();
	while (this->m_counter.load(std::memory_order_acquire) != 0) {
		using namespace std;
		std::this_thread::sleep_for(50ms);
	}
	for (auto &t : this->m_th)
		t.join();
}

ЗЫ: спасибо.

Исходная версия pavlick, :

Разобрался, можно послать процессу сингал SIGALARM все потоки в блокирующих операциях пробудятся. Просто для теста набросал, такжи будит и поток, который ожидает ввода с консоли.

#include <thread>
#include <signal.h>
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <endian.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <chrono>
using namespace std;

const char *iface_ip = "127.0.0.1";
unsigned short port = 10500;


void f() {
	int tcp_listener = socket(AF_INET, SOCK_STREAM, 0);
	if(tcp_listener == -1)
		return;

	in_addr fip{};
	if( inet_aton(iface_ip, &fip) != 1)
		return;
	sockaddr_in my_addr{};
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htobe16(port);
	my_addr.sin_addr = fip;
	if( bind(tcp_listener, (sockaddr*)(&my_addr), sizeof(my_addr) ) != 0)
		return;

	if( listen(tcp_listener, 1) != 0)
		return;

	int tcp_socket = accept(tcp_listener, NULL, NULL);
	if(tcp_socket == -1)
		return;

}
int main() {
	thread t(f);
	this_thread::sleep_for(2s);
	kill(getpid(), SIGALRM);
	t.join();
}

По поводу sleep_for() - естественно, что в боевом варианте не применяю (не впадаю в join() псле 2 сек), потоки завершаются и декрементируют счетчик, когда он равен нулю - все потоки завершились

class Run_tag  // передается аргументом в каждый созданный поток через Thread pool
{
	friend class Thread_pool;
	std::atomic_uint &m_counter;
	Run_tag &operator=(const Run_tag &) = delete;
	Run_tag(std::atomic_uint &counter): m_counter(counter)
	{
		this->m_counter.fetch_add(1, std::memory_order_relaxed);
	}
public:
	~Run_tag() {this->m_counter.fetch_sub(1, std::memory_order_release);}
	Run_tag(const Run_tag &other_tag): m_counter(other_tag.m_counter)
	{
		this->m_counter.fetch_add(1, std::memory_order_relaxed);
	}
};

inline Thread_pool::~Thread_pool()
{
	this->request_stop();
	while (this->m_counter.load(std::memory_order_acquire) != 0) {
		using namespace std;
		std::this_thread::sleep_for(50ms);
	}
	for (auto &t : this->m_th)
		t.join();
}

ЗЫ: спасибо.