diff options
-rw-r--r-- | async/src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | async/src/async.cpp | 6 | ||||
-rw-r--r-- | async/src/async.h | 20 | ||||
-rw-r--r-- | async/src/debug.cpp | 73 | ||||
-rw-r--r-- | async/src/debug.h | 80 |
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}) | |||
5 | set(async_SRCS | 5 | set(async_SRCS |
6 | async.cpp | 6 | async.cpp |
7 | future.cpp | 7 | future.cpp |
8 | debug.cpp | ||
8 | ) | 9 | ) |
9 | 10 | ||
10 | add_library(${PROJECT_NAME} SHARED ${async_SRCS}) | 11 | add_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 | |||
25 | using namespace Async; | 24 | using namespace Async; |
26 | 25 | ||
27 | Private::Execution::Execution(const Private::ExecutorBasePtr &executor) | 26 | Private::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 | ||
50 | void Private::Execution::releaseFuture() | 54 | void 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 | |||
120 | typedef QSharedPointer<Execution> ExecutionPtr; | 126 | typedef QSharedPointer<Execution> ExecutionPtr; |
121 | 127 | ||
122 | class ExecutorBase | 128 | class 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 | ||
132 | public: | 139 | public: |
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 | ||
148 | template<typename PrevOut, typename Out, typename ... In> | 159 | template<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 | ||
672 | template<typename Out, typename ... In> | 687 | template<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 | ||
691 | template<typename PrevOut, typename Out, typename In> | 707 | template<typename PrevOut, typename Out, typename In> |
@@ -727,6 +743,7 @@ template<typename Out, typename In> | |||
727 | ReduceExecutor<Out, In>::ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent) | 743 | ReduceExecutor<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 | ||
732 | template<typename Out, typename ... In> | 749 | template<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 | ||
739 | template<typename Out, typename ... In> | 757 | template<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 | ||
780 | template<typename PrevOut, typename Out, typename In> | 799 | template<typename PrevOut, typename Out, typename In> |
@@ -812,6 +831,7 @@ template<typename Out, typename In> | |||
812 | SyncReduceExecutor<Out, In>::SyncReduceExecutor(SyncReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent) | 831 | SyncReduceExecutor<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 | |||
28 | namespace Async | ||
29 | { | ||
30 | |||
31 | Q_LOGGING_CATEGORY(Debug, "org.kde.async", QtWarningMsg); | ||
32 | Q_LOGGING_CATEGORY(Trace, "org.kde.async.trace", QtWarningMsg); | ||
33 | |||
34 | QString 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 | |||
48 | using namespace Async; | ||
49 | |||
50 | int Tracer::lastId = 0; | ||
51 | |||
52 | Tracer::Tracer(Private::Execution *execution) | ||
53 | : mId(lastId++) | ||
54 | , mExecution(execution) | ||
55 | { | ||
56 | msg(Async::Tracer::Start); | ||
57 | } | ||
58 | |||
59 | Tracer::~Tracer() | ||
60 | { | ||
61 | msg(Async::Tracer::End); | ||
62 | // FIXME: Does this work on parallel executions? | ||
63 | --lastId; | ||
64 | --mId; | ||
65 | } | ||
66 | |||
67 | void 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 | |||
28 | namespace Async | ||
29 | { | ||
30 | |||
31 | Q_DECLARE_LOGGING_CATEGORY(Debug) | ||
32 | Q_DECLARE_LOGGING_CATEGORY(Trace) | ||
33 | |||
34 | QString demangleName(const char *name); | ||
35 | |||
36 | namespace Private | ||
37 | { | ||
38 | class Execution; | ||
39 | } | ||
40 | |||
41 | class Tracer | ||
42 | { | ||
43 | public: | ||
44 | Tracer(Private::Execution *execution); | ||
45 | ~Tracer(); | ||
46 | |||
47 | private: | ||
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 | ||