aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/JSCTaskScheduler.cpp
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-07-22 04:31:58 -0700
committerGravatar GitHub <noreply@github.com> 2023-07-22 04:31:58 -0700
commitc6a3467625fede0fe9901ab53b0aabd651866b64 (patch)
tree6cdd9bfd79756e97081b45de5323a7bbde62ceff /src/bun.js/bindings/JSCTaskScheduler.cpp
parent636cec03e10ab487b1df3057aaab60b4d2b02c99 (diff)
downloadbun-c6a3467625fede0fe9901ab53b0aabd651866b64.tar.gz
bun-c6a3467625fede0fe9901ab53b0aabd651866b64.tar.zst
bun-c6a3467625fede0fe9901ab53b0aabd651866b64.zip
Unified event loop (#3741)
* Unified event loop * Update WebKit, add test for es-module-lexer * Update README.md * Use async wasm * Explicitly set whether concurrenttask should be deinit'd * Update package.json --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/bindings/JSCTaskScheduler.cpp')
-rw-r--r--src/bun.js/bindings/JSCTaskScheduler.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/bun.js/bindings/JSCTaskScheduler.cpp b/src/bun.js/bindings/JSCTaskScheduler.cpp
new file mode 100644
index 000000000..436be4c0a
--- /dev/null
+++ b/src/bun.js/bindings/JSCTaskScheduler.cpp
@@ -0,0 +1,101 @@
+#include "config.h"
+#include <JavaScriptCore/VM.h>
+#include "JSCTaskScheduler.h"
+#include "BunClientData.h"
+
+using Ticket = JSC::DeferredWorkTimer::Ticket;
+using Task = JSC::DeferredWorkTimer::Task;
+using TicketData = JSC::DeferredWorkTimer::TicketData;
+
+namespace Bun {
+using namespace JSC;
+
+extern "C" void Bun__queueJSCDeferredWorkTaskConcurrently(void* bunVM, void* task);
+extern "C" void Bun__eventLoop__incrementRefConcurrently(void* bunVM, int delta);
+
+class JSCDeferredWorkTask {
+public:
+ JSCDeferredWorkTask(Ticket ticket, Task&& task)
+ : ticket(ticket)
+ , task(WTFMove(task))
+ {
+ }
+
+ Ticket ticket;
+ Task task;
+
+ WTF_MAKE_FAST_ALLOCATED;
+};
+
+static JSC::VM& getVM(Ticket ticket)
+{
+ return ticket->scriptExecutionOwner.get()->vm();
+}
+
+void JSCTaskScheduler::onAddPendingWork(std::unique_ptr<TicketData> ticket, JSC::DeferredWorkTimer::WorkKind kind)
+{
+ JSC::VM& vm = getVM(ticket.get());
+ auto clientData = WebCore::clientData(vm);
+ auto& scheduler = clientData->deferredWorkTimer;
+ LockHolder holder { scheduler.m_lock };
+ if (kind != DeferredWorkTimer::WorkKind::Other) {
+
+ Bun__eventLoop__incrementRefConcurrently(clientData->bunVM, 1);
+ scheduler.m_pendingTicketsKeepingEventLoopAlive.add(WTFMove(ticket));
+ } else {
+ scheduler.m_pendingTicketsOther.add(WTFMove(ticket));
+ }
+}
+void JSCTaskScheduler::onScheduleWorkSoon(Ticket ticket, Task&& task)
+{
+ auto* job = new JSCDeferredWorkTask(ticket, WTFMove(task));
+ Bun__queueJSCDeferredWorkTaskConcurrently(WebCore::clientData(getVM(ticket))->bunVM, job);
+}
+
+void JSCTaskScheduler::onCancelPendingWork(Ticket ticket)
+{
+ auto& scheduler = WebCore::clientData(getVM(ticket))->deferredWorkTimer;
+
+ LockHolder holder { scheduler.m_lock };
+ bool isKeepingEventLoopAlive = scheduler.m_pendingTicketsKeepingEventLoopAlive.removeIf([ticket](const auto& pendingTicket) {
+ return pendingTicket.get() == ticket;
+ });
+
+ if (isKeepingEventLoopAlive) {
+ holder.unlockEarly();
+ JSC::VM& vm = getVM(ticket);
+ Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(vm)->bunVM, -1);
+ } else {
+ scheduler.m_pendingTicketsOther.removeIf([ticket](const auto& pendingTicket) {
+ return pendingTicket.get() == ticket;
+ });
+ }
+}
+
+static void runPendingWork(void* bunVM, Bun::JSCTaskScheduler& scheduler, JSCDeferredWorkTask* job)
+{
+ LockHolder holder { scheduler.m_lock };
+ auto pendingTicket = scheduler.m_pendingTicketsKeepingEventLoopAlive.take(job->ticket);
+ if (!pendingTicket) {
+ pendingTicket = scheduler.m_pendingTicketsOther.take(job->ticket);
+ } else {
+ Bun__eventLoop__incrementRefConcurrently(bunVM, -1);
+ }
+ holder.unlockEarly();
+
+ if (pendingTicket && !pendingTicket->isCancelled()) {
+ job->task(job->ticket);
+ }
+
+ delete job;
+}
+
+extern "C" void Bun__runDeferredWork(Bun::JSCDeferredWorkTask* job)
+{
+ auto& vm = getVM(job->ticket);
+ auto clientData = WebCore::clientData(vm);
+
+ runPendingWork(clientData->bunVM, clientData->deferredWorkTimer, job);
+}
+
+}