Simple example
Below you can find source code of a simple example that uses main features of
the libbase
library. This example is located in the /examples/simple/
directory in the repository and - if
enabled - will be built along the
libbase
library itself.
CMakeLists.txt
1add_executable(simple "")
2
3target_compile_options(simple
4 PRIVATE
5 ${LIBBASE_COMPILE_FLAGS}
6)
7
8target_link_libraries(simple
9 PRIVATE
10 libbase
11)
12
13target_sources(simple
14 PRIVATE
15 main.cc
16)
main.cc
1#include <thread>
2
3#include "base/bind.h"
4#include "base/init.h"
5#include "base/logging.h"
6#include "base/synchronization/auto_signaller.h"
7#include "base/synchronization/waitable_event.h"
8#include "base/threading/thread.h"
9#include "base/threading/thread_pool.h"
10#include "base/timer/elapsed_timer.h"
11#include "base/trace_event/trace_event.h"
12#include "base/trace_event/trace_flow.h"
13#include "base/trace_event/trace_flush.h"
14
15namespace {
16std::shared_ptr<base::SequencedTaskRunner> tr1;
17std::shared_ptr<base::SequencedTaskRunner> tr2;
18} // namespace
19
20void Task1(std::shared_ptr<base::TaskRunner> current,
21 std::shared_ptr<base::TaskRunner> next,
22 base::WaitableEvent* five_left_event,
23 base::AutoSignaller finished_event,
24 int n) {
25 CHECK_GE(n, 0) << "`n` must be greater or equal to 0";
26 TRACE_EVENT("thread_example", "task1", "n", std::to_string(n));
27 TRACE_EVENT_WITH_FLOW_STEP("thread_example", "flow:ThreadExample", &tr1);
28 LOG(INFO) << __FUNCTION__ << "() Writing from thread "
29 << std::this_thread::get_id() << " with n=" << n
30 << "(tr1: " << tr1->RunsTasksInCurrentSequence()
31 << ", tr2: " << tr2->RunsTasksInCurrentSequence() << ")"
32 << std::endl;
33
34 if (n == 5) {
35 five_left_event->Signal();
36 }
37 if (n > 0) {
38 next->PostTask(FROM_HERE,
39 base::BindOnce(&Task1, next, current, five_left_event,
40 std::move(finished_event), n - 1));
41 }
42}
43
44void ThreadExample() {
45 TRACE_EVENT("thread_example", "ThreadExample");
46 base::Thread t1{};
47 base::Thread t2{};
48
49 t1.Start();
50 t2.Start();
51
52 tr1 = t1.TaskRunner();
53 tr2 = t2.TaskRunner();
54
55 base::WaitableEvent five_left_event{};
56 base::WaitableEvent finished_event{};
57
58 {
59 TRACE_EVENT("thread_example", "Async work start");
60 TRACE_EVENT_WITH_FLOW_BEGIN("thread_example", "flow:ThreadExample", &tr1);
61 tr1->PostTask(FROM_HERE,
62 base::BindOnce(&Task1, tr1, tr2, &five_left_event,
63 base::AutoSignaller{&finished_event}, 10));
64 }
65
66 five_left_event.Wait();
67 LOG(INFO) << __FUNCTION__ << "() (at most 5 calls left)...";
68 finished_event.Wait();
69 LOG(INFO) << __FUNCTION__ << "() finished";
70
71 {
72 TRACE_EVENT_WITH_FLOW_END("thread_example", "flow:ThreadExample", &tr1);
73 TRACE_EVENT("thread_example", "Async work done");
74 }
75 t2.Stop();
76 t1.Stop();
77}
78
79void ThreadDelayedExample() {
80 base::Thread thread{};
81 base::WaitableEvent finished_event{};
82
83 thread.Start();
84
85 thread.TaskRunner()->PostDelayedTask(
86 FROM_HERE,
87 base::BindOnce(
88 []([[maybe_unused]] base::AutoSignaller finished_signaller) {
89 LOG(INFO)
90 << "ThreadDelayedExample() delayed (300ms) task executing";
91 },
92 base::AutoSignaller{&finished_event}),
93 base::Milliseconds(300));
94
95 thread.TaskRunner()->PostTask(
96 FROM_HERE, base::BindOnce([]() {
97 LOG(INFO) << "ThreadDelayedExample() non-delayed task executing";
98 }));
99
100 thread.TaskRunner()->PostDelayedTask(
101 FROM_HERE, base::BindOnce([]() {
102 LOG(INFO) << "ThreadDelayedExample() delayed (100ms) task executing";
103 }),
104 base::Milliseconds(100));
105
106 finished_event.Wait();
107 LOG(INFO) << __FUNCTION__ << "() finished";
108
109 thread.Stop();
110}
111
112void ThreadPoolNonSequencedExample() {
113 base::ThreadPool pool{1};
114 pool.Start();
115
116 auto generic_tr1 = pool.GetTaskRunner();
117
118 pool.Stop();
119}
120
121void ThreadPoolSequencedExample() {
122 base::ThreadPool pool{4};
123 pool.Start();
124
125 auto sequenced_tr1 = pool.CreateSequencedTaskRunner();
126 auto sequenced_tr2 = pool.CreateSequencedTaskRunner();
127
128 pool.Stop();
129}
130
131void ThreadPoolSingleThreadExample() {
132 base::ThreadPool pool{4};
133 pool.Start();
134
135 auto single_thread_tr1 = pool.CreateSingleThreadTaskRunner();
136
137 pool.Stop();
138}
139
140int main(int argc, char* argv[]) {
141 base::Initialize(argc, argv, base::InitOptions{});
142
143 const auto timer = base::ElapsedTimer{};
144
145 ThreadExample();
146 ThreadDelayedExample();
147 ThreadPoolNonSequencedExample();
148 ThreadPoolSequencedExample();
149 ThreadPoolSingleThreadExample();
150
151 LOG(INFO) << "Example finished in " << timer.Elapsed().InMillisecondsF()
152 << "ms";
153 TRACE_EVENT_FLUSH_TO_STREAM(LOG(INFO) << "Trace:\n");
154
155 base::Deinitialize();
156 return 0;
157}