• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 21808757328

08 Feb 2026 08:39PM UTC coverage: 90.075% (-1.6%) from 91.642%
21808757328

push

github

web-flow
Merge pull request #5300 from KaganCanSit/remove-unnecessary-includes

IWYU - Remove unnecessary header includes to improve build performance

102250 of 113517 relevant lines covered (90.07%)

11519008.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.07
/src/lib/filters/threaded_fork.cpp
1
/*
2
* Threaded Fork
3
* (C) 2013 Joel Low
4
*     2013 Jack Lloyd
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/filters.h>
10

11
#if defined(BOTAN_HAS_THREAD_UTILS)
12

13
   #include <botan/internal/barrier.h>
14
   #include <botan/internal/semaphore.h>
15

16
namespace Botan {
17

18
struct Threaded_Fork_Data {
2✔
19
      /*
20
   * Semaphore for indicating that there is work to be done (or to
21
   * quit)
22
   */
23
      Semaphore m_input_ready_semaphore;
24

25
      /*
26
   * Synchronises all threads to complete processing data in lock-step.
27
   */
28
      Barrier m_input_complete_barrier;
29

30
      /*
31
   * The work that needs to be done. This should be only when the threads
32
   * are NOT running (i.e. before notifying the work condition, after
33
   * the input_complete_barrier has reset.)
34
   */
35
      const uint8_t* m_input = nullptr;
36

37
      /*
38
   * The length of the work that needs to be done.
39
   */
40
      size_t m_input_length = 0;
41
};
42

43
/*
44
* Threaded_Fork constructor
45
*/
46
Threaded_Fork::Threaded_Fork(Filter* f1, Filter* f2, Filter* f3, Filter* f4) :
1✔
47
      Fork(nullptr, static_cast<size_t>(0)), m_thread_data(new Threaded_Fork_Data) {
1✔
48
   Filter* filters[4] = {f1, f2, f3, f4};
1✔
49
   set_next(filters, 4);
1✔
50
}
1✔
51

52
/*
53
* Threaded_Fork constructor
54
*/
55
Threaded_Fork::Threaded_Fork(Filter* filters[], size_t count) :
1✔
56
      Fork(nullptr, static_cast<size_t>(0)), m_thread_data(new Threaded_Fork_Data) {
1✔
57
   set_next(filters, count);
1✔
58
}
1✔
59

60
Threaded_Fork::~Threaded_Fork() {
4✔
61
   m_thread_data->m_input = nullptr;
2✔
62
   m_thread_data->m_input_length = 0;
2✔
63

64
   m_thread_data->m_input_ready_semaphore.release(m_threads.size());
2✔
65

66
   for(auto& thread : m_threads) {
9✔
67
      thread->join();
7✔
68
   }
69
}
6✔
70

71
std::string Threaded_Fork::name() const {
×
72
   return "Threaded Fork";
×
73
}
74

75
void Threaded_Fork::set_next(Filter* f[], size_t n) {
2✔
76
   Fork::set_next(f, n);
2✔
77
   n = m_next.size();
2✔
78

79
   if(n < m_threads.size()) {
2✔
80
      m_threads.resize(n);
×
81
   } else {
82
      m_threads.reserve(n);
2✔
83
      for(size_t i = m_threads.size(); i != n; ++i) {
9✔
84
         m_threads.push_back(std::make_shared<std::thread>([this, next = m_next[i]] { thread_entry(next); }));
14✔
85
      }
86
   }
87
}
2✔
88

89
void Threaded_Fork::send(const uint8_t input[], size_t length) {
920✔
90
   if(!m_write_queue.empty()) {
920✔
91
      thread_delegate_work(m_write_queue.data(), m_write_queue.size());
×
92
   }
93
   thread_delegate_work(input, length);
920✔
94

95
   bool nothing_attached = true;
920✔
96
   for(size_t j = 0; j != total_ports(); ++j) {
5,517✔
97
      if(m_next[j] != nullptr) {
4,597✔
98
         nothing_attached = false;
4,597✔
99
      }
100
   }
101

102
   if(nothing_attached) {
920✔
103
      m_write_queue += std::make_pair(input, length);
×
104
   } else {
105
      m_write_queue.clear();
920✔
106
   }
107
}
920✔
108

109
void Threaded_Fork::thread_delegate_work(const uint8_t input[], size_t length) {
920✔
110
   //Set the data to do.
111
   m_thread_data->m_input = input;
920✔
112
   m_thread_data->m_input_length = length;
920✔
113

114
   //Let the workers start processing.
115
   m_thread_data->m_input_complete_barrier.wait(total_ports() + 1);
920✔
116
   m_thread_data->m_input_ready_semaphore.release(total_ports());
920✔
117

118
   //Wait for all the filters to finish processing.
119
   m_thread_data->m_input_complete_barrier.sync();
920✔
120

121
   //Reset the thread data
122
   m_thread_data->m_input = nullptr;
920✔
123
   m_thread_data->m_input_length = 0;
920✔
124
}
920✔
125

126
void Threaded_Fork::thread_entry(Filter* filter) {
7✔
127
   while(true) {
4,597✔
128
      m_thread_data->m_input_ready_semaphore.acquire();
4,604✔
129

130
      if(m_thread_data->m_input == nullptr) {
4,604✔
131
         break;
132
      }
133

134
      filter->write(m_thread_data->m_input, m_thread_data->m_input_length);
4,597✔
135
      m_thread_data->m_input_complete_barrier.sync();
4,597✔
136
   }
137
}
7✔
138

139
}  // namespace Botan
140

141
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc