File tree 5 files changed +71
-4
lines changed
examples/emscripten-tests 5 files changed +71
-4
lines changed Original file line number Diff line number Diff line change
1
+ // basic file operations
2
+ #include < iostream>
3
+ #include < fstream>
4
+ #include < string>
5
+ #include < vector>
6
+ #include < thread>
7
+ #include < emscripten.h>
8
+ #include " pthreadfs.h"
9
+
10
+
11
+ void threadMain (int msg) {
12
+ size_t thread_id = std::hash<std::thread::id>{}(std::this_thread::get_id ());
13
+ std::ofstream myfile;
14
+ myfile.open (" filesystemaccess/multi_threading_example" , std::ios_base::app);
15
+ myfile << " Writing from thread " << msg << " Id: " << thread_id << " " ;
16
+ myfile.close ();
17
+ EM_ASM ({console.log (`Wrote on thread ${$0 }`);}, thread_id);
18
+ return ;
19
+ }
20
+
21
+ int main () {
22
+ emscripten_init_pthreadfs ();
23
+ EM_ASM ({console.log (" Hello from main" )});
24
+ std::remove (" filesystemaccess/multi_threading_example" );
25
+
26
+ constexpr int number_of_threads = 10 ;
27
+
28
+ std::cout << " Proof that stdout works fine.\n " ;
29
+
30
+ std::vector<std::thread> threads;
31
+
32
+ for (int i = 0 ; i< number_of_threads; i++) {
33
+ std::thread thread (threadMain, i);
34
+ threads.push_back (std::move (thread));
35
+ }
36
+
37
+ std::ofstream myfile;
38
+ myfile.open (" filesystemaccess/multi_threading_example" );
39
+ myfile << " Writing the main thread.\n " ;
40
+ myfile.close ();
41
+
42
+ for (int i = 0 ; i< number_of_threads; i++) {
43
+ threads[i].join ();
44
+ }
45
+
46
+ EM_ASM ({
47
+ console.log (' Remember to check that the contents of file multi_threading_example are correct.' );
48
+ });
49
+
50
+ return 0 ;
51
+ }
Original file line number Diff line number Diff line change @@ -33,6 +33,9 @@ void SyncToAsync::shutdown() {
33
33
}
34
34
35
35
void SyncToAsync::doWork (std::function<void (SyncToAsync::Callback)> newWork) {
36
+ // Use the doWorkMutex to prevent more than one doWork being in flight at a
37
+ // time, so that this is usable from multiple threads safely.
38
+ std::lock_guard<std::mutex> doWorkLock (doWorkMutex);
36
39
// Send the work over.
37
40
{
38
41
std::lock_guard<std::mutex> lock (mutex);
@@ -302,4 +305,4 @@ void emscripten_init_pthreadfs() {
302
305
init_fsafs (&resumeWrapper_v);
303
306
});
304
307
return ;
305
- }
308
+ }
Original file line number Diff line number Diff line change @@ -190,11 +190,16 @@ class SyncToAsync {
190
190
// Run some work on thread. This is a synchronous call, but the thread can do
191
191
// async work for us. To allow us to know when the async work finishes, the
192
192
// worker is given a function to call at that time.
193
+ //
194
+ // It is safe to call this method from multiple threads, as it locks itself.
195
+ // That is, you can create an instance of this and call it from multiple
196
+ // threads freely.
193
197
void doWork (std::function<void (Callback)> newWork);
194
198
195
199
private:
196
200
std::thread thread;
197
201
std::mutex mutex;
202
+ std::mutex doWorkMutex;
198
203
std::condition_variable condition;
199
204
std::function<void (Callback)> work;
200
205
bool readyToWork = false ;
@@ -221,4 +226,4 @@ void resumeWrapper_l(long retVal);
221
226
222
227
void resumeWrapper_wasi (__wasi_errno_t retVal);
223
228
224
- #endif // PTHREADFS_H
229
+ #endif // PTHREADFS_H
Original file line number Diff line number Diff line change @@ -33,6 +33,9 @@ void SyncToAsync::shutdown() {
33
33
}
34
34
35
35
void SyncToAsync::doWork (std::function<void (SyncToAsync::Callback)> newWork) {
36
+ // Use the doWorkMutex to prevent more than one doWork being in flight at a
37
+ // time, so that this is usable from multiple threads safely.
38
+ std::lock_guard<std::mutex> doWorkLock (doWorkMutex);
36
39
// Send the work over.
37
40
{
38
41
std::lock_guard<std::mutex> lock (mutex);
@@ -302,4 +305,4 @@ void emscripten_init_pthreadfs() {
302
305
init_fsafs (&resumeWrapper_v);
303
306
});
304
307
return ;
305
- }
308
+ }
Original file line number Diff line number Diff line change @@ -190,11 +190,16 @@ class SyncToAsync {
190
190
// Run some work on thread. This is a synchronous call, but the thread can do
191
191
// async work for us. To allow us to know when the async work finishes, the
192
192
// worker is given a function to call at that time.
193
+ //
194
+ // It is safe to call this method from multiple threads, as it locks itself.
195
+ // That is, you can create an instance of this and call it from multiple
196
+ // threads freely.
193
197
void doWork (std::function<void (Callback)> newWork);
194
198
195
199
private:
196
200
std::thread thread;
197
201
std::mutex mutex;
202
+ std::mutex doWorkMutex;
198
203
std::condition_variable condition;
199
204
std::function<void (Callback)> work;
200
205
bool readyToWork = false ;
@@ -221,4 +226,4 @@ void resumeWrapper_l(long retVal);
221
226
222
227
void resumeWrapper_wasi (__wasi_errno_t retVal);
223
228
224
- #endif // PTHREADFS_H
229
+ #endif // PTHREADFS_H
You can’t perform that action at this time.
0 commit comments