libtasks Documentation  1.6
test_exec.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 ADTECH GmbH
3  * Licensed under MIT (https://github.com/adtechlabs/libtasks/blob/master/COPYING)
4  *
5  * Author: Andreas Pohl
6  */
7 
8 #include <tasks/dispatcher.h>
9 #include <tasks/exec.h>
10 #include <tasks/executor.h> // for set_timeout
11 #include <atomic>
12 #include <mutex>
13 #include <condition_variable>
14 #include <set>
15 
16 #include "test_exec.h"
17 
18 std::mutex g_mutex;
19 std::condition_variable g_cond;
20 
21 namespace tasks {
22 
24  std::atomic<int> state(0);
25 
26  // create a task
27  auto t1 = new exec_task([&state] {
28  state = 1;
29  g_cond.notify_one();
30  });
31  dispatcher::instance()->add_task(t1);
32 
33  CPPUNIT_ASSERT_MESSAGE(std::string("state=") + std::to_string(state), check_state(state, 1));
34 
35  exec([&state] { state++; }, [&state] {
36  state++;
37  g_cond.notify_one();
38  });
39 
40  CPPUNIT_ASSERT_MESSAGE(std::string("state=") + std::to_string(state), check_state(state, 3));
41 
42  state = 0;
43  for (int i = 0; i < 1000; i++) {
44  exec([&state] {
45  state++;
46  g_cond.notify_one();
47  });
48  }
49 
50  CPPUNIT_ASSERT_MESSAGE(std::string("state=") + std::to_string(state), check_state(state, 1000));
51 
52  /* Deactivated as they are a bit unreliable because of all the sleeping.
53  // dispatcher tests
54  CPPUNIT_ASSERT_MESSAGE(std::string("size=") + std::to_string(dispatcher::instance()->m_executors.size()),
55  dispatcher::instance()->m_executors.size() == 1);
56  // save ref to the one executor
57  std::shared_ptr<executor> executor1 = dispatcher::instance()->free_executor();
58  executor1->m_busy = false;
59 
60  // use it
61  exec([] { std::this_thread::sleep_for(std::chrono::seconds(2)); });
62 
63  // create a new executor
64  std::shared_ptr<executor> executor2 = dispatcher::instance()->free_executor();
65  executor2->m_busy = false;
66 
67  // they should be different
68  CPPUNIT_ASSERT(executor1.get() != executor2.get());
69 
70  // use the second executor
71  exec([] { std::this_thread::sleep_for(std::chrono::seconds(2)); });
72 
73  // check that we have two
74  CPPUNIT_ASSERT_MESSAGE(std::string("size=") + std::to_string(dispatcher::instance()->m_executors.size()),
75  dispatcher::instance()->m_executors.size() == 2);
76 
77  // now let they all die
78  std::this_thread::sleep_for(std::chrono::seconds(10));
79 
80  // free_executor will clean up and create a new executor
81  std::shared_ptr<executor> executor3 = dispatcher::instance()->free_executor();
82  executor3->m_busy = false;
83 
84  CPPUNIT_ASSERT(executor1.get() != executor3.get());
85  CPPUNIT_ASSERT(executor2.get() != executor3.get());
86 
87  // we should be back to one now
88  CPPUNIT_ASSERT_MESSAGE(std::string("size=") + std::to_string(dispatcher::instance()->m_executors.size()),
89  dispatcher::instance()->m_executors.size() == 1);
90  */
91 }
92 
93 bool test_exec::check_state(std::atomic<int>& state, int expected) {
94  std::unique_lock<std::mutex> lock(g_mutex);
95  return g_cond.wait_for(lock, std::chrono::seconds(10), [&state, expected] { return state == expected; });
96 }
97 }
static std::shared_ptr< dispatcher > instance()
Definition: dispatcher.h:75
std::mutex g_mutex
Definition: test_exec.cpp:18
std::condition_variable g_cond
Definition: test_exec.cpp:19
void exec(exec_task::func_t f)
Execute code in a separate executor thread.
Definition: exec.cpp:14
bool check_state(std::atomic< int > &state, int expected)
Definition: test_exec.cpp:93