我正在尝试访问一个我通过引用传递给一个将运行到程序结束的线程的值。我想对这个值执行一些操作,然后通过引用传递给另一个线程。
我研究过线程期货,但我不确定这是否符合我的目的,因为我需要不断更新价值。如果我只使用普通的互斥锁,由于访问该值的其他线程阻塞,我的操作永远不会被调用。 (这就是我为类中的函数使用了原子bool标志的原因)。关于如何进行的任何建议?这是我的代码。
主程序
#include "sock_send.h"
#include <thread>
#include <functional>
#include <iostream>
#include <atomic>
extern std::mutex some_other_mutex;
int main(){
int portno[4] = {55011, 55016, 55021, 55026};
std::vector <double> data_r(6), data_l(6);
std::atomic <bool> flag1(false), flag2(false);
sock_send newsocket1;
sock_send newsocket3;
newsocket1.startsocket(portno[0]);
newsocket3.startsocket(portno[2]);
std::thread t1 (&sock_send::readsocket, &newsocket1, std::ref(data_r), std::ref(flag1));
//对data_r执行一些操作,比如data_l = data_r / 10;
std::thread t3 (&sock_send::writesocket, &newsocket3, std::ref(data_l), std::ref(flag1));
t1.join();
t3.detach();
return 0;
}
sock_send.h
#ifndef SOCK_SEND_H
#define SOCK_SEND_H
#include <functional>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <mutex>
#include <vector>
#include <thread>
#include <atomic>
extern std::mutex some_other_mutex;
class sock_send
{
public:
void startsocket (int portno);
void writesocket(std::vector<double> & data_o, std::atomic <bool> &flag);
void readsocket(std::vector<double> & data_in, std::atomic <bool> &flag);
~sock_send();
private:
struct sockaddr_in serv_addr, cli_addr;
int n, epfd, sockfd, yes=1, newsockfd = 0, nbytess,
clilen = sizeof(cli_addr);
// define epoll event structs
struct epoll_event event, *events = new epoll_event;
};
#endif
sock_send.cc
#include "sock_send.h"
std::mutex some_other_mutex;
void sock_send::startsocket (int portno){
//create an epoll file descriptor
if ((epfd = epoll_create1(0)) == -1)
std::cout << "Error on epoll create\t" << errno << std::endl;
//create the socket file descriptor
if ((sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
std::cout << "Error on socket create\t" << errno << std::endl;
// get rid of annoying port in use
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1)
std::cout << "Error on socket reuse option\t" << errno << std::endl;
// fill up serv addr with zeros
bzero((char *) &serv_addr, sizeof(serv_addr));
//enter data in serv addr
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
serv_addr.sin_addr.s_addr = INADDR_ANY;
// bind port and ip to socket 1
if ((bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) == -1)
std::cout << "Error on binding sock\t" << errno << std::endl;
//start listening on socket
if ((listen(sockfd,100))==-1)
std::cout << "Error on listen sock\t" << errno << std::endl;
// socket epoll control
event.data.fd = sockfd;
event.events = EPOLLIN;
if ((epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event)) == -1)
std::cout << "Error on epoll ctl sock\t" << errno << std::endl;
while (newsockfd == 0){
// wait for an event using epoll
if ((n = epoll_wait (epfd, events, 20, -1)) == -1){
std::cout << "Error on epoll wait\t" << errno << std::endl;
continue;
}
if (sockfd == events[0].data.fd){
// accept incoming connection
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,(socklen_t*)&clilen)) == -1){
std::cout << "Error on accept\t " << errno << std::endl;
continue;
}
event.data.fd = newsockfd;
event.events = EPOLLIN;
if ((epoll_ctl (epfd, EPOLL_CTL_ADD, newsockfd, &event)) == -1){
std::cout << "Error on epoll cntl" << errno << std::endl;
continue;
}
break;
}
else
std::cout << "Epoll returning some other socket \t" << events[0].data.fd << std::endl;
}
}
void sock_send::readsocket(std::vector<double> & data_in, std::atomic <bool> &flag){
while (1){
// wait for an event using epoll
if ((n = epoll_wait (epfd, events, 20, 0)) == -1){
std::cout << "Error on epoll wait\t" << errno << std::endl;
continue;
}
//if newsock connections available
if ((newsockfd == events[0].data.fd) & (flag ==false)){
std::unique_lock<std::mutex> lck (some_other_mutex);
nbytess = recv(events[0].data.fd, data_in.data() , (sizeof data_in[0])*(data_in.size()), 0);
lck.unlock();
flag = true;
if (nbytess == -1){
std::cout << "Error during read: " << errno << std::endl;
break;
}
if (nbytess == 0){
std::cout << "End of data from this socket" << std::endl;
break;
}
}
}
}
void sock_send::writesocket(std::vector<double> & data_o, std::atomic <bool> &flag){
while(1){
if (flag == true ){
std::unique_lock<std::mutex> lck (some_other_mutex);
nbytess = send(newsockfd, data_o.data(),(sizeof data_o[0])*(data_o.size()), 0);
lck.unlock();
flag =false;
if (nbytess == -1){
if (errno == 104)
std::cout << "Connection Closed" << std::endl;
else
std::cout << "Error during write: " << errno << std::endl;
}
}
}
}
sock_send::~sock_send()
{
delete events;
close (sockfd);
}
&LT;&LT;&LT;&LT;&LT;&LT;&LT;&LT;&LT;&LT;&LT;编辑:新单线程代码&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;
主
#include "sock_send.h"
#include <functional>
#include <iostream>
#include <chrono>
#include <thread>
int main(){
int portno[2] = {55011, 55021};
std::vector<double> data_mod(6);
sock_send newsocket1;
newsocket1.startsocket(portno,2);
for (double i=0; i<9993999; i++){
newsocket1.read(data_mod);
std::this_thread::sleep_for(std::chrono::nanoseconds(1));
newsocket1.write(data_mod);
}
return 0;
}
sock_send.h
#ifndef SOCK_SEND_H
#define SOCK_SEND_H
#include <functional>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <mutex>
#include <vector>
class sock_send
{
public:
void startsocket (int * portno, int np);
void read(std::vector<double> &data_in);
void write(std::vector<double> &data_o);
~sock_send();
private:
struct sockaddr_in serv_addr[2], cli_addr[2];
int n[2], epfd[2], sockfd[2], yes=1, newsockfd[2] = {0,0}, nbytess[2],
clilen[2] = {sizeof(cli_addr[0]), sizeof(cli_addr[1])};
// define epoll event structs
struct epoll_event event[2], *events[2] = {new epoll_event, new epoll_event};
};
#endif
sock_send.cc
#include "sock_send.h"
void sock_send::startsocket (int *portno, int np){
for (int i = 0; i <np; i++){
//create an epoll file descriptor
if ((epfd[i] = epoll_create1(0)) == -1)
std::cout << "Error on epoll create\t" << errno << std::endl;
//create the socket file descriptor
if ((sockfd[i] = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
std::cout << "Error on socket create\t" << errno << std::endl;
// get rid of annoying port in use
if (setsockopt(sockfd[i], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1)
std::cout << "Error on socket reuse option\t" << errno << std::endl;
// fill up serv addr with zeros
bzero((char *) &serv_addr[i], sizeof(serv_addr[i]));
//enter data in serv addr
serv_addr[i].sin_family = AF_INET;
serv_addr[i].sin_port = htons(portno[i]);
serv_addr[i].sin_addr.s_addr = INADDR_ANY;
// bind port and ip to socket 1
if ((bind(sockfd[i], (struct sockaddr *) &serv_addr[i], sizeof(serv_addr[i]))) == -1)
std::cout << "Error on binding sock\t" << errno << std::endl;
//start listening on socket
if ((listen(sockfd[i],100))==-1)
std::cout << "Error on listen sock\t" << errno << std::endl;
// socket epoll control
event[i].data.fd = sockfd[i];
event[i].events = EPOLLIN;
if ((epoll_ctl(epfd[i], EPOLL_CTL_ADD, sockfd[i], &event[i])) == -1)
std::cout << "Error on epoll ctl sock\t" << errno << std::endl;
while (newsockfd[i] == 0){
// wait for an event using epoll
if ((n[i] = epoll_wait (epfd[i], events[i], 20, -1)) == -1){
std::cout << "Error on epoll wait\t" << errno << std::endl;
continue;
}
if (sockfd[i] == events[i][0].data.fd){
// accept incoming connection
if ((newsockfd[i] = accept(sockfd[i], (struct sockaddr *) &cli_addr[i],(socklen_t*)&clilen[i])) == -1){
std::cout << "Error on accept\t " << errno << std::endl;
continue;
}
event[i].data.fd = newsockfd[i];
event[i].events = EPOLLIN;
if ((epoll_ctl (epfd[i], EPOLL_CTL_ADD, newsockfd[i], &event[i])) == -1){
std::cout << "Error on epoll cntl" << errno << std::endl;
continue;
}
break;
}
else
std::cout << "Epoll returning some other socket \t" << events[i][0].data.fd << std::endl;
}
}
}
void sock_send::read(std::vector<double> &data_in){
// wait for an event using epoll
if ((n[0] = epoll_wait (epfd[0], events[0], 20, 0)) == -1){
std::cout << "Error on epoll wait\t" << errno << std::endl;
}
//if newsock connections available
if ((newsockfd[0] == events[0][0].data.fd)){
nbytess[0] = recv(events[0][0].data.fd, data_in.data() , (sizeof data_in[0])*(data_in.size()), 0);
if (nbytess[0] == -1){
std::cout << "Error during read: " << errno << std::endl;
}
if (nbytess[0] == 0){
std::cout << "End of data from this socket" << std::endl;
}
//std::cout << data_in[0] << std::endl;
}
}
void sock_send::write(std::vector<double> &data_o){
std::cout << data_o[0] << std::endl;
nbytess[1] = send(newsockfd[1], data_o.data(),(sizeof data_o[0])*(data_o.size()), 0);
if (nbytess[1] == -1){
if (errno == 104)
std::cout << "Connection Closed" << std::endl;
else
std::cout << "Error during write: " << errno << std::endl;
}
}
sock_send::~sock_send()
{
delete events[0], events[1];
close (sockfd[0]);
close (sockfd[1]);
}