1/*
2 * Copyright 2016 WebAssembly Community Group participants
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//
18// Threads helpers.
19//
20
21#ifndef wasm_support_threads_h
22#define wasm_support_threads_h
23
24#include <atomic>
25#include <cassert>
26#include <condition_variable>
27#include <functional>
28#include <memory>
29#include <mutex>
30#include <thread>
31#include <vector>
32
33#include "compiler-support.h"
34
35namespace wasm {
36
37// The work state of a helper thread - is there more to do,
38// or are we finished for now.
39enum class ThreadWorkState { More, Finished };
40
41class ThreadPool;
42
43//
44// A helper thread.
45//
46// You can only create and destroy these on the main thread.
47//
48
49class Thread {
50 ThreadPool* parent;
51 std::unique_ptr<std::thread> thread;
52 std::mutex mutex;
53 std::condition_variable condition;
54 bool done = false;
55 std::function<ThreadWorkState()> doWork = nullptr;
56
57public:
58 Thread(ThreadPool* parent);
59 ~Thread();
60
61 // Start to do work, calling doWork() until
62 // it returns false.
63 void work(std::function<ThreadWorkState()> doWork);
64
65private:
66 static void mainLoop(void* self);
67};
68
69//
70// A pool of helper threads.
71//
72// There is only one, to avoid recursive pools using too many cores.
73//
74
75class ThreadPool {
76 std::vector<std::unique_ptr<Thread>> threads;
77 bool running = false;
78 std::condition_variable condition;
79 std::atomic<size_t> ready;
80
81 // A mutex for creating the pool safely
82 static std::mutex creationMutex;
83 // A mutex for work() so that the pool can only work on one
84 // thing at a time
85 static std::mutex workMutex;
86 // A mutex for communication with the worker threads
87 static std::mutex threadMutex;
88
89private:
90 void initialize(size_t num);
91
92public:
93 // Get the number of cores we can use.
94 static size_t getNumCores();
95
96 // Get the singleton threadpool.
97 static ThreadPool* get();
98
99 // Execute a bunch of tasks by the pool. This calls
100 // getTask() (in a thread-safe manner) to get tasks, and
101 // sends them to workers to be executed. This method
102 // blocks until all tasks are complete.
103 void work(std::vector<std::function<ThreadWorkState()>>& doWorkers);
104
105 size_t size();
106
107 bool isRunning();
108
109 // Called by helper threads when they are free and ready.
110 void notifyThreadIsReady();
111
112private:
113 void resetThreadsAreReady();
114
115 bool areThreadsReady();
116};
117
118// Verify a code segment is only entered once. Usage:
119// static OnlyOnce onlyOnce;
120// onlyOnce.verify();
121
122class OnlyOnce {
123 std::atomic<int> created;
124
125public:
126 OnlyOnce() { created.store(0); }
127
128 void verify() {
129 [[maybe_unused]] auto before = created.fetch_add(1);
130 assert(before == 0);
131 }
132};
133
134} // namespace wasm
135
136#endif // wasm_support_threads_h
137

source code of dart_sdk/third_party/binaryen/src/src/support/threads.h