خرید بک لینک

Vote count: 0

I am developing an application that has both an user interface and the logic of the program. Let's call them UI and Client. As I don't want the user interface to be frozen by the logic of the program —which will coect to the server, send and receive data that would block the main thread—, I launch a new thread in the client, and the idea is to post all the work to the new thread.

For example, the flow of the program when trying to coect would be the following one:

  1. User clicks Coect button, after having filled the IP and port data.
  2. The user interface sends a coect signal with that data to the client.
  3. The client attempts to coect and sends back a signal to the user interface indicating the result of that attempt —true or false—.

I have successfully achieved to make the client send that last signal to the user interface. However, I am facing a lot of trouble with sending the coect signal from the user interface to the client. Therefore, I have achieved and tested 1 and 2.

qtui.hpp

#ifndef QTUI_H
#define QTUI_H

#include <QMainWindow>
#include <QFileSystemWatcher>

#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>
#include <boost/bind.hpp>

#include "../common/inotify.hpp"

class Client;

namespace Ui {
class QTUI;
}

class QTUI : public QMainWindow, public boost::enable_shared_from_this<QTUI>
{
    Q_OBJECT

public:
    explicit QTUI(QWidget *parent = 0);
    ~QTUI();

    /* Signals */
    typedef boost::signals2::signal
        <void (const char* ipaddress, const char* port)> start_coect;
    typedef start_coect::slot_type start_coect_st;

    boost::signals2::coection start_coect_ui(const start_coect_st& slot);

private slots:

    void on_pushButton_coect_released();

    void coection_status(bool error);

private:
    Ui::QTUI *ui;

    boost::shared_ptr<Client> client_;

    start_coect sc_signal;
};

#endif // QTUI_H

qtui.cpp: I have removed some parts that are not related to the question itself.

#include "qtui.h"
#include "qtui.h"

#include <iostream>

#include <QHostAddress>
#include <QRegExp>
#include <QIntValidator>
#include <QFileDialog>

#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>

#include "../client/client.hpp"


#include <boost/bind.hpp>
#include <boost/thread.hpp>

QTUI::QTUIQWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::QTUI),
    client_(new Client(shared_from_this())),
{
    ui->setupUi(this);

    /*...*/

    client_->get_con_status(boost::bind(&QTUI::coection_status, this, _1));

}

void QTUI::coection_status(bool error)
{
    /*...*/
}

QTUI::~QTUI()
{
    delete ui;
}

void QTUI::on_pushButton_coect_released()
{
/*
* Get ip address and port
*
*/
    sc_signal(address,port);

}

boost::signals2::coection QTUI::start_coect_ui(const start_coect_st& 
slot)
{
    retu sc_signal.coect(slot);
}

Then, in the client part I have the following:

#ifndef CLIENT_HPP
#define CLIENT_HPP

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>

#include <boost/signals2.hpp>

#include "../common/message.hpp"

class QTUI;

class Client : public boost::enable_shared_from_this<Client>
{
public:
    Client(boost::shared_ptr<QTUI> ui);

    void imagine_this_was_a_signal(const char* ipaddress, const char* port);
    bool coect(const char* ipaddress, const char* port);
    bool discoect();
    bool identify_user(const char* useame, const char* password);


    /* Signals */
    typedef boost::signals2::signal<void (bool status)> coect_status;
    typedef coect_status::slot_type coect_status_st;

    boost::signals2::coection get_con_status(const coect_status_st& slot);

private:
    void start();
    void stop();

    void handle_coect(
        boost::asio::ip::tcp::resolver::iterator iterator,
        const boost::system::error_code& error);
    void handle_read(size_t bytes_transferred, 
        const boost::system::error_code& error);
    void handle_write(size_t bytes_transferred,
        const boost::system::error_code& error);

    void read();
    void read_header();
    void write_header();
    void write();

    boost::shared_ptr<QTUI> ui_;
    boost::shared_ptr<boost::thread> thread_;
    boost::shared_ptr<boost::asio::io_service> io_service_;
    boost::shared_ptr<boost::asio::io_service::work> work_;
    boost::shared_ptr<boost::asio::ip::tcp::socket> socket_;

    Message read_, write_;
    bool coected_;
    bool logged_in;
    bool rheader_, wheader_;

    coect_status cs_sig;
};

#endif//  client.hpp 

client.cpp

#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <boost/function.hpp>

#include <cstdio> /* sprintf */

#include "client.hpp"
#include "../common/commands.hpp"
#include "../gui/qtgui.h"

#include <functional> 
#include <unistd.h>

Client::Client(boost::shared_ptr<QTGUI> ui):
ui_(ui),
io_service_(new boost::asio::io_service),
work_(new boost::asio::io_service::work(*io_service_)),
coected_(false)
{
    const char* ip = "127.0.0.1";
    const char* por = "9000";

    boost::function<void(const char* one, const char* two)> b =
    boost::bind(&Client::coect, shared_from_this(), _1, _2);

    io_service_->post(b(ip,por));
    /*ui->start_coect_ui(
        boost::bind(io_service_->post(
            boost::protect(boost::bind(&Client::coect, shared_from_this(), 
                ip, por)
            )), shared_from_this()
        )   
    );*/

/*ui_->start_coect_ui(boost::bind(
    boost::bind(
        io_service_->post(&Client::coect, shared_from_this(), ip, por),
                shared_from_this()
);*/
    start();
}

void Client::imagine_this_was_a_signal(const char* ipaddress, const char* port)
{
    io_service_->post(boost::bind(
        &Client::coect, shared_from_this(), ipaddress, port
    ));
}

bool Client::coect(const char* ipaddress, const char* port)
{
    socket_.reset(new boost::asio::ip::tcp::socket(*io_service_));
    boost::asio::ip::tcp::resolver resolver(*io_service_);
    boost::asio::ip::tcp::resolver::query query(ipaddress, port);
    boost::asio::ip::tcp::resolver::iterator iterator 
    = resolver.resolve(query);
    boost::asio::ip::tcp::endpoint endpoint = *iterator;

    std::cout << "async_coect" << std::endl;
    socket_->async_coect(
        endpoint, boost::bind(&Client::handle_coect, shared_from_this(), 
            iterator, boost::asio::placeholders::error)
    );
}

bool Client::discoect()
{
    try
    {
        if(!coected_)
            retu true;
        socket_.reset();
        coected_ = false;
        retu true;
    }
    catch(boost::system::system_error& e)
    {
        retu false;
    }
}

bool Client::identify_user(const char* useame, const char* password)
{
/*...*/
}

void Client::handle_coect(boost::asio::ip::tcp::resolver::iterator 
    iterator, const boost::system::error_code& error)
{

    std::cout << "Handling coect" << std::endl;
    cs_sig(error);
    if(!error)
    {
        std::cout << "No error" << std::endl;
    }
    else if(error)
    {
        std::cout << "Error: " << error << std::endl;
    }
    if(iterator != boost::asio::ip::tcp::resolver::iterator())
    {
        std::cout << "Elseif iterator..." << std::endl;
        socket_->close();
        boost::asio::ip::tcp::endpoint endpoint = *iterator;
        socket_->async_coect(endpoint, boost::bind(&Client::handle_coect,
            shared_from_this(), ++iterator, boost::asio::placeholders::error
            )
        );
    }
}

void Client::handle_read(size_t bytes_transferred, 
    const boost::system::error_code& error)
{
/*...*/
}

void Client::handle_write(size_t bytes_transferred, 
    const boost::system::error_code& error)
{
/*...*/
}

void Client::read()
{
/*...*/
}

void Client::read_header()
{
/*...*/
}

void Client::write_header()
{
/*...*/
}

void Client::write()
{
/*...*/
}


void Client::start()
{
    if(thread_)
        retu;

    std::cout << "Creating new thread bruh" << std::endl;
    thread_.reset(new boost::thread(
        boost::bind(&boost::asio::io_service::run, io_service_)
    ));
    std::cout << "start Thread ID [" << boost::this_thread::get_id() << 
    "]" << std::endl;
}

void Client::stop()
{
    if(!thread_)
        retu;

    std::cout << "Ending" << std::endl;
    socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
    socket_->close();
    io_service_->stop();
    thread_->join();
    io_service_->reset();
    thread_.reset();
}

boost::signals2::coection Client::get_con_status(const coect_status_st& 
slot)
{
    retu cs_sig.coect(slot);
}

The important part is the constructor of the client. Those commented things and everything else is what I have been trying so far. Thanks to some altruist individuals at Boost's IRC chael I have understood what my problem is with that:

Apparently, io_service->post needs a 'nullary' function. And the bindings I do with Client::coect and its two placeholders make that function 'non-nullary'. If that was not enough, I try to bind the result of posting that function —which is void— to the slot of the signal. Therefore, the compiler complaints.

I thought about using functions somehow, in order to tu that 'nullary' function into 'non-nullary', and I also have been told about using lambdas. However I would like to stick to bind, if it is possible.

The questions are: Is it possible to make that function nullary? Is it possible to bind a post to a slot? Does this make sense?

Thank you very much indeed.

asked 42 secs ago

برچسب: نویسنده: استخدام کار تاريخ: شنبه 15 خرداد 1395 ساعت: 7:14

صفحه بندی