| 142 | Future<Void> start(Database const& cx) override { return _start(cx, this); } |
| 143 | |
| 144 | ACTOR Future<Void> _start(Database cx, ThreadSafetyWorkload* self) { |
| 145 | state std::vector<ThreadInfo*> threadInfo; |
| 146 | |
| 147 | Reference<IDatabase> dbRef = |
| 148 | wait(unsafeThreadFutureToFuture(ThreadSafeDatabase::createFromExistingDatabase(cx))); |
| 149 | self->db = dbRef; |
| 150 | |
| 151 | if (deterministicRandom()->coinflip()) { |
| 152 | MultiVersionApi::api->selectApiVersion(cx->apiVersion.version()); |
| 153 | self->db = MultiVersionDatabase::debugCreateFromExistingDatabase(dbRef); |
| 154 | } |
| 155 | |
| 156 | state int i; |
| 157 | for (i = 0; i < self->threadsPerClient; ++i) { |
| 158 | threadInfo.push_back(new ThreadInfo(i, self)); |
| 159 | g_network->startThread(self->threadStart, threadInfo[i]); |
| 160 | } |
| 161 | |
| 162 | wait(delay(self->threadDuration)); |
| 163 | |
| 164 | // Signals the threads to stop |
| 165 | self->mutex.enter(); |
| 166 | self->stopped = true; |
| 167 | self->mutex.leave(); |
| 168 | |
| 169 | for (i = 0; i < threadInfo.size(); ++i) { |
| 170 | try { |
| 171 | wait(threadInfo[i]->done.getFuture()); |
| 172 | } catch (Error& e) { |
| 173 | self->success = false; |
| 174 | printf("Thread %d.%d failed: %s\n", self->clientId, i, e.name()); |
| 175 | TraceEvent(SevError, "ThreadSafety_ThreadFailed").error(e); |
| 176 | } |
| 177 | |
| 178 | delete threadInfo[i]; |
| 179 | } |
| 180 | |
| 181 | return Void(); |
| 182 | } |
| 183 | |
| 184 | THREAD_FUNC threadStart(void* arg) { |
| 185 | ThreadInfo* info = (ThreadInfo*)arg; |
nothing calls this directly
no test coverage detected