I want to use Qtimer to pause executing of given block of codes, while in another thread it does something else. I connected the timeout of the thread with qeventloop quit, but the problem is, that the timeout is not called. When another emit occures, the timeout is magically triggered or if I add another connect the time out is triggered too. I think I miss something about the use of qtimer, qeventloop and qthread. Can anyone help? I extracted the basic code for testing and put it here:
main.cpp
#include "widget.h"
#include <QApplication>
#include "tim.h"
#include <QThread>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget *w=new Widget();
tim *t=new tim();
QThread *thread=new QThread();
t->moveToThread(thread);
thread->start();
QThread::connect(w,SIGNAL(signalDoIt()),t,SLOT(slotDoIt()),Qt::QueuedConnection);
QThread::connect(w,SIGNAL(signalQuitTimer()),t,SLOT(slotQuitTimer()),Qt::QueuedConnection);
QThread::connect(t,SIGNAL(signalSetText(QString)),w,SLOT(slotSetText(QString)),Qt::QueuedConnection);
w->show();
return a.exec();
}
tim.h
#ifndef TIM_H
#define TIM_H
#include <QObject>
#include<QTimer>
#include<QTime>
#include<QEventLoop>
#include<QThread>
#include<QDebug>
class tim : public QObject
{
Q_OBJECT
public:
tim();
~tim();
signals:
void signalSetText(QString);
public slots:
void slotDoIt();
void slotQuitTimer();
void slotShowTime();
private:
QTimer *trainingTimer;
QEventLoop loopTrainingWait;
QTime time;
};
#endif // TIM_H
tim.cpp
#include "tim.h"
tim::tim()
{
qDebug()<<"constructor";
trainingTimer=new QTimer(this);
trainingTimer->setTimerType(Qt::PreciseTimer);
trainingTimer->setSingleShot(true);
QThread::connect(trainingTimer,SIGNAL(timeout()),&loopTrainingWait,SLOT(quit()));
// QThread::connect(trainingTimer,SIGNAL(timeout()),this,SLOT(slotShowTime())); //to uncomment all works, but withou this, it does not
}
void tim::slotDoIt()
{
trainingTimer->start(5000);
time.start();
loopTrainingWait.exec();
QString text(QString::number(loopTrainingWait.isRunning())+" "+ QString::number(time.elapsed()));
qDebug()<<text;
emit signalSetText(text);
}
void tim::slotShowTime()
{
QString text(QString::number(loopTrainingWait.isRunning())+" slot "+ QString::number(time.elapsed()));
qDebug()<<text;
emit signalSetText(text);
}
void tim::slotQuitTimer()
{
if(loopTrainingWait.isRunning())
loopTrainingWait.quit();
if(trainingTimer->isActive())
trainingTimer->stop();
}
tim::~tim()
{
}
//gui for testing
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
void slotSetText(QString text);
signals:
void signalDoIt();
void signalQuitTimer();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
void Widget::slotSetText(QString text)
{
ui->label->setText(text);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
this->close();
}
void Widget::on_pushButton_2_clicked()
{
emit signalDoIt();
}
void Widget::on_pushButton_3_clicked()
{
emit signalQuitTimer();
}
I met the same issue,and eventually I wrote SLOT between public and :,then it works
the problem was in static qeventloop, making this dynamic
loopTrainingWait=new QEventLoop(this);
with parent this, resolved the issue
Related
For some fun purposes, I'm writing a Tetris game. I created two classes: "GameBackground" and "Tetromino". Since the "Tetromino" class has a dependency on the "GameBackground" class, I injected this dependency in the constructor using an interface such that I can test the "Tetromino" class independent of the GameBackground class by mocking it. When I use gmock to create the "GameBackgroundMock", the test fails. When I use my own mock like
class MyOwnMock : public IGameBackground {
public:
MyOwnMock() : IGameBackground() {
};
bool RequestSpaceOnGrid(TetrominoPositionType requested_coordinates) override{
return true;
}
};
then the test passes. Apparently, I don't use the gmock in the right way. I would appreciate any suggestion leading to a green test by using gmock.
For implementation details see the following code basis.
My initial folder structure looks as follows:
[Project structure][1]
[1]: https://i.stack.imgur.com/7h8zT.png
The corresponding files at the project's top-level:
CMakeLists.txt.in:
# see https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
CMakeLists.txt:
cmake_minimum_required(VERSION 3.11.3)
project(Test)
set(CMAKE_CXX_STANDARD 17)
# Download and unpack googletest at configure time
# (see https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project)
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Add googletest directly to our build. This defines the gtest and gtest_main targets.
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
add_subdirectory(src)
add_subdirectory(test)
The content of the src folder:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.11.3)
add_library(GameBackground_Lib STATIC GameBackground.cpp)
add_library(Tetromino_Lib STATIC Tetromino.cpp)
IGameBackground.h
#ifndef TEST_IGAMEBACKGROUND_H
#define TEST_IGAMEBACKGROUND_H
#include <utility>
#include <vector>
#include <iostream>
using TetrominoPositionType = std::vector<std::pair<int, int>>;
class IGameBackground {
public:
virtual ~IGameBackground() = default;
virtual bool RequestSpaceOnGrid(TetrominoPositionType) = 0;
};
#endif //TEST_IGAMEBACKGROUND_H
GameBackground.h
#ifndef TEST_GAMEBACKGROUND_H
#define TEST_GAMEBACKGROUND_H
#include "IGameBackground.h"
#include <tuple>
#include <utility>
#include <vector>
class GameBackground : public IGameBackground {
public:
GameBackground(int, int);
bool RequestSpaceOnGrid(TetrominoPositionType) override;
private:
int m_horizontal_grid_size;
int m_vertical_grid_size;
int m_nr_buttomlines_filled{};
std::vector<std::vector<bool>> m_occupancy_grid{};
};
#endif //TEST_GAMEBACKGROUND_H
GameBackground.cpp
#include "GameBackground.h"
GameBackground::GameBackground(int vertical_grid_size, int horizontal_grid_size)
: m_horizontal_grid_size{horizontal_grid_size},
m_vertical_grid_size{vertical_grid_size} {
m_occupancy_grid.resize(vertical_grid_size);
for (auto &row : m_occupancy_grid) {
row.resize(horizontal_grid_size);
}
}
bool GameBackground::RequestSpaceOnGrid(
TetrominoPositionType requested_coordinates) {
bool is_every_coordinate_within_bounds{true};
for (const auto &position : requested_coordinates) {
int pos_x{position.first}, pos_y{position.second};
if (pos_x < 0 || pos_x >= m_vertical_grid_size || pos_y < 0 ||
pos_y >= m_horizontal_grid_size) {
is_every_coordinate_within_bounds = false;
break;
}
}
bool is_request_successfull{false};
if (is_every_coordinate_within_bounds) {
try {
bool is_occupied{false};
for (const auto &position : requested_coordinates) {
int row{position.first}, column{position.second};
is_occupied |= m_occupancy_grid.at(row).at(column);
}
if (!is_occupied) {
for (const auto &position : requested_coordinates) {
int row{position.first}, column{position.second};
m_occupancy_grid.at(row).at(column) = true;
}
is_request_successfull = true;
}
} catch (std::out_of_range const &e) {
std::cerr << e.what() << '\n';
}
}
return is_request_successfull;
}
Tetromino.h
#ifndef TEST_TETROMINO_H
#define TEST_TETROMINO_H
#include <memory>
#include <utility>
#include <vector>
#include "IGameBackground.h"
enum class Direction { left, right, down };
using TetrominoPositionType = std::vector<std::pair<int, int>>;
class Tetromino {
public:
Tetromino(IGameBackground&, TetrominoPositionType);
TetrominoPositionType getPosition();
void setPosition(TetrominoPositionType);
void moveOneStep(Direction);
private:
TetrominoPositionType m_position;
IGameBackground& m_game_background;
};
#endif //TEST_TETROMINO_H
Tetromino.cpp
#include "Tetromino.h"
#include <utility>
Tetromino::Tetromino(IGameBackground &game_background,
TetrominoPositionType init_position)
: m_game_background{game_background},
m_position{std::move(init_position)} {};
TetrominoPositionType Tetromino::getPosition() { return m_position; }
void Tetromino::setPosition(TetrominoPositionType position) {
m_position = std::move(position);
}
void Tetromino::moveOneStep(Direction direction) {
TetrominoPositionType position = getPosition();
switch (direction) {
case Direction::down:
for (auto &pos : position) {
++pos.first;
}
if (m_game_background.RequestSpaceOnGrid(position)) {
setPosition(position);
}
break;
case Direction::left:
for (auto &pos : position) {
--pos.second;
}
if (m_game_background.RequestSpaceOnGrid(position)) {
setPosition(position);
}
break;
case Direction::right:
for (auto &pos : position) {
++pos.second;
}
if (m_game_background.RequestSpaceOnGrid(position)) {
setPosition(position);
}
break;
}
}
The content of the test folder
CMakeLists.txt
cmake_minimum_required(VERSION 3.11.3)
add_executable(TetrominoTest TetrominoTest.cpp)
target_link_libraries(TetrominoTest gmock_main gtest_main Tetromino_Lib)
TetrominoTest.cpp
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "../src/IGameBackground.h"
#include "../src/Tetromino.h"
//class MyOwnMock : public IGameBackground {
//public:
// MyOwnMock() : IGameBackground() {
// };
// bool RequestSpaceOnGrid(TetrominoPositionType requested_coordinates) override{
// return true;
// }
//};
class GameBackgroundMock : public IGameBackground {
public:
GameBackgroundMock() : IGameBackground() {
};
MOCK_METHOD(bool, RequestSpaceOnGrid,
(TetrominoPositionType requested_coordinates), (override));
};
class MoveTetromino : public ::testing::Test {
protected:
MoveTetromino() : unit_under_test(a_mock, init_position) {};
TetrominoPositionType init_position{{0, 0},
{0, 1},
{0, 2},
{0, 3}};
Tetromino unit_under_test;
GameBackgroundMock a_mock;
//MyOwnMock a_mock;
};
TEST_F(MoveTetromino, move_right) {
TetrominoPositionType current_position{init_position};
TetrominoPositionType expected_position{init_position};
for (auto &elem : expected_position) {
elem.second++;
}
ON_CALL(a_mock, RequestSpaceOnGrid(current_position)).WillByDefault(::testing::Return(true));
unit_under_test.moveOneStep(Direction::right);
TetrominoPositionType actual_position = unit_under_test.getPosition();
EXPECT_EQ(expected_position, actual_position);
}
You're using ON_CALL which sets a default value to be returned when a mocked method is being called. This is useful if you don't care how many times given method will be called in your tests and you just set a default value to be returned any number of times (however, expect calls are being matched first, it's a longer story).
It's better to use EXPECT_CALL in your case to explicitly state what actions you anticipate and validate them:
EXPECT_CALL(a_mock, RequestSpaceOnGrid(current_position)).WillOnce(::testing::Return(true));
If you will use this, gmock will let you know what's wrong with the test: the RequestSpaceOnGrid was called, however not with current_position but with expected_position. Not sure if this is expected, but this is what happens in the test.
The test passes by calling either
ON_CALL(a_mock, RequestSpaceOnGrid(expected_position)).WillByDefault(::testing::Return(true));
or as Quarra suggested
EXPECT_CALL(a_mock, RequestSpaceOnGrid(expected_position)).WillOnce(::testing::Return(true));
The crucial point was to give expected_position instead of current_position to the mocked RequestSpaceOnGrid method.
Another possibility would be to get the test green to call the mocked method with ::testing::_
ON_CALL(a_mock, RequestSpaceOnGrid(::testing::_)).WillByDefault(::testing::Return(true));
In this case, the mocked method would always return true independent of the given argument.
#ifndef CAMERAHANDLER_H_
#define CAMERAHANDLER_H_
#include <QtCore/QObject>
class CameraHandler: public QObject
{
Q_OBJECT
public:
//… constructor destructor etc
void setupControls(const QString &camName, const QString &vfButtonName);
Q_INVOKABLE void camerastart();
Q_INVOKABLE void camerastop();
private slots:
void onOpenSuccess(); //when camera is opened successfully
void onShutterFired(); //when we get shutterfired event
void onButtonClick(); //when the button is clicked
void onStopVfSuccess(); //when viewfinder has been stopped
void onStartVfSuccess(); //when viewfinder has been started
private:
Camera* m_camera;
Button* m_camButton;
bool m_ViewfinderOn;
bool m_cameraopen;
//const bb::cascades::AbstractPane *m_abstractPane;
};
#endif /* CAMERAHANDLER_H_ */
I have file Camerahandler.h file in src folder Cascades Framework to develop BB10 app.
But i receive error "'Camera' does not name a type" & "'Button' does not name a
type". Please help me fix!
How about if you add these two?
#include <bb/cascades/multimedia/Camera>
#include <bb/cascades/Button>
How do I fix this error:
undefined reference to button sensor
when compiling example-mesh.c using Micaz mote in contiki?
Here is my code I run the simulation in the mote output window only 3 messages are sent while the rest is " packet timedout " how can I solve that problem to send messages based on timer value ?
#include "contiki.h"
#include "net/rime.h"
#include "net/rime/mesh.h"
#include "contiki-conf.h"
#include "sys/etimer.h"
#include "sys/process.h"
#include "sys/ctimer.h"
#include "dev/leds.h"
#include <stdio.h>
#include <string.h>
#define MESSAGE "Hello"
static struct mesh_conn mesh;
/*---------------------------------------------------------------------------*/
PROCESS(example_mesh_process, "Mesh example");
AUTOSTART_PROCESSES(&example_mesh_process);
/*---------------------------------------------------------------------------*/
static void
sent(struct mesh_conn *c)
{
printf("packet sent\n");
}
static void
timedout(struct mesh_conn *c)
{
printf("packet timedout\n");
}
static void
recv(struct mesh_conn *c, const rimeaddr_t *from, uint8_t hops)
{
printf("Data received from %d.%d: %.*s (%d)\n",
from->u8[0], from->u8[1],
packetbuf_datalen(), (char *)packetbuf_dataptr(), packetbuf_datalen());
packetbuf_copyfrom(MESSAGE, strlen(MESSAGE));
mesh_send(&mesh, from);
}
const static struct mesh_callbacks callbacks = {recv, sent, timedout};
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_mesh_process, ev, data)
{
static struct etimer et;
PROCESS_EXITHANDLER(mesh_close(&mesh);)
PROCESS_BEGIN();
mesh_open(&mesh, 132, &callbacks);
while(1) {
rimeaddr_t addr;
etimer_set(&et, 5 * CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
etimer_reset(&et);
/* Send a message to node number 1. */
packetbuf_copyfrom(MESSAGE, strlen(MESSAGE));
addr.u8[0] = 1;
addr.u8[1] = 0;
mesh_send(&mesh, &addr);
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
As far as I know the Micaz mote does not have a button and therefore the reference to the button_sensor sensor is not valid.
The example is designed to send a message every time the button is pressed so if you want this example to work you need to rewrite the example to send messages based on a timer value.
This is how I would write it. However this node is dependent on another node that needs to accept the messages!
#include "contiki.h"
#include "net/rime.h"
#include "net/rime/mesh.h"
#include <stdio.h>
#include <string.h>
#define MESSAGE "Hello"
static struct mesh_conn mesh;
/*---------------------------------------------------------------------------*/
PROCESS(example_mesh_process, "Mesh example");
AUTOSTART_PROCESSES(&example_mesh_process);
/*---------------------------------------------------------------------------*/
static void
sent(struct mesh_conn *c)
{
printf("packet sent\n");
}
static void
timedout(struct mesh_conn *c)
{
printf("packet timedout\n");
}
static void
recv(struct mesh_conn *c, const rimeaddr_t *from, uint8_t hops)
{
printf("Data received from %d.%d: %.*s (%d)\n",
from->u8[0], from->u8[1],
packetbuf_datalen(), (char *)packetbuf_dataptr(), packetbuf_datalen());
packetbuf_copyfrom(MESSAGE, strlen(MESSAGE));
mesh_send(&mesh, from);
}
const static struct mesh_callbacks callbacks = {recv, sent, timedout};
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_mesh_process, ev, data)
{
static struct etimer et;
PROCESS_EXITHANDLER(mesh_close(&mesh);)
PROCESS_BEGIN();
mesh_open(&mesh, 132, &callbacks);
while(1) {
linkaddr_t addr;
etimer_set(&et, 5 * CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
/* Send a message to node number 1. */
packetbuf_copyfrom(MESSAGE, strlen(MESSAGE));
addr.u8[0] = 1;
addr.u8[1] = 0;
mesh_send(&mesh, &addr);
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
I am using Qt 5.3 and trying to develop application for IOS.
Problem is, QWidget application in a iPhone Retina simulator:
QMessage becomes full-screen.
In Application output panel I see: This plugin does not support
propagateSizeHints().
So looking for alternative solution for QMessageBox. I don't want to learn QML yet.
If you do an overlay on top of your widget you can make something similar to the iOS popups.
Basically you create another widget, and you parent it to the widget you want it to be drawn on top of.
Here are some helpful flags and lines of code to put in your overlay constructor:
setPalette(Qt::transparent);
// if you have buttons on this overlay you probably don't want this one
setAttribute(Qt::WA_TransparentForMouseEvents);
QGraphicsDropShadowEffect * dse = new QGraphicsDropShadowEffect();
dse->setBlurRadius(20);
this->setGraphicsEffect(dse);
Then be sure to command a resize of your overlay when the parent widget resizes:
void ParentWidget::resizeEvent(QResizeEvent *event)
{
overlay->resize(event->size());
event->accept();
}
http://www.qtcentre.org/wiki/index.php?title=Widget_Overlay
UPDATE: Awesome example
main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
w.resize(300,600);
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "overlaydialogbox.h"
#include <QResizeEvent>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void resizeEvent(QResizeEvent *event);
private:
OverlayDialogBox * m_overlay;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_overlay = new OverlayDialogBox(this);
}
MainWindow::~MainWindow() { }
void MainWindow::resizeEvent(QResizeEvent *event)
{
m_overlay->resize(event->size());
event->accept();
}
overlaydialogbox.h
#ifndef OVERLAYDIALOGBOX_H
#define OVERLAYDIALOGBOX_H
#include <QWidget>
class OverlayDialogBox : public QWidget
{
Q_OBJECT
public:
explicit OverlayDialogBox(QWidget *parent = 0);
signals:
void accepted();
void rejected();
void finished(int);
public slots:
};
#endif // OVERLAYDIALOGBOX_H
overlaydialogbox.cpp
#include "overlaydialogbox.h"
#include <QGridLayout>
#include <QGraphicsEffect>
#include <QLabel>
#include <QDialogButtonBox>
#include <QMessageBox>
#include <QIcon>
OverlayDialogBox::OverlayDialogBox(QWidget *parent) :
QWidget(parent)
{
setPalette(Qt::transparent);
// if you have buttons on this overlay you probably don't want this one
// setAttribute(Qt::WA_TransparentForMouseEvents);
QGraphicsDropShadowEffect * dse = new QGraphicsDropShadowEffect();
dse->setBlurRadius(20);
this->setGraphicsEffect(dse);
QGridLayout * grid = new QGridLayout();
this->setLayout(grid);
QMessageBox * msg = new QMessageBox(QMessageBox::Warning,"Testing","This is a test QMessageBox.");
QObject::connect(msg, SIGNAL(accepted()), this, SIGNAL(accepted()));
QObject::connect(msg, SIGNAL(finished(int)), this, SIGNAL(finished(int)));
QObject::connect(msg, SIGNAL(rejected()), this, SIGNAL(rejected()));
QObject::connect(msg, SIGNAL(finished(int)), this, SLOT(close()));
msg->setPalette(Qt::white);
grid->addWidget(msg);
}
Hope that helps.
This questions is a bit annoying, I can't get the following code to compile. You will have to compile the code below.
I am having some trouble with boost asio, I am trying to abstract the logic of accepting connections into a uniform abstraction so that I can initiate connection for windows named-pipes and Unix domain sockets uniformly with regular TCP/IP.
There are 3 classes shown in the code below, the first 2 are the implementations of acceping TCP connections, and the third class below is a generic class that is implemented in terms of the first 2. I am having troubles with boost::bind calls. The trouble probably lies with my understanding of the semantics.
If I make TcpDestinationAcceptor::handle_accept a regular member function (--i.e., not a template member function) which results in me not passing the AcceptHandler parameter. The code compiles fine. Note: I do not remove the template function status from TcpDestinationAcceptor::StartAccepting.
Note: I have already started on a different design, still I would like to pursue this design if possible.
Self contained code:
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/asio/placeholders.hpp>
class TcpDestinationConnection
{
public:
typedef boost::asio::ip::tcp::socket t_io_object;
TcpDestinationConnection(boost::asio::io_service & io_s)
: m_io_object(io_s) {} ;
t_io_object & io_object() { return m_io_object; }
private:
t_io_object m_io_object;
};
class TcpDestinationAcceptor
{
public:
typedef boost::asio::ip::tcp::acceptor t_acceptor;
typedef boost::shared_ptr<TcpDestinationConnection> t_connection_ptr;
TcpDestinationAcceptor( boost::asio::io_service & io_s)
: m_io_service(io_s),
m_acceptor(io_s)
{
m_acceptor.open(boost::asio::ip::tcp::v4());
}
TcpDestinationAcceptor( boost::asio::io_service & io_s ,
const boost::asio::ip::tcp::endpoint & endpoint)
: m_io_service(io_s),
m_acceptor(io_s, endpoint)
{
m_acceptor.open(boost::asio::ip::tcp::v4());
}
t_acceptor & acceptor() { return m_acceptor; }
template<typename AcceptHandler>
void StartAccepting(AcceptHandler h)
{
t_connection_ptr new_session(new TcpDestinationConnection(m_io_service));
m_acceptor.async_accept( new_session->io_object(),
boost::bind( &TcpDestinationAcceptor::handle_accept<AcceptHandler>, this,
boost::asio::placeholders::error, new_session, h));
}
template<typename AcceptHandler>
void handle_accept(const boost::system::error_code & err, t_connection_ptr cur, AcceptHandler h) {
}
private:
boost::asio::io_service & m_io_service;
boost::asio::ip::tcp::acceptor m_acceptor;
};
template<typename t_acceptor>
class ConnectionOracle
{
public:
ConnectionOracle()
: m_io_service(),
m_acceptor(m_io_service) {}
typename t_acceptor::t_acceptor & native_acceptor() { return m_acceptor.acceptor(); }
boost::asio::io_service & io_service() { return m_io_service; }
void StartConnection( typename t_acceptor::t_connection_ptr connection,
boost::system::error_code & error)
{
}
void Begin()
{
m_acceptor.StartAccepting( boost::bind( &ConnectionOracle::StartConnection,this,
_1,
boost::asio::placeholders::error));
m_io_service.run();
}
private:
boost::asio::io_service m_io_service;
t_acceptor m_acceptor;
};
int main()
{
ConnectionOracle<TcpDestinationAcceptor> ConOracle;
ConOracle.native_acceptor().
bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),50000));
ConOracle.Begin();
return 0;
}