summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--async/src/CMakeLists.txt1
-rw-r--r--async/src/async.cpp6
-rw-r--r--async/src/async.h20
-rw-r--r--async/src/debug.cpp73
-rw-r--r--async/src/debug.h80
5 files changed, 179 insertions, 1 deletions
diff --git a/async/src/CMakeLists.txt b/async/src/CMakeLists.txt
index 6f8ab63..becc8ee 100644
--- a/async/src/CMakeLists.txt
+++ b/async/src/CMakeLists.txt
@@ -5,6 +5,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
5set(async_SRCS 5set(async_SRCS
6 async.cpp 6 async.cpp
7 future.cpp 7 future.cpp
8 debug.cpp
8) 9)
9 10
10add_library(${PROJECT_NAME} SHARED ${async_SRCS}) 11add_library(${PROJECT_NAME} SHARED ${async_SRCS})
diff --git a/async/src/async.cpp b/async/src/async.cpp
index 6f28084..e92d333 100644
--- a/async/src/async.cpp
+++ b/async/src/async.cpp
@@ -21,7 +21,6 @@
21#include <QDebug> 21#include <QDebug>
22#include <QEventLoop> 22#include <QEventLoop>
23 23
24
25using namespace Async; 24using namespace Async;
26 25
27Private::Execution::Execution(const Private::ExecutorBasePtr &executor) 26Private::Execution::Execution(const Private::ExecutorBasePtr &executor)
@@ -45,6 +44,11 @@ void Private::Execution::setFinished()
45{ 44{
46 isFinished = true; 45 isFinished = true;
47 //executor.clear(); 46 //executor.clear();
47#ifndef QT_NO_DEBUG
48 if (tracer) {
49 delete tracer;
50 }
51#endif
48} 52}
49 53
50void Private::Execution::releaseFuture() 54void Private::Execution::releaseFuture()
diff --git a/async/src/async.h b/async/src/async.h
index 2243046..73eeaa0 100644
--- a/async/src/async.h
+++ b/async/src/async.h
@@ -25,6 +25,7 @@
25#include <iterator> 25#include <iterator>
26 26
27#include "future.h" 27#include "future.h"
28#include "debug.h"
28#include "async_impl.h" 29#include "async_impl.h"
29 30
30#include <QVector> 31#include <QVector>
@@ -115,8 +116,13 @@ struct Execution {
115 bool isFinished; 116 bool isFinished;
116 117
117 ExecutionPtr prevExecution; 118 ExecutionPtr prevExecution;
119
120#ifndef QT_NO_DEBUG
121 Tracer *tracer;
122#endif
118}; 123};
119 124
125
120typedef QSharedPointer<Execution> ExecutionPtr; 126typedef QSharedPointer<Execution> ExecutionPtr;
121 127
122class ExecutorBase 128class ExecutorBase
@@ -128,6 +134,7 @@ class ExecutorBase
128 friend class Async::Job; 134 friend class Async::Job;
129 135
130 friend class Execution; 136 friend class Execution;
137 friend class Async::Tracer;
131 138
132public: 139public:
133 virtual ~ExecutorBase(); 140 virtual ~ExecutorBase();
@@ -143,6 +150,10 @@ protected:
143 virtual bool handleError(const ExecutionPtr &execution) = 0; 150 virtual bool handleError(const ExecutionPtr &execution) = 0;
144 151
145 ExecutorBasePtr mPrev; 152 ExecutorBasePtr mPrev;
153
154#ifndef QT_NO_DEBUG
155 QString mExecutorName;
156#endif
146}; 157};
147 158
148template<typename PrevOut, typename Out, typename ... In> 159template<typename PrevOut, typename Out, typename ... In>
@@ -581,6 +592,9 @@ ExecutionPtr Executor<PrevOut, Out, In ...>::exec(const ExecutorBasePtr &self)
581 // Passing 'self' to execution ensures that the Executor chain remains 592 // Passing 'self' to execution ensures that the Executor chain remains
582 // valid until the entire execution is finished 593 // valid until the entire execution is finished
583 ExecutionPtr execution = ExecutionPtr::create(self); 594 ExecutionPtr execution = ExecutionPtr::create(self);
595#ifndef QT_NO_DEBUG
596 execution->tracer = new Tracer(execution.data()); // owned by execution
597#endif
584 598
585 // chainup 599 // chainup
586 execution->prevExecution = mPrev ? mPrev->exec(mPrev) : ExecutionPtr(); 600 execution->prevExecution = mPrev ? mPrev->exec(mPrev) : ExecutionPtr();
@@ -667,6 +681,7 @@ ThenExecutor<Out, In ...>::ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler
667 : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(error, parent) 681 : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(error, parent)
668 , mFunc(then) 682 , mFunc(then)
669{ 683{
684 STORE_EXECUTOR_NAME("ThenExecutor", Out, In ...);
670} 685}
671 686
672template<typename Out, typename ... In> 687template<typename Out, typename ... In>
@@ -686,6 +701,7 @@ EachExecutor<PrevOut, Out, In>::EachExecutor(EachTask<Out, In> each, ErrorHandle
686 : Executor<PrevOut, Out, In>(error, parent) 701 : Executor<PrevOut, Out, In>(error, parent)
687 , mFunc(each) 702 , mFunc(each)
688{ 703{
704 STORE_EXECUTOR_NAME("EachExecutor", PrevOut, Out, In);
689} 705}
690 706
691template<typename PrevOut, typename Out, typename In> 707template<typename PrevOut, typename Out, typename In>
@@ -727,6 +743,7 @@ template<typename Out, typename In>
727ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent) 743ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent)
728 : ThenExecutor<Out, In>(reduce, errorFunc, parent) 744 : ThenExecutor<Out, In>(reduce, errorFunc, parent)
729{ 745{
746 STORE_EXECUTOR_NAME("ReduceExecutor", Out, In);
730} 747}
731 748
732template<typename Out, typename ... In> 749template<typename Out, typename ... In>
@@ -734,6 +751,7 @@ SyncThenExecutor<Out, In ...>::SyncThenExecutor(SyncThenTask<Out, In ...> then,
734 : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(errorFunc, parent) 751 : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(errorFunc, parent)
735 , mFunc(then) 752 , mFunc(then)
736{ 753{
754 STORE_EXECUTOR_NAME("SyncThenExecutor", Out, In ...);
737} 755}
738 756
739template<typename Out, typename ... In> 757template<typename Out, typename ... In>
@@ -775,6 +793,7 @@ SyncEachExecutor<PrevOut, Out, In>::SyncEachExecutor(SyncEachTask<Out, In> each,
775 : Executor<PrevOut, Out, In>(errorFunc, parent) 793 : Executor<PrevOut, Out, In>(errorFunc, parent)
776 , mFunc(each) 794 , mFunc(each)
777{ 795{
796 STORE_EXECUTOR_NAME("SyncEachExecutor", PrevOut, Out, In);
778} 797}
779 798
780template<typename PrevOut, typename Out, typename In> 799template<typename PrevOut, typename Out, typename In>
@@ -812,6 +831,7 @@ template<typename Out, typename In>
812SyncReduceExecutor<Out, In>::SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent) 831SyncReduceExecutor<Out, In>::SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent)
813 : SyncThenExecutor<Out, In>(reduce, errorFunc, parent) 832 : SyncThenExecutor<Out, In>(reduce, errorFunc, parent)
814{ 833{
834 STORE_EXECUTOR_NAME("SyncReduceExecutor", Out, In);
815} 835}
816 836
817 837
diff --git a/async/src/debug.cpp b/async/src/debug.cpp
new file mode 100644
index 0000000..9dfad1a
--- /dev/null
+++ b/async/src/debug.cpp
@@ -0,0 +1,73 @@
1/*
2 * Copyright 2015 Daniel Vrátil <dvratil@redhat.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "debug.h"
19#include "async.h"
20
21#include <QStringBuilder>
22
23#ifdef __GNUG__
24#include <cxxabi.h>
25#include <memory>
26#endif
27
28namespace Async
29{
30
31Q_LOGGING_CATEGORY(Debug, "org.kde.async", QtWarningMsg);
32Q_LOGGING_CATEGORY(Trace, "org.kde.async.trace", QtWarningMsg);
33
34QString demangleName(const char *name)
35{
36#ifdef __GNUG__
37 int status = 1; // uses -3 to 0 error codes
38 std::unique_ptr<char, void(*)(void*)> demangled(abi::__cxa_demangle(name, 0, 0, &status), std::free);
39 if (status == 0) {
40 return QString(demangled.get());
41 }
42#endif
43 return QString(name);
44}
45
46}
47
48using namespace Async;
49
50int Tracer::lastId = 0;
51
52Tracer::Tracer(Private::Execution *execution)
53 : mId(lastId++)
54 , mExecution(execution)
55{
56 msg(Async::Tracer::Start);
57}
58
59Tracer::~Tracer()
60{
61 msg(Async::Tracer::End);
62 // FIXME: Does this work on parallel executions?
63 --lastId;
64 --mId;
65}
66
67void Tracer::msg(Tracer::MsgType msgType)
68{
69 qCDebug(Trace).nospace() << (QString().fill(QLatin1Char(' '), mId * 2) %
70 (msgType == Async::Tracer::Start ? " START " : " END ") %
71 QString::number(mId) % " " %
72 mExecution->executor->mExecutorName);
73}
diff --git a/async/src/debug.h b/async/src/debug.h
new file mode 100644
index 0000000..c453eb3
--- /dev/null
+++ b/async/src/debug.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright 2015 Daniel Vrátil <dvratil@redhat.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef ASYNC_DEBUG_H
19#define ASYNC_DEBUG_H
20
21#include <QLoggingCategory>
22#include <QStringBuilder>
23
24#ifndef QT_NO_DEBUG
25#include <typeinfo>
26#endif
27
28namespace Async
29{
30
31Q_DECLARE_LOGGING_CATEGORY(Debug)
32Q_DECLARE_LOGGING_CATEGORY(Trace)
33
34QString demangleName(const char *name);
35
36namespace Private
37{
38class Execution;
39}
40
41class Tracer
42{
43public:
44 Tracer(Private::Execution *execution);
45 ~Tracer();
46
47private:
48 enum MsgType {
49 Start,
50 End
51 };
52 void msg(MsgType);
53
54 int mId;
55 Private::Execution *mExecution;
56
57 static int lastId;
58};
59
60}
61
62#ifndef QT_NO_DEBUG
63 template<typename T>
64 QString storeExecutorNameExpanded() {
65 return Async::demangleName(typeid(T).name());
66 }
67
68 template<typename T, typename ... Tail>
69 typename std::enable_if<sizeof ... (Tail) != 0, QString>::type
70 storeExecutorNameExpanded() {
71 return storeExecutorNameExpanded<T>() % QStringLiteral(", ") % storeExecutorNameExpanded<Tail ...>();
72 }
73
74 #define STORE_EXECUTOR_NAME(name, ...) \
75 ExecutorBase::mExecutorName = QStringLiteral(name) % QStringLiteral("<") % storeExecutorNameExpanded<__VA_ARGS__>() % QStringLiteral(">")
76#else
77 #define STORE_EXECUTOR_NAME(...)
78#endif
79
80#endif // ASYNC_DEBUG_H \ No newline at end of file