在c ++ 11中访问通过引用传递给线程的值

时间:2016-12-06 23:17:00

标签: c++ linux matlab c++11 simulink

我正在尝试访问一个我通过引用传递给一个将运行到程序结束的线程的值。我想对这个值执行一些操作,然后通过引用传递给另一个线程。

我研究过线程期货,但我不确定这是否符合我的目的,因为我需要不断更新价值。如果我只使用普通的互斥锁,由于访问该值的其他线程阻塞,我的操作永远不会被调用。 (这就是我为类中的函数使用了原子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]);
}

0 个答案:

没有答案