Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated the Readme.md. Added flat version of chapter06 and script for…
… flattening.
- Loading branch information
Showing
19 changed files
with
2,162 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
Chapter06/flat/01_tasks_processor_base/01_tasks_processor_base.pro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
if (!include(../../../config.txt)) { | ||
error("Failed to open config.txt") | ||
} | ||
|
||
SOURCES += main.cpp | ||
!msvc:LIBS += -lboost_thread -lboost_system |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
7 changes: 7 additions & 0 deletions
7
Chapter06/flat/02_tasks_processor_timers/02_tasks_processor_timers.pro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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!"); | ||
} |
8 changes: 8 additions & 0 deletions
8
Chapter06/flat/04_tasks_processor_network_accept/04_tasks_processor_network_accept.pro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.