PNG  IHDR* pHYs+ IDATx]n#; cdLb Ǚ[at¤_:uP}>!Usă cag޿ ֵNu`ݼTâabO7uL&y^wFٝA"l[|ŲHLN밪4*sG3|Dv}?+y߉{OuOAt4Jj.u]Gz*҉sP'VQKbA1u\`& Af;HWj hsO;ogTu uj7S3/QzUr&wS`M$X_L7r2;aE+ώ%vikDA:dR+%KzƉo>eOth$z%: :{WwaQ:wz%4foɹE[9<]#ERINƻv溂E%P1i01 |Jvҗ&{b?9g=^wζXn/lK::90KwrюO\!ջ3uzuGv^;騢wq<Iatv09:tt~hEG`v;3@MNZD.1]L:{ծI3`L(÷ba")Y.iljCɄae#I"1 `3*Bdz>j<fU40⨬%O$3cGt]j%Fߠ_twJ;ABU8vP3uEԑwQ V:h%))LfraqX-ۿX]v-\9I gl8tzX ]ecm)-cgʒ#Uw=Wlێn(0hPP/ӨtQ“&J35 $=]r1{tLuǮ*i0_;NƝ8;-vݏr8+U-kruȕYr0RnC]*ެ(M:]gE;{]tg(#ZJ9y>utRDRMdr9㪩̞zֹb<ģ&wzJM"iI( .ꮅX)Qw:9,i좜\Ԛi7&N0:asϓc];=ΗOӣ APqz93 y $)A*kVHZwBƺnWNaby>XMN*45~ղM6Nvm;A=jֲ.~1}(9`KJ/V F9[=`~[;sRuk]rєT!)iQO)Y$V ی ۤmzWz5IM Zb )ˆC`6 rRa}qNmUfDsWuˤV{ Pݝ'=Kֳbg,UҘVz2ﴻnjNgBb{? ߮tcsͻQuxVCIY۠:(V뺕 ٥2;t`@Fo{Z9`;]wMzU~%UA蛚dI vGq\r82iu +St`cR.6U/M9IENDB`// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef INCLUDE_CPPGC_PLATFORM_H_ #define INCLUDE_CPPGC_PLATFORM_H_ #include #include "cppgc/source-location.h" #include "v8-platform.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory) namespace cppgc { // TODO(v8:10346): Create separate includes for concepts that are not // V8-specific. using IdleTask = v8::IdleTask; using JobHandle = v8::JobHandle; using JobDelegate = v8::JobDelegate; using JobTask = v8::JobTask; using PageAllocator = v8::PageAllocator; using Task = v8::Task; using TaskPriority = v8::TaskPriority; using TaskRunner = v8::TaskRunner; using TracingController = v8::TracingController; /** * Platform interface used by Heap. Contains allocators and executors. */ class V8_EXPORT Platform { public: virtual ~Platform() = default; /** * \returns the allocator used by cppgc to allocate its heap and various * support structures. Returning nullptr results in using the `PageAllocator` * provided by `cppgc::InitializeProcess()` instead. */ virtual PageAllocator* GetPageAllocator() = 0; /** * Monotonically increasing time in seconds from an arbitrary fixed point in * the past. This function is expected to return at least * millisecond-precision values. For this reason, * it is recommended that the fixed point be no further in the past than * the epoch. **/ virtual double MonotonicallyIncreasingTime() = 0; /** * Foreground task runner that should be used by a Heap. */ virtual std::shared_ptr GetForegroundTaskRunner() { return nullptr; } /** * Posts `job_task` to run in parallel. Returns a `JobHandle` associated with * the `Job`, which can be joined or canceled. * This avoids degenerate cases: * - Calling `CallOnWorkerThread()` for each work item, causing significant * overhead. * - Fixed number of `CallOnWorkerThread()` calls that split the work and * might run for a long time. This is problematic when many components post * "num cores" tasks and all expect to use all the cores. In these cases, * the scheduler lacks context to be fair to multiple same-priority requests * and/or ability to request lower priority work to yield when high priority * work comes in. * A canonical implementation of `job_task` looks like: * \code * class MyJobTask : public JobTask { * public: * MyJobTask(...) : worker_queue_(...) {} * // JobTask implementation. * void Run(JobDelegate* delegate) override { * while (!delegate->ShouldYield()) { * // Smallest unit of work. * auto work_item = worker_queue_.TakeWorkItem(); // Thread safe. * if (!work_item) return; * ProcessWork(work_item); * } * } * * size_t GetMaxConcurrency() const override { * return worker_queue_.GetSize(); // Thread safe. * } * }; * * // ... * auto handle = PostJob(TaskPriority::kUserVisible, * std::make_unique(...)); * handle->Join(); * \endcode * * `PostJob()` and methods of the returned JobHandle/JobDelegate, must never * be called while holding a lock that could be acquired by `JobTask::Run()` * or `JobTask::GetMaxConcurrency()` -- that could result in a deadlock. This * is because (1) `JobTask::GetMaxConcurrency()` may be invoked while holding * internal lock (A), hence `JobTask::GetMaxConcurrency()` can only use a lock * (B) if that lock is *never* held while calling back into `JobHandle` from * any thread (A=>B/B=>A deadlock) and (2) `JobTask::Run()` or * `JobTask::GetMaxConcurrency()` may be invoked synchronously from * `JobHandle` (B=>JobHandle::foo=>B deadlock). * * A sufficient `PostJob()` implementation that uses the default Job provided * in libplatform looks like: * \code * std::unique_ptr PostJob( * TaskPriority priority, std::unique_ptr job_task) override { * return std::make_unique( * std::make_shared( * this, std::move(job_task), kNumThreads)); * } * \endcode */ virtual std::unique_ptr PostJob( TaskPriority priority, std::unique_ptr job_task) { return nullptr; } /** * Returns an instance of a `TracingController`. This must be non-nullptr. The * default implementation returns an empty `TracingController` that consumes * trace data without effect. */ virtual TracingController* GetTracingController(); }; /** * Process-global initialization of the garbage collector. Must be called before * creating a Heap. * * Can be called multiple times when paired with `ShutdownProcess()`. * * \param page_allocator The allocator used for maintaining meta data. Must stay * always alive and not change between multiple calls to InitializeProcess. If * no allocator is provided, a default internal version will be used. */ V8_EXPORT void InitializeProcess(PageAllocator* page_allocator = nullptr); /** * Must be called after destroying the last used heap. Some process-global * metadata may not be returned and reused upon a subsequent * `InitializeProcess()` call. */ V8_EXPORT void ShutdownProcess(); namespace internal { V8_EXPORT void Fatal(const std::string& reason = std::string(), const SourceLocation& = SourceLocation::Current()); } // namespace internal } // namespace cppgc #endif // INCLUDE_CPPGC_PLATFORM_H_