4#include <QtCore/private/qohoslogger_p.h>
5#include <condition_variable>
10#include <qohossinglethreadexecutor.h>
20std::shared_ptr<::pthread_attr_t> makePthreadAttr()
22 auto threadAttrStorage =
std::make_shared<::pthread_attr_t>();
23 auto threadAttr =
std::shared_ptr<::pthread_attr_t>(
24 threadAttrStorage.get(),
25 [threadAttrStorage](::pthread_attr_t *attr) {
26 ::pthread_attr_destroy(attr);
29 int initResult = ::pthread_attr_init(threadAttr.get());
31 qOhosReportFatalErrorAndAbort(
"pthread_attr_init() failed: %s",
std::strerror(initResult));
36std::shared_ptr<
void> startNewThread(
37 std::function<
void()> threadFunction,
const ::pthread_attr_t &threadAttributes)
41 std::function<
void()> threadFunction;
45 auto context =
std::make_shared<Context>();
46 context->threadFunction =
std::move(threadFunction);
48 auto threadHandle = makeDestroyNotifier(
50 if (context->optThreadId.hasValue())
51 ::pthread_join(context->optThreadId.value(),
nullptr);
54 auto pthreadStartRoutineFunc = [](
void *arg) ->
void * {
55 auto *context =
static_cast<Context *>(arg);
56 context->threadFunction();
61 int createResult = ::pthread_create(&threadId, &threadAttributes, pthreadStartRoutineFunc, context.get());
62 if (createResult != 0) {
63 qOhosReportFatalErrorAndAbort(
64 "%s: pthread_create() failed: %s", Q_FUNC_INFO,
std::strerror(createResult));
67 context->optThreadId = threadId;
72std::shared_ptr<::pthread_attr_t> createSingleThreadExecutorThreadAttributes(
75 auto threadAttributes = makePthreadAttr();
77 if (config.threadPreferredStackSize.hasValue()) {
78 int setStackSizeResult = ::pthread_attr_setstacksize(
79 threadAttributes.get(), config.threadPreferredStackSize.value());
80 if (setStackSizeResult != 0) {
82 "%s: pthread_attr_setstacksize() failed: %s",
83 Q_FUNC_INFO,
std::strerror(setStackSizeResult));
87 return threadAttributes;
90class SingleThreadExecutor
95 ~SingleThreadExecutor();
97 void enqueueTask(
std::function<
void()> task);
100 std::shared_ptr<
void> m_workerThreadHandle;
101 std::mutex m_tasksQueueMutex;
102 std::queue<std::function<
void()>> m_tasksQueue;
103 std::condition_variable m_tasksQueueNonEmptyCv;
108 m_workerThreadHandle = startNewThread(
111 std::function<
void()> task;
114 std::unique_lock<std::mutex> tasksQueueLock(m_tasksQueueMutex);
115 m_tasksQueueNonEmptyCv.wait(
118 return !m_tasksQueue.empty();
121 task = std::move(m_tasksQueue.front());
131 *createSingleThreadExecutorThreadAttributes(config));
134SingleThreadExecutor::~SingleThreadExecutor()
137 m_workerThreadHandle.reset();
140void SingleThreadExecutor::enqueueTask(
std::function<
void()> task)
142 std::lock_guard<
std::mutex> tasksQueueLock(m_tasksQueueMutex);
143 m_tasksQueue.push(std::move(task));
144 m_tasksQueueNonEmptyCv.notify_one();
151 auto executor =
std::make_shared<SingleThreadExecutor>(config);
152 return [executor](
std::function<
void()> task) {
153 executor->enqueueTask(
std::move(task));
std::enable_if_t< qohosplugincore_h_detail::isQOhosOptional< QOhosInvokeResult< Func, T > >, QOhosInvokeResult< Func, T > > andThen(Func &&func) const
QOhosConsumer< std::function< void()> > makeSingleThreadExecutor(const SingleThreadExecutorConfig &config={})