@lucent-lang/lucent 0.0.4 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -0
- package/app.plugin.js +46 -10
- package/dist/{bench-CR3E7e2e.js → bench-eEez4jhQ.js} +10 -6
- package/dist/{build-CAIrRSYA.js → build-CpUjeHFz.js} +1 -1
- package/dist/{build-check-QozuNJm5.js → build-check-BA1ZEp9s.js} +28 -13
- package/dist/{check-1SCmYlqA.js → check-BZx3FgI6.js} +1 -1
- package/dist/cli.js +62 -13
- package/dist/{codes-CIuwXt1S.js → codes-D-6LxUqD.js} +163 -7
- package/dist/compiler.js +4 -4
- package/dist/{dashboard-B-NzjjaN.js → dashboard-CC-HXhcd.js} +2 -2
- package/dist/{dev-BYWMP7oC.js → dev-DI5yL8zx.js} +62 -23
- package/dist/{diagnostic-BM9sXmwl.js → diagnostic-BvwLZQS1.js} +3 -1
- package/dist/{doctor-C0PrfWT6.js → doctor-CTAX3euc.js} +1 -1
- package/dist/{doctor-DdR4JnVc.js → doctor-CrgOAV5L.js} +1 -1
- package/dist/{explain--vV1oaRl.js → explain-Byit07F-.js} +1 -1
- package/dist/{packages-HyskKIsY.js → packages-CSmKeaAh.js} +2 -33
- package/dist/pipeline-BM_VM2X_.js +700 -0
- package/dist/project-BKNoTEEp.js +342 -0
- package/dist/sdk-coverage-iiv3JqMp.js +113 -0
- package/dist/sdk-diff-ByJ1Gw-F.js +109 -0
- package/dist/sdk-lock-BQn7IyRs.js +38 -0
- package/dist/{sdk-prefetch-mo04JDZV.js → sdk-prefetch-Bv2pNega.js} +2 -2
- package/dist/{sdk-search-Iv4K3-8a.js → sdk-search-CPGJm_Ne.js} +2 -2
- package/dist/{sdk-show-CkrdlqlP.js → sdk-show-BUkLqRnA.js} +5 -4
- package/dist/sdk-usage-0ZFMAYg1.js +95 -0
- package/dist/src-ChnmWLwn.js +40851 -0
- package/dist/trace-Bi4hkmPx.js +139 -0
- package/lib/core.cjs +368 -1
- package/lib/sdk/android.d.ts +54 -1
- package/lib/sdk/compose.d.ts +94 -0
- package/lib/sdk/compose.schemas.json.gz +0 -0
- package/lib/sdk/core.d.ts +201 -0
- package/lib/sdk/ios.d.ts +75 -2
- package/lib/sdk/ui.d.ts +129 -0
- package/metro/transformer.cjs +11 -2
- package/package.json +4 -3
- package/runtime/cpp/lucent/abort.cpp +59 -11
- package/runtime/cpp/lucent/abort.h +22 -6
- package/runtime/cpp/lucent/array.h +12 -2
- package/runtime/cpp/lucent/async.h +101 -21
- package/runtime/cpp/lucent/bigint.cpp +898 -0
- package/runtime/cpp/lucent/bigint.h +302 -0
- package/runtime/cpp/lucent/buffer.cpp +228 -0
- package/runtime/cpp/lucent/buffer.h +328 -0
- package/runtime/cpp/lucent/builtins.cpp +4 -1
- package/runtime/cpp/lucent/bytes.h +21 -2
- package/runtime/cpp/lucent/callback.cpp +29 -0
- package/runtime/cpp/lucent/callback.h +230 -0
- package/runtime/cpp/lucent/compute.cpp +370 -0
- package/runtime/cpp/lucent/compute.h +455 -0
- package/runtime/cpp/lucent/conversions.h +111 -0
- package/runtime/cpp/lucent/core.h +16 -5
- package/runtime/cpp/lucent/equality.h +107 -28
- package/runtime/cpp/lucent/execution.cpp +416 -0
- package/runtime/cpp/lucent/execution.h +270 -0
- package/runtime/cpp/lucent/extension.cpp +97 -0
- package/runtime/cpp/lucent/extension.h +210 -0
- package/runtime/cpp/lucent/helpers.h +12 -5
- package/runtime/cpp/lucent/items.h +52 -0
- package/runtime/cpp/lucent/jserror.cpp +9 -0
- package/runtime/cpp/lucent/jserror.h +11 -0
- package/runtime/cpp/lucent/jsi/convert.cpp +138 -0
- package/runtime/cpp/lucent/jsi/convert.h +128 -59
- package/runtime/cpp/lucent/jsi/host.cpp +213 -35
- package/runtime/cpp/lucent/jsi/host.h +116 -16
- package/runtime/cpp/lucent/json.h +19 -1
- package/runtime/cpp/lucent/lifecycle.cpp +260 -0
- package/runtime/cpp/lucent/lifecycle.h +124 -0
- package/runtime/cpp/lucent/lucent.h +7 -0
- package/runtime/cpp/lucent/map.h +41 -7
- package/runtime/cpp/lucent/native.cpp +35 -47
- package/runtime/cpp/lucent/native.h +116 -26
- package/runtime/cpp/lucent/number.cpp +38 -38
- package/runtime/cpp/lucent/number.h +33 -0
- package/runtime/cpp/lucent/operation.h +65 -0
- package/runtime/cpp/lucent/ops.h +14 -6
- package/runtime/cpp/lucent/platform/android.cpp +223 -10
- package/runtime/cpp/lucent/platform/android.h +227 -4
- package/runtime/cpp/lucent/platform/android_activity.cpp +258 -0
- package/runtime/cpp/lucent/platform/android_requests.h +140 -0
- package/runtime/cpp/lucent/platform/compose.h +256 -0
- package/runtime/cpp/lucent/platform/ios.h +325 -25
- package/runtime/cpp/lucent/platform/ios.mm +1 -14
- package/runtime/cpp/lucent/platform/ios_ui.h +192 -0
- package/runtime/cpp/lucent/platform/ios_ui.mm +454 -0
- package/runtime/cpp/lucent/platform/swiftui.h +190 -0
- package/runtime/cpp/lucent/presentation.cpp +11 -0
- package/runtime/cpp/lucent/presentation.h +109 -0
- package/runtime/cpp/lucent/reactive.cpp +406 -0
- package/runtime/cpp/lucent/reactive.h +566 -0
- package/runtime/cpp/lucent/report.cpp +40 -0
- package/runtime/cpp/lucent/report.h +16 -0
- package/runtime/cpp/lucent/resource.cpp +83 -0
- package/runtime/cpp/lucent/resource.h +75 -0
- package/runtime/cpp/lucent/scheduler.cpp +38 -124
- package/runtime/cpp/lucent/scheduler.h +102 -83
- package/runtime/cpp/lucent/scope.cpp +308 -0
- package/runtime/cpp/lucent/scope.h +452 -0
- package/runtime/cpp/lucent/sizing.h +263 -0
- package/runtime/cpp/lucent/slots.h +231 -0
- package/runtime/cpp/lucent/trace.cpp +539 -0
- package/runtime/cpp/lucent/trace.h +251 -0
- package/runtime/cpp/lucent/transport.cpp +9 -0
- package/runtime/cpp/lucent/transport.h +341 -0
- package/runtime/cpp/lucent/view.cpp +123 -0
- package/runtime/cpp/lucent/view.h +157 -0
- package/runtime/cpp/rn/LucentComponentView.h +121 -0
- package/runtime/cpp/rn/LucentComponentView.mm +479 -0
- package/runtime/cpp/rn/LucentModule.cpp +37 -7
- package/runtime/cpp/rn/LucentModule.h +3 -0
- package/runtime/cpp/rn/LucentViewChildren.h +80 -0
- package/runtime/cpp/rn/LucentViewChildren.mm +211 -0
- package/runtime/cpp/rn/LucentViewRegistry.h +62 -0
- package/runtime/cpp/rn/LucentViewRequests.cpp +91 -0
- package/runtime/cpp/rn/LucentViewRequests.h +104 -0
- package/runtime/cpp/rn/LucentViewSizing.h +345 -0
- package/runtime/cpp/rn/LucentViewSlots.h +242 -0
- package/runtime/cpp/rn/LucentViewValues.h +125 -0
- package/runtime/cpp/rn/LucentViews.h +440 -0
- package/runtime/cpp/rn/LucentViewsAndroid.cpp +439 -0
- package/runtime/cpp/rn/LucentViewsAndroid.h +138 -0
- package/runtime/cpp/third_party/dragonbox/LICENSE-Boost +23 -0
- package/runtime/cpp/third_party/dragonbox/README.md +16 -0
- package/runtime/cpp/third_party/dragonbox/dragonbox.h +4440 -0
- package/runtime/js/index.d.ts +11 -1
- package/runtime/js/index.js +84 -8
- package/runtime/js/views.d.ts +38 -0
- package/runtime/js/views.js +226 -0
- package/runtime/native/android/CMakeLists.txt +4 -1
- package/runtime/native/android/src/compose/java/dev/lucent/compose/CompositionRules.kt +44 -0
- package/runtime/native/android/src/compose/java/dev/lucent/compose/LucentComposition.kt +161 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentActivities.java +292 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentChildren.java +174 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentHostView.java +232 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentInitializer.java +46 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentPackage.java +4 -3
- package/runtime/native/android/src/main/java/dev/lucent/LucentRequestActivity.java +92 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentSlotView.java +102 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManager.java +149 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManagers.java +16 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViews.java +44 -0
- package/runtime/test/jsi/harness.cpp +9 -0
- package/schemas/build.schema.json +96 -1
- package/schemas/check.schema.json +56 -1
- package/schemas/lucent.schema.json +495 -9
- package/schemas/sdk-diff.schema.json +70 -0
- package/schemas/sdk-lock.schema.json +67 -0
- package/ts-plugin/index.js +85 -4
- package/dist/pipeline-CH7-2cxu.js +0 -232
- package/dist/project-D8tEet0k.js +0 -150
- package/dist/sdk-coverage-BoW_3Efd.js +0 -64
- package/dist/src-BD7f1_aZ.js +0 -11493
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
#include "compute.h"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <thread>
|
|
7
|
+
|
|
8
|
+
#include "report.h"
|
|
9
|
+
|
|
10
|
+
namespace lucent {
|
|
11
|
+
|
|
12
|
+
namespace {
|
|
13
|
+
|
|
14
|
+
/// The task running on this thread.
|
|
15
|
+
thread_local TaskContext* running = nullptr;
|
|
16
|
+
|
|
17
|
+
size_t defaultWorkers() {
|
|
18
|
+
unsigned cores = std::thread::hardware_concurrency();
|
|
19
|
+
return cores > 2 ? cores - 1 : 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
} // namespace
|
|
23
|
+
|
|
24
|
+
Error computeQueueFullError(size_t capacity) {
|
|
25
|
+
return makeError(String::fromLatin1("QuotaExceededError"),
|
|
26
|
+
String::fromUtf8("The compute queue is full (" + std::to_string(capacity) + " tasks waiting)"));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Error computePoolClosedError() {
|
|
30
|
+
return makeError(String::fromLatin1("InvalidStateError"), String::fromLatin1("The compute pool has shut down"));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Error computePoolShutdownError() {
|
|
34
|
+
return makeError(String::fromLatin1("AbortError"), String::fromLatin1("The compute pool shut down"));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// --- TaskContext ----------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
TaskContext* TaskContext::current() noexcept { return running; }
|
|
40
|
+
|
|
41
|
+
void TaskContext::throwCancelled() {
|
|
42
|
+
throwError(String::fromLatin1("AbortError"), String::fromLatin1("The task was cancelled"));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const std::shared_ptr<Scope>& TaskContext::scope() {
|
|
46
|
+
if (scope_) return scope_;
|
|
47
|
+
|
|
48
|
+
ExecutionContext* worker = ExecutionContext::current();
|
|
49
|
+
if (running != this || !worker) throw std::logic_error("A task's scope is used on its worker, while it runs");
|
|
50
|
+
|
|
51
|
+
scope_ = Scope::create(0, worker->root());
|
|
52
|
+
return scope_;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
void TaskContext::end() {
|
|
56
|
+
auto scope = std::move(scope_);
|
|
57
|
+
scope_ = nullptr;
|
|
58
|
+
|
|
59
|
+
if (!scope) return;
|
|
60
|
+
|
|
61
|
+
if (auto e = scope->dispose()) reportUncaught(e, "compute task");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// --- ComputeTask ----------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
detail::ComputeTask::~ComputeTask() {
|
|
67
|
+
if (!sink_) return;
|
|
68
|
+
|
|
69
|
+
TaskTiming timing;
|
|
70
|
+
timing.entry = name_;
|
|
71
|
+
timing.outcome = outcome_.load();
|
|
72
|
+
timing.started = started_ != Time{};
|
|
73
|
+
timing.admitted = admitted_;
|
|
74
|
+
|
|
75
|
+
if (timing.started) {
|
|
76
|
+
timing.waited = started_ - submitted_;
|
|
77
|
+
|
|
78
|
+
if (finished_ != Time{}) timing.ran = finished_ - started_;
|
|
79
|
+
if (finished_ != Time{} && settled_ != Time{}) timing.delivered = settled_ - finished_;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
(*sink_)(timing);
|
|
84
|
+
} catch (...) {
|
|
85
|
+
reportUncaught(std::current_exception(), "compute timing");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
void detail::ComputeTask::delivered(OperationState outcome) {
|
|
90
|
+
if (timed()) settled_ = now();
|
|
91
|
+
|
|
92
|
+
outcome_.store(outcome);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void detail::ComputeTask::tracePhase(const char* ended, const char* next) noexcept {
|
|
96
|
+
if (!traceId_) return;
|
|
97
|
+
|
|
98
|
+
trace::end(phase_, trace::Category::Compute, ended, {.id = traceId_, .detail = name_});
|
|
99
|
+
phase_ = next ? trace::begin(trace::Category::Compute, next) : trace::Mark{};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void detail::ComputeTask::finishRun() {
|
|
103
|
+
context_.end();
|
|
104
|
+
|
|
105
|
+
if (timed()) finished_ = now();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// --- ComputePool ----------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
std::shared_ptr<ComputePool> ComputePool::create(Options options) {
|
|
111
|
+
return std::shared_ptr<ComputePool>(new ComputePool(options));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const std::shared_ptr<ComputePool>& ComputePool::shared() {
|
|
115
|
+
// Leaked, like the process it serves.
|
|
116
|
+
static auto* pool = new std::shared_ptr<ComputePool>(create());
|
|
117
|
+
return *pool;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
ComputePool::ComputePool(Options options) : capacity_(options.capacity ? options.capacity : kDefaultCapacity) {
|
|
121
|
+
size_t count = options.workers ? options.workers : defaultWorkers();
|
|
122
|
+
|
|
123
|
+
for (size_t i = 0; i < count; i++) workers_.push_back(IsolatedContext::create());
|
|
124
|
+
|
|
125
|
+
// The first worker is handed out first.
|
|
126
|
+
for (size_t i = count; i > 0; i--) idle_.push_back(i - 1);
|
|
127
|
+
|
|
128
|
+
stats_.workers = count;
|
|
129
|
+
stats_.capacity = capacity_;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
ComputePool::~ComputePool() { shutdown(); }
|
|
133
|
+
|
|
134
|
+
std::function<void()> ComputePool::admit(const TaskRef& task, const AbortSignal& signal) {
|
|
135
|
+
enum class Refusal { None, Full, Closed } refusal = Refusal::None;
|
|
136
|
+
std::optional<size_t> worker;
|
|
137
|
+
|
|
138
|
+
const bool timed = timing_.load(std::memory_order_relaxed);
|
|
139
|
+
const auto before = timed ? detail::ComputeTask::now() : detail::ComputeTask::Time{};
|
|
140
|
+
|
|
141
|
+
// Traced from here: waiting for a worker.
|
|
142
|
+
if (trace::enabled()) [[unlikely]] {
|
|
143
|
+
task->traceId_ = trace::newId();
|
|
144
|
+
task->phase_ = trace::begin(trace::Category::Compute, "compute.wait");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
size_t queued = 0;
|
|
148
|
+
|
|
149
|
+
{
|
|
150
|
+
std::lock_guard<std::mutex> g(m_);
|
|
151
|
+
|
|
152
|
+
if (timed && sink_) {
|
|
153
|
+
task->submitted_ = detail::ComputeTask::now();
|
|
154
|
+
task->admitted_ = task->submitted_ - before;
|
|
155
|
+
task->sink_ = sink_;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (closed_) {
|
|
159
|
+
refusal = Refusal::Closed;
|
|
160
|
+
} else if (!idle_.empty()) {
|
|
161
|
+
worker = idle_.back();
|
|
162
|
+
idle_.pop_back();
|
|
163
|
+
|
|
164
|
+
task->place_ = detail::ComputeTask::Place::Assigned;
|
|
165
|
+
assigned_.push_back(task);
|
|
166
|
+
|
|
167
|
+
stats_.submitted++;
|
|
168
|
+
stats_.started++;
|
|
169
|
+
stats_.peakRunning = std::max(stats_.peakRunning, assigned_.size());
|
|
170
|
+
} else if (queue_.size() < capacity_) {
|
|
171
|
+
task->place_ = detail::ComputeTask::Place::Queued;
|
|
172
|
+
queue_.push_back(task);
|
|
173
|
+
|
|
174
|
+
stats_.submitted++;
|
|
175
|
+
stats_.saturated++;
|
|
176
|
+
stats_.peakQueued = std::max(stats_.peakQueued, queue_.size());
|
|
177
|
+
queued = queue_.size();
|
|
178
|
+
} else {
|
|
179
|
+
stats_.submitted++;
|
|
180
|
+
stats_.rejected++;
|
|
181
|
+
refusal = Refusal::Full;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (task->traceId_) {
|
|
186
|
+
// Every worker busy: the task waits in the queue, this deep.
|
|
187
|
+
if (queued) {
|
|
188
|
+
trace::instant(trace::Category::Compute, "compute.saturated", {.id = task->traceId_, .value = static_cast<int64_t>(queued), .detail = task->name_});
|
|
189
|
+
trace::counter("compute.queued", static_cast<int64_t>(queued));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (refusal != Refusal::None) {
|
|
193
|
+
trace::instant(trace::Category::Compute, "compute.rejected", {.id = task->traceId_, .detail = task->name_});
|
|
194
|
+
task->tracePhase("compute.wait", nullptr);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (refusal == Refusal::Closed) throwError(computePoolClosedError());
|
|
199
|
+
if (refusal == Refusal::Full) throwError(computeQueueFullError(capacity_));
|
|
200
|
+
|
|
201
|
+
if (worker) dispatch(*worker, task);
|
|
202
|
+
|
|
203
|
+
std::weak_ptr<detail::ComputeTask> weakTask = task;
|
|
204
|
+
uint64_t listener = 0;
|
|
205
|
+
|
|
206
|
+
if (signal) {
|
|
207
|
+
std::weak_ptr<AbortSignalObject> weakSignal = signal;
|
|
208
|
+
|
|
209
|
+
listener = signal->add([weakTask, weakSignal] {
|
|
210
|
+
auto task = weakTask.lock();
|
|
211
|
+
auto signal = weakSignal.lock();
|
|
212
|
+
if (task && signal) task->abandon(signal->reason);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Refused on the signal's owner: it aborted since the submission began.
|
|
216
|
+
if (listener == 0) task->abandon(signal->reason);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
std::weak_ptr<ComputePool> weakPool = weak_from_this();
|
|
220
|
+
|
|
221
|
+
return [weakPool, weakTask, signal, listener] {
|
|
222
|
+
if (signal && listener) signal->remove(listener);
|
|
223
|
+
|
|
224
|
+
auto task = weakTask.lock();
|
|
225
|
+
if (!task) return;
|
|
226
|
+
|
|
227
|
+
// Settled: whatever the task produces from now on is released.
|
|
228
|
+
task->context_.cancel();
|
|
229
|
+
|
|
230
|
+
if (auto pool = weakPool.lock()) pool->withdraw(task);
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
void ComputePool::dispatch(size_t index, TaskRef task) {
|
|
235
|
+
auto self = shared_from_this();
|
|
236
|
+
|
|
237
|
+
// Refused only once the pool has shut down, which cancelled the task.
|
|
238
|
+
workers_[index]->post([self, index, task = std::move(task)]() mutable { self->runOn(index, std::move(task)); });
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
void ComputePool::runOn(size_t index, TaskRef task) {
|
|
242
|
+
if (task->timed()) task->started_ = detail::ComputeTask::now();
|
|
243
|
+
|
|
244
|
+
task->tracePhase("compute.wait", "compute.run");
|
|
245
|
+
|
|
246
|
+
bool posted;
|
|
247
|
+
{
|
|
248
|
+
struct Running {
|
|
249
|
+
explicit Running(TaskContext* task) { running = task; }
|
|
250
|
+
~Running() { running = nullptr; }
|
|
251
|
+
} current(&task->context_);
|
|
252
|
+
|
|
253
|
+
posted = task->run();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
TaskRef next;
|
|
257
|
+
{
|
|
258
|
+
std::lock_guard<std::mutex> g(m_);
|
|
259
|
+
|
|
260
|
+
auto it = std::find(assigned_.begin(), assigned_.end(), task);
|
|
261
|
+
if (it != assigned_.end()) assigned_.erase(it);
|
|
262
|
+
task->place_ = detail::ComputeTask::Place::None;
|
|
263
|
+
|
|
264
|
+
stats_.finished++;
|
|
265
|
+
if (!posted) stats_.abandoned++;
|
|
266
|
+
|
|
267
|
+
if (!closed_ && !queue_.empty()) {
|
|
268
|
+
next = std::move(queue_.front());
|
|
269
|
+
queue_.pop_front();
|
|
270
|
+
|
|
271
|
+
next->place_ = detail::ComputeTask::Place::Assigned;
|
|
272
|
+
assigned_.push_back(next);
|
|
273
|
+
stats_.started++;
|
|
274
|
+
} else {
|
|
275
|
+
idle_.push_back(index);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Outside the lock: the last reference may go, with what the task held.
|
|
280
|
+
task = nullptr;
|
|
281
|
+
|
|
282
|
+
// A turn of its own, so the worker's microtasks and other jobs run between.
|
|
283
|
+
if (next) dispatch(index, std::move(next));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
void ComputePool::withdraw(const TaskRef& task) {
|
|
287
|
+
TaskRef removed;
|
|
288
|
+
|
|
289
|
+
{
|
|
290
|
+
std::lock_guard<std::mutex> g(m_);
|
|
291
|
+
|
|
292
|
+
if (task->place_ != detail::ComputeTask::Place::Queued) return;
|
|
293
|
+
|
|
294
|
+
auto it = std::find(queue_.begin(), queue_.end(), task);
|
|
295
|
+
removed = std::move(*it);
|
|
296
|
+
queue_.erase(it);
|
|
297
|
+
|
|
298
|
+
task->place_ = detail::ComputeTask::Place::None;
|
|
299
|
+
stats_.cancelledQueued++;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
removed->tracePhase("compute.wait", nullptr);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
void ComputePool::shutdown() {
|
|
306
|
+
std::deque<TaskRef> queued;
|
|
307
|
+
std::vector<TaskRef> assigned;
|
|
308
|
+
|
|
309
|
+
{
|
|
310
|
+
std::lock_guard<std::mutex> g(m_);
|
|
311
|
+
|
|
312
|
+
if (closed_) return;
|
|
313
|
+
|
|
314
|
+
closed_ = true;
|
|
315
|
+
queued.swap(queue_);
|
|
316
|
+
assigned.swap(assigned_);
|
|
317
|
+
|
|
318
|
+
for (auto& task : queued) task->place_ = detail::ComputeTask::Place::None;
|
|
319
|
+
stats_.cancelledQueued += queued.size();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
Error reason = computePoolShutdownError();
|
|
323
|
+
|
|
324
|
+
for (auto& task : assigned) {
|
|
325
|
+
task->context_.cancel();
|
|
326
|
+
task->abandon(reason);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
for (auto& task : queued) {
|
|
330
|
+
task->abandon(reason);
|
|
331
|
+
task->tracePhase("compute.wait", nullptr);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
for (auto& worker : workers_) worker->shutdown();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
bool ComputePool::waitStopped(double timeoutMs) {
|
|
338
|
+
auto deadline = std::chrono::steady_clock::now() + std::chrono::microseconds(static_cast<int64_t>(timeoutMs * 1000));
|
|
339
|
+
|
|
340
|
+
for (auto& worker : workers_) {
|
|
341
|
+
double left = std::chrono::duration<double, std::milli>(deadline - std::chrono::steady_clock::now()).count();
|
|
342
|
+
if (!worker->waitStopped(std::max(left, 0.0))) return false;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
ComputeStats ComputePool::stats() const {
|
|
349
|
+
std::lock_guard<std::mutex> g(m_);
|
|
350
|
+
|
|
351
|
+
ComputeStats stats = stats_;
|
|
352
|
+
stats.queued = queue_.size();
|
|
353
|
+
stats.running = assigned_.size();
|
|
354
|
+
return stats;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
void ComputePool::setTimingSink(TimingSink sink) {
|
|
358
|
+
std::shared_ptr<const TimingSink> replaced = sink ? std::make_shared<const TimingSink>(std::move(sink)) : nullptr;
|
|
359
|
+
|
|
360
|
+
{
|
|
361
|
+
std::lock_guard<std::mutex> g(m_);
|
|
362
|
+
|
|
363
|
+
std::swap(sink_, replaced);
|
|
364
|
+
timing_.store(sink_ != nullptr, std::memory_order_relaxed);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// The old sink, if no task still holds it, goes here, outside the lock.
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
} // namespace lucent
|