diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-01-30 13:57:08 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-01-30 13:57:08 +0100 |
commit | a9ddd636be6d5cd95c6c6b109619a4b1b109901b (patch) | |
tree | 231acfc8522a6c23de55b71028212d508bca664f | |
parent | 3656a6dc4ad0c166b06cb64293f1a979a684084d (diff) | |
download | sink-a9ddd636be6d5cd95c6c6b109619a4b1b109901b.tar.gz sink-a9ddd636be6d5cd95c6c6b109619a4b1b109901b.zip |
A first clang-format configuration
It's not perfect, especially with regards to single-line lambdas where
the breaks after the curly-brace is lost, but otherwise it's pretty
close already. With clang 3.9 (instead of 3.7) some finer grained
controls will be available that might help.
Also Q_SLOTS is not yet recognized, but slots works fine.
-rw-r--r-- | .clang-format | 52 | ||||
-rw-r--r-- | formattest.cpp | 187 | ||||
-rw-r--r-- | formatting.txt | 7 |
3 files changed, 246 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1822f86 --- /dev/null +++ b/.clang-format | |||
@@ -0,0 +1,52 @@ | |||
1 | AccessModifierOffset: -4 | ||
2 | AlignEscapedNewlinesLeft: true | ||
3 | AlignTrailingComments: false | ||
4 | AlignAfterOpenBracket: false | ||
5 | AllowAllParametersOfDeclarationOnNextLine: true | ||
6 | AllowShortBlocksOnASingleLine: false | ||
7 | AllowShortFunctionsOnASingleLine: Inline | ||
8 | AllowShortIfStatementsOnASingleLine: false | ||
9 | AllowShortLoopsOnASingleLine: false | ||
10 | AlwaysBreakAfterDefinitionReturnType: false | ||
11 | AlwaysBreakBeforeMultilineStrings: false | ||
12 | AlwaysBreakTemplateDeclarations: false | ||
13 | BinPackArguments: true | ||
14 | BinPackParameters: true | ||
15 | BreakBeforeBinaryOperators: false | ||
16 | BreakBeforeBraces: Mozilla | ||
17 | BreakBeforeTernaryOperators: false | ||
18 | BreakConstructorInitializersBeforeComma: false | ||
19 | ColumnLimit: 180 | ||
20 | CommentPragmas: '' | ||
21 | ConstructorInitializerAllOnOneLineOrOnePerLine: true | ||
22 | ConstructorInitializerIndentWidth: 4 | ||
23 | ContinuationIndentWidth: 0 | ||
24 | Cpp11BracedListStyle: false | ||
25 | DerivePointerBinding: false | ||
26 | ForEachMacros: ['foreach', 'Q_FOREACH'] | ||
27 | IndentCaseLabels: true | ||
28 | IndentFunctionDeclarationAfterType: false | ||
29 | IndentWidth: 4 | ||
30 | Language: Cpp | ||
31 | MaxEmptyLinesToKeep: 2 | ||
32 | NamespaceIndentation: None | ||
33 | ObjCSpaceAfterProperty: true | ||
34 | ObjCSpaceBeforeProtocolList: true | ||
35 | PenaltyBreakBeforeFirstCallParameter: 100 | ||
36 | PenaltyBreakComment: 100 | ||
37 | PenaltyBreakFirstLessLess: 0 | ||
38 | PenaltyBreakString: 100 | ||
39 | PenaltyExcessCharacter: 1 | ||
40 | PenaltyReturnTypeOnItsOwnLine: 0 | ||
41 | PointerBindsToType: false | ||
42 | SpaceBeforeAssignmentOperators: true | ||
43 | SpaceBeforeParens: ControlStatements | ||
44 | SpaceInEmptyParentheses: false | ||
45 | SpacesBeforeTrailingComments: 1 | ||
46 | SpacesInAngles: false | ||
47 | SpacesInCStyleCastParentheses: false | ||
48 | SpacesInContainerLiterals: false | ||
49 | SpacesInParentheses: false | ||
50 | Standard: Cpp11 | ||
51 | TabWidth: 4 | ||
52 | UseTab: Never | ||
diff --git a/formattest.cpp b/formattest.cpp new file mode 100644 index 0000000..f12fd59 --- /dev/null +++ b/formattest.cpp | |||
@@ -0,0 +1,187 @@ | |||
1 | |||
2 | namespace async { | ||
3 | template<typename T> | ||
4 | KAsync::Job<T> run(const std::function<T()> &f) | ||
5 | { | ||
6 | return KAsync::start<T>([f](KAsync::Future<T> &future) { | ||
7 | auto result = QtConcurrent::run(f); | ||
8 | auto watcher = new QFutureWatcher<T>; | ||
9 | watcher->setFuture(result); | ||
10 | QObject::connect(watcher, &QFutureWatcher<T>::finished, watcher, [&future, watcher]() { | ||
11 | future.setValue(watcher->future().result()); | ||
12 | delete watcher; | ||
13 | future.setFinished(); | ||
14 | }); | ||
15 | }); | ||
16 | } | ||
17 | |||
18 | } | ||
19 | |||
20 | void run() | ||
21 | { | ||
22 | return KAsync::start<T>([f](KAsync::Future<T> &future) { | ||
23 | auto result = QtConcurrent::run(f); | ||
24 | auto watcher = new QFutureWatcher<T>; | ||
25 | watcher->setFuture(result); | ||
26 | QObject::connect(watcher, &QFutureWatcher<T>::finished, watcher, [&future]() { | ||
27 | future.setFinished(); | ||
28 | }); | ||
29 | }); | ||
30 | } | ||
31 | |||
32 | class ResourceAccessFactory { | ||
33 | public: | ||
34 | static ResourceAccessFactory &instance() | ||
35 | { | ||
36 | static ResourceAccessFactory *instance = 0; | ||
37 | if (!instance) { | ||
38 | instance = new ResourceAccessFactory; | ||
39 | } | ||
40 | return *instance; | ||
41 | } | ||
42 | |||
43 | Sink::ResourceAccess::Ptr getAccess(const QByteArray &instanceIdentifier) | ||
44 | { | ||
45 | if (!mCache.contains(instanceIdentifier)) { | ||
46 | //Reuse the pointer if something else kept the resourceaccess alive | ||
47 | if (mWeakCache.contains(instanceIdentifier)) { | ||
48 | auto sharedPointer = mWeakCache.value(instanceIdentifier).toStrongRef(); | ||
49 | if (sharedPointer) { | ||
50 | mCache.insert(instanceIdentifier, sharedPointer); | ||
51 | } | ||
52 | } | ||
53 | if (!mCache.contains(instanceIdentifier)) { | ||
54 | //Create a new instance if necessary | ||
55 | auto sharedPointer = Sink::ResourceAccess::Ptr::create(instanceIdentifier); | ||
56 | QObject::connect(sharedPointer.data(), &Sink::ResourceAccess::ready, sharedPointer.data(), [this, instanceIdentifier](bool ready) { | ||
57 | if (!ready) { | ||
58 | mCache.remove(instanceIdentifier); | ||
59 | } | ||
60 | }); | ||
61 | mCache.insert(instanceIdentifier, sharedPointer); | ||
62 | mWeakCache.insert(instanceIdentifier, sharedPointer); | ||
63 | } | ||
64 | } | ||
65 | if (!mTimer.contains(instanceIdentifier)) { | ||
66 | auto timer = new QTimer; | ||
67 | //Drop connection after 3 seconds (which is a random value) | ||
68 | QObject::connect(timer, &QTimer::timeout, timer, [this, instanceIdentifier]() { | ||
69 | mCache.remove(instanceIdentifier); | ||
70 | }); | ||
71 | timer->setInterval(3000); | ||
72 | mTimer.insert(instanceIdentifier, timer); | ||
73 | } | ||
74 | auto timer = mTimer.value(instanceIdentifier); | ||
75 | timer->start(); | ||
76 | return mCache.value(instanceIdentifier); | ||
77 | } | ||
78 | |||
79 | QHash<QByteArray, QWeakPointer<Sink::ResourceAccess> > mWeakCache; | ||
80 | QHash<QByteArray, Sink::ResourceAccess::Ptr> mCache; | ||
81 | QHash<QByteArray, QTimer*> mTimer; | ||
82 | }; | ||
83 | |||
84 | class ChangeReplay : public QObject | ||
85 | { | ||
86 | Q_OBJECT | ||
87 | public: | ||
88 | |||
89 | typedef std::function<KAsync::Job<void>(const QByteArray &type, const QByteArray &key, const QByteArray &value)> ReplayFunction; | ||
90 | |||
91 | ChangeReplay(const QString &resourceName, const ReplayFunction &replayFunction) | ||
92 | : mStorage(storageLocation(), resourceName, Storage::ReadOnly), | ||
93 | mChangeReplayStore(storageLocation(), resourceName + ".changereplay", Storage::ReadWrite), | ||
94 | mReplayFunction(replayFunction) | ||
95 | { | ||
96 | |||
97 | } | ||
98 | |||
99 | qint64 getLastReplayedRevision() | ||
100 | { | ||
101 | qint64 lastReplayedRevision = 0; | ||
102 | auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadOnly); | ||
103 | replayStoreTransaction.openDatabase().scan("lastReplayedRevision", [&lastReplayedRevision](const QByteArray &key, const QByteArray &value) -> bool { | ||
104 | lastReplayedRevision = value.toLongLong(); | ||
105 | return false; | ||
106 | }, [](const Storage::Error &) { | ||
107 | }); | ||
108 | return lastReplayedRevision; | ||
109 | } | ||
110 | |||
111 | bool allChangesReplayed() | ||
112 | { | ||
113 | const qint64 topRevision = Storage::maxRevision(mStorage.createTransaction(Storage::ReadOnly)); | ||
114 | const qint64 lastReplayedRevision = getLastReplayedRevision(); | ||
115 | Trace() << "All changes replayed " << topRevision << lastReplayedRevision; | ||
116 | return (lastReplayedRevision >= topRevision); | ||
117 | } | ||
118 | |||
119 | Q_SIGNALS: | ||
120 | void changesReplayed(); | ||
121 | |||
122 | public Q_SLOTS: | ||
123 | void revisionChanged() | ||
124 | { | ||
125 | auto mainStoreTransaction = mStorage.createTransaction(Storage::ReadOnly); | ||
126 | auto replayStoreTransaction = mChangeReplayStore.createTransaction(Storage::ReadWrite); | ||
127 | qint64 lastReplayedRevision = 1; | ||
128 | replayStoreTransaction.openDatabase().scan("lastReplayedRevision", [&lastReplayedRevision](const QByteArray &key, const QByteArray &value) -> bool { | ||
129 | lastReplayedRevision = value.toLongLong(); | ||
130 | return false; | ||
131 | }, [](const Storage::Error &) { | ||
132 | }); | ||
133 | const qint64 topRevision = Storage::maxRevision(mainStoreTransaction); | ||
134 | |||
135 | Trace() << "Changereplay from " << lastReplayedRevision << " to " << topRevision; | ||
136 | if (lastReplayedRevision <= topRevision) { | ||
137 | qint64 revision = lastReplayedRevision; | ||
138 | for (;revision <= topRevision; revision++) { | ||
139 | const auto uid = Storage::getUidFromRevision(mainStoreTransaction, revision); | ||
140 | const auto type = Storage::getTypeFromRevision(mainStoreTransaction, revision); | ||
141 | const auto key = Storage::assembleKey(uid, revision); | ||
142 | mainStoreTransaction.openDatabase(type + ".main").scan(key, [&lastReplayedRevision, type, this](const QByteArray &key, const QByteArray &value) -> bool { | ||
143 | mReplayFunction(type, key, value).exec(); | ||
144 | //TODO make for loop async, and pass to async replay function together with type | ||
145 | Trace() << "Replaying " << key; | ||
146 | return false; | ||
147 | }, [key](const Storage::Error &) { | ||
148 | ErrorMsg() << "Failed to replay change " << key; | ||
149 | }); | ||
150 | } | ||
151 | revision--; | ||
152 | replayStoreTransaction.openDatabase().write("lastReplayedRevision", QByteArray::number(revision)); | ||
153 | replayStoreTransaction.commit(); | ||
154 | Trace() << "Replayed until " << revision; | ||
155 | } | ||
156 | emit changesReplayed(); | ||
157 | } | ||
158 | |||
159 | private: | ||
160 | Sink::Storage mStorage; | ||
161 | Sink::Storage mChangeReplayStore; | ||
162 | ReplayFunction mReplayFunction; | ||
163 | }; | ||
164 | |||
165 | KAsync::Job<void> processPipeline() | ||
166 | { | ||
167 | mPipeline->startTransaction(); | ||
168 | Trace() << "Cleaning up from " << mPipeline->cleanedUpRevision() + 1 << " to " << mLowerBoundRevision; | ||
169 | for (qint64 revision = mPipeline->cleanedUpRevision() + 1; revision <= mLowerBoundRevision; revision++) { | ||
170 | mPipeline->cleanupRevision(revision); | ||
171 | } | ||
172 | mPipeline->commit(); | ||
173 | |||
174 | //Go through all message queues | ||
175 | auto it = QSharedPointer<QListIterator<MessageQueue*> >::create(mCommandQueues); | ||
176 | return KAsync::dowhile( | ||
177 | [it]() { return it->hasNext(); }, | ||
178 | [it, this](KAsync::Future<void> &future) { | ||
179 | auto queue = it->next(); | ||
180 | processQueue(queue).then<void>([&future]() { | ||
181 | Trace() << "Queue processed"; | ||
182 | future.setFinished(); | ||
183 | }).exec(); | ||
184 | } | ||
185 | ); | ||
186 | } | ||
187 | |||
diff --git a/formatting.txt b/formatting.txt new file mode 100644 index 0000000..7ad5ab1 --- /dev/null +++ b/formatting.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | Configuration: See .clang-format | ||
2 | |||
3 | # Reformat | ||
4 | clang-format -i common/*.{cpp,h} | ||
5 | |||
6 | # Test | ||
7 | clang-format formattest.cpp > formatted && vimdiff formattest.cpp formatted | ||