Skip to content

Commit

Permalink
Updated the Readme.md. Added flat version of chapter06 and script for…
Browse files Browse the repository at this point in the history
… flattening.
  • Loading branch information
apolukhin committed May 25, 2017
1 parent f7f451e commit f6540bb
Show file tree
Hide file tree
Showing 19 changed files with 2,162 additions and 9 deletions.
Expand Up @@ -17,7 +17,7 @@ class tasks_processor: public tp_network::tasks_processor {
);
}

// one thread is the current thread
// First thread is the current thread.
-- threads_count;

boost::asio::io_service& ios = get_ios();
Expand Down
@@ -0,0 +1,6 @@
if (!include(../../../config.txt)) {
error("Failed to open config.txt")
}

SOURCES += main.cpp
!msvc:LIBS += -lboost_thread -lboost_system
125 changes: 125 additions & 0 deletions Chapter06/flat/01_tasks_processor_base/main.cpp
@@ -0,0 +1,125 @@
// Amost all the code for this example is in this header

#include <boost/thread/thread.hpp>

namespace detail {

template <class T>
struct task_wrapped {
private:
T task_unwrapped_;

public:
explicit task_wrapped(const T& f)
: task_unwrapped_(f)
{}

void operator()() const {
// Resetting interruption.
try {
boost::this_thread::interruption_point();
} catch(const boost::thread_interrupted&){}

try {
// Executing task.
task_unwrapped_();
} catch (const std::exception& e) {
std::cerr<< "Exception: " << e.what() << '\n';
} catch (const boost::thread_interrupted&) {
std::cerr<< "Thread interrupted\n";
} catch (...) {
std::cerr<< "Unknown exception\n";
}
}
};

} // namespace detail

namespace detail {

template <class T>
task_wrapped<T> make_task_wrapped(const T& task_unwrapped) {
return task_wrapped<T>(task_unwrapped);
}

} // namespace detail


#include <boost/asio/io_service.hpp>
namespace tp_base {

class tasks_processor: private boost::noncopyable {
protected:
static boost::asio::io_service& get_ios() {
static boost::asio::io_service ios;
static boost::asio::io_service::work work(ios);

return ios;
}

public:
template <class T>
static void push_task(const T& task_unwrapped) {
get_ios().post(detail::make_task_wrapped(task_unwrapped));
}

static void start() {
get_ios().run();
}

static void stop() {
get_ios().stop();
}
}; // tasks_processor

} // namespace tp_base

using namespace tp_base;

int func_test() {
static int counter = 0;
++ counter;
boost::this_thread::interruption_point();

switch (counter) {
case 3:
throw std::logic_error("Just checking");

case 10:
// Emulation of thread interruption.
// Caught inside task_wrapped and does not stop execution.
throw boost::thread_interrupted();

case 90:
// Stopping the tasks_processor.
tasks_processor::stop();
}

return counter;
}

int main () {
for (std::size_t i = 0; i < 100; ++i) {
tasks_processor::push_task(&func_test);
}

// Processing was not started.
assert(func_test() == 1);

// We can also use lambda as a task.
#ifndef BOOST_NO_CXX11_LAMBDAS
// Counting 2 + 2 asynchronously.
int sum = 0;
tasks_processor::push_task(
[&sum]() { sum = 2 + 2; }
);
// Processing was not started.
assert(sum == 0);
#endif

// Does not throw, but blocks till
// one of the tasks it is owning
// calls tasks_processor::stop().
tasks_processor::start();
assert(func_test() == 91);
}
@@ -0,0 +1,7 @@
if (!include(../../../config.txt)) {
error("Failed to open config.txt")
}

SOURCES += main.cpp
QMAKE_CXXFLAGS += $$CPP11FLAG
!msvc:LIBS += -lboost_thread -lboost_system
189 changes: 189 additions & 0 deletions Chapter06/flat/02_tasks_processor_timers/main.cpp
@@ -0,0 +1,189 @@
// Almost all the code for this recipe
// is in this header file.


#include <boost/thread/thread.hpp>

namespace detail {

template <class T>
struct task_wrapped {
private:
T task_unwrapped_;

public:
explicit task_wrapped(const T& f)
: task_unwrapped_(f)
{}

void operator()() const {
// Resetting interruption.
try {
boost::this_thread::interruption_point();
} catch(const boost::thread_interrupted&){}

try {
// Executing task.
task_unwrapped_();
} catch (const std::exception& e) {
std::cerr<< "Exception: " << e.what() << '\n';
} catch (const boost::thread_interrupted&) {
std::cerr<< "Thread interrupted\n";
} catch (...) {
std::cerr<< "Unknown exception\n";
}
}
};

} // namespace detail

namespace detail {

template <class T>
task_wrapped<T> make_task_wrapped(const T& task_unwrapped) {
return task_wrapped<T>(task_unwrapped);
}

} // namespace detail


#include <boost/asio/io_service.hpp>
namespace tp_base {

class tasks_processor: private boost::noncopyable {
protected:
static boost::asio::io_service& get_ios() {
static boost::asio::io_service ios;
static boost::asio::io_service::work work(ios);

return ios;
}

public:
template <class T>
static void push_task(const T& task_unwrapped) {
get_ios().post(detail::make_task_wrapped(task_unwrapped));
}

static void start() {
get_ios().run();
}

static void stop() {
get_ios().stop();
}
}; // tasks_processor

} // namespace tp_base


#include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/system/error_code.hpp>
#include <memory> // std::unique_ptr
#include <iostream>

namespace detail {

template <class Functor>
struct timer_task {
private:
std::unique_ptr<boost::asio::deadline_timer> timer_;
task_wrapped<Functor> task_;

public:
explicit timer_task(
std::unique_ptr<boost::asio::deadline_timer> timer,
const Functor& task_unwrapped)
: timer_(std::move(timer))
, task_(task_unwrapped)
{}

void operator()(const boost::system::error_code& error) const {
if (!error) {
task_();
} else {
std::cerr << error << '\n';
}
}
};

} // namespace detail

namespace tp_timers {

class tasks_processor: public tp_base::tasks_processor {
public:

template <class Time, class Functor>
static void run_delayed(Time duration_or_time, const Functor& f) {
std::unique_ptr<boost::asio::deadline_timer> timer(
new boost::asio::deadline_timer(
get_ios(), duration_or_time
)
);

boost::asio::deadline_timer& timer_ref = *timer;

timer_ref.async_wait(
detail::timer_task<Functor>(
std::move(timer),
f
)
);
}
};

} // namespace tp_timers

using namespace tp_timers;

struct test_functor {
int& i_;

explicit test_functor(int& i);

void operator()() const {
i_ = 1;
tasks_processor::stop();
}
};

void test_func1();

#include <boost/date_time/posix_time/posix_time.hpp>

int main () {
const int seconds_to_wait = 3;
int i = 0;

tasks_processor::run_delayed(
boost::posix_time::seconds(seconds_to_wait),
test_functor(i)
);

tasks_processor::run_delayed(
boost::posix_time::from_time_t(time(NULL) + 1),
&test_func1
);

int t1 = static_cast<int>(time(NULL));
assert(i == 0);

// Blocks till one of the tasks
// calls tasks_processor::stop().
tasks_processor::start();

assert(i == 1);
int t2 = static_cast<int>(time(NULL));
assert(t2 - t1 >= seconds_to_wait);
}


test_functor::test_functor(int& i)
: i_(i)
{}

void test_func1() {
throw std::logic_error("It works!");
}
@@ -0,0 +1,8 @@
if (!include(../../../config.txt)) {
error("Failed to open config.txt")
}

SOURCES += main.cpp

QMAKE_CXXFLAGS += $$CPP11FLAG
!msvc:LIBS += -lboost_thread -lboost_system

0 comments on commit f6540bb

Please sign in to comment.