#endif
#include "mtasker.hh"
#include "misc.hh"
-#include <stdio.h>
+#include <cstdio>
#include <iostream>
#ifdef PDNS_USE_VALGRIND
return -1;
}
- Waiter w;
- w.context = std::make_shared<pdns_ucontext_t>();
- w.ttd.tv_sec = 0;
- w.ttd.tv_usec = 0;
- if (timeoutMsec) {
- struct timeval increment;
+ Waiter waiter;
+ waiter.context = std::make_shared<pdns_ucontext_t>();
+ waiter.ttd.tv_sec = 0;
+ waiter.ttd.tv_usec = 0;
+ if (timeoutMsec != 0) {
+ struct timeval increment{};
increment.tv_sec = timeoutMsec / 1000;
- increment.tv_usec = 1000 * (timeoutMsec % 1000);
- if (now)
- w.ttd = increment + *now;
+ increment.tv_usec = static_cast<decltype(increment.tv_usec)>(1000 * (timeoutMsec % 1000));
+ if (now != nullptr) {
+ waiter.ttd = increment + *now;
+ }
else {
- struct timeval realnow;
- gettimeofday(&realnow, 0);
- w.ttd = increment + realnow;
+ struct timeval realnow{};
+ gettimeofday(&realnow, nullptr);
+ waiter.ttd = increment + realnow;
}
}
- w.tid = d_tid;
- w.key = key;
+ waiter.tid = d_tid;
+ waiter.key = key;
- d_waiters.insert(w);
+ d_waiters.insert(waiter);
#ifdef MTASKERTIMING
unsigned int diff = d_threads[d_tid].dt.ndiff() / 1000;
d_threads[d_tid].totTime += diff;
#ifdef MTASKERTIMING
d_threads[d_tid].dt.start();
#endif
- if (val && d_waitstatus == Answer)
+ if (val && d_waitstatus == Answer) {
*val = d_waitval;
- d_tid = w.tid;
- if ((char*)&w < d_threads[d_tid].highestStackSeen) {
- d_threads[d_tid].highestStackSeen = (char*)&w;
+ }
+ d_tid = waiter.tid;
+ if ((char*)&waiter < d_threads[d_tid].highestStackSeen) {
+ d_threads[d_tid].highestStackSeen = (char*)&waiter;
}
key = d_eventkey;
return d_waitstatus;
return 0;
}
d_waitstatus = Answer;
- if (val)
+ if (val) {
d_waitval = *val;
-
+ }
d_tid = waiter->tid; // set tid
d_eventkey = waiter->key; // pass waitEvent the exact key it was woken for
auto userspace = std::move(waiter->context);
template <class Key, class Val, class Cmp>
std::shared_ptr<pdns_ucontext_t> MTasker<Key, Val, Cmp>::getUContext()
{
- auto uc = std::make_shared<pdns_ucontext_t>();
+ auto ucontext = std::make_shared<pdns_ucontext_t>();
if (d_cachedStacks.empty()) {
- uc->uc_stack.resize(d_stacksize + 1);
+ ucontext->uc_stack.resize(d_stacksize + 1);
}
else {
- uc->uc_stack = std::move(d_cachedStacks.top());
+ ucontext->uc_stack = std::move(d_cachedStacks.top());
d_cachedStacks.pop();
}
- uc->uc_link = &d_kernel; // come back to kernel after dying
+ ucontext->uc_link = &d_kernel; // come back to kernel after dying
#ifdef PDNS_USE_VALGRIND
uc->valgrind_id = VALGRIND_STACK_REGISTER(&uc->uc_stack[0],
&uc->uc_stack[uc->uc_stack.size() - 1]);
#endif /* PDNS_USE_VALGRIND */
- return uc;
+ return ucontext;
}
//! launches a new thread
template <class Key, class Val, class Cmp>
void MTasker<Key, Val, Cmp>::makeThread(tfunc_t* start, void* val)
{
- auto uc = getUContext();
+ auto ucontext = getUContext();
++d_threadsCount;
auto& thread = d_threads[d_maxtid];
- auto mt = this;
// we will get a better approximation when the task is executed, but that prevents notifying a stack at nullptr
// on the first invocation
- d_threads[d_maxtid].startOfStack = &uc->uc_stack[uc->uc_stack.size() - 1];
- thread.start = [start, val, mt]() {
- char dummy;
- mt->d_threads[mt->d_tid].startOfStack = mt->d_threads[mt->d_tid].highestStackSeen = &dummy;
- auto const tid = mt->d_tid;
+ d_threads[d_maxtid].startOfStack = &ucontext->uc_stack[ucontext->uc_stack.size() - 1];
+ thread.start = [start, val, this]() {
+ char dummy{};
+ d_threads[d_tid].startOfStack = d_threads[d_tid].highestStackSeen = &dummy;
+ auto const tid = d_tid;
start(val);
- mt->d_zombiesQueue.push(tid);
+ d_zombiesQueue.push(tid);
};
- pdns_makecontext(*uc, thread.start);
+ pdns_makecontext(*ucontext, thread.start);
- thread.context = std::move(uc);
+ thread.context = std::move(ucontext);
d_runQueue.push(d_maxtid++); // will run at next schedule invocation
}
return true;
}
if (!d_waiters.empty()) {
- struct timeval rnow;
- if (!now)
- gettimeofday(&rnow, 0);
- else
+ struct timeval rnow{};
+ if (now != nullptr) {
+ gettimeofday(&rnow, nullptr);
+ }
+ else {
rnow = *now;
-
+ }
typedef typename waiters_t::template index<KeyTag>::type waiters_by_ttd_index_t;
// waiters_by_ttd_index_t& ttdindex=d_waiters.template get<KeyTag>();
waiters_by_ttd_index_t& ttdindex = boost::multi_index::get<KeyTag>(d_waiters);
if (i->ttd.tv_sec && i->ttd < rnow) {
d_waitstatus = TimeOut;
d_eventkey = i->key; // pass waitEvent the exact key it was woken for
- auto uc = i->context;
+ auto ucontext = i->context;
d_tid = i->tid;
ttdindex.erase(i++); // removes the waitpoint
notifyStackSwitch(d_threads[d_tid].startOfStack, d_stacksize);
try {
- pdns_swapcontext(d_kernel, *uc); // swaps back to the above point 'A'
+ pdns_swapcontext(d_kernel, *ucontext); // swaps back to the above point 'A'
}
catch (...) {
notifyStackSwitchDone();
}
notifyStackSwitchDone();
}
- else if (i->ttd.tv_sec)
+ else if (i->ttd.tv_sec != 0) {
break;
- else
+ }
+ else {
++i;
+ }
}
}
return false;
#include <cstdint>
#include <ctime>
#include <queue>
-#include <map>
#include <memory>
#include <stack>
-#include <vector>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/key_extractors.hpp>
+
#include "namespaces.hh"
#include "misc.hh"
#include "mtasker_context.hh"
{
std::shared_ptr<pdns_ucontext_t> context;
std::function<void(void)> start;
- const char* startOfStack;
- const char* highestStackSeen;
+ const char* startOfStack{};
+ const char* highestStackSeen{};
#ifdef MTASKERTIMING
CPUTime dt;
unsigned int totTime;
{
EventKey key;
std::shared_ptr<pdns_ucontext_t> context;
- struct timeval ttd;
- int tid;
+ struct timeval ttd{};
+ int tid{};
};
struct KeyTag
{
};
- typedef multi_index_container<
+ using waiters_t = multi_index_container<
Waiter,
indexed_by<
ordered_unique<member<Waiter, EventKey, &Waiter::key>, Cmp>,
- ordered_non_unique<tag<KeyTag>, member<Waiter, struct timeval, &Waiter::ttd>>>>
- waiters_t;
+ ordered_non_unique<tag<KeyTag>, member<Waiter, struct timeval, &Waiter::ttd>>>>;
waiters_t d_waiters;
This limit applies solely to the stack, the heap is not limited in any way. If threads need to allocate a lot of data,
the use of new/delete is suggested.
*/
- MTasker(size_t stacksize = 16 * 8192, size_t stackCacheSize = 0) :
+ MTasker(size_t stacksize = static_cast<size_t>(16 * 8192), size_t stackCacheSize = 0) :
d_stacksize(stacksize), d_maxCachedStacks(stackCacheSize), d_waitstatus(Error)
{
initMainStackBounds();
d_stacksize = d_stacksize >> 4 << 4;
}
- typedef void tfunc_t(void*); //!< type of the pointer that starts a thread
+ using tfunc_t = void (void *); //!< type of the pointer that starts a thread
int waitEvent(EventKey& key, EventVal* val = nullptr, unsigned int timeoutMsec = 0, const struct timeval* now = nullptr);
void yield();
int sendEvent(const EventKey& key, const EventVal* val = nullptr);
void getEvents(std::vector<EventKey>& events);
void makeThread(tfunc_t* start, void* val);
bool schedule(const struct timeval* now = nullptr);
- bool noProcesses() const;
- unsigned int numProcesses() const;
- int getTid() const;
+ [[nodiscard]] bool noProcesses() const;
+ [[nodiscard]] unsigned int numProcesses() const;
+ [[nodiscard]] int getTid() const;
uint64_t getMaxStackUsage();
unsigned int getUsec();