История изменений
Исправление
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();
}
ЗЫ: спасибо.