Skip to content

Commit

Permalink
Merge pull request emscripten-core#5 from rstz/multiple-backend-support
Browse files Browse the repository at this point in the history
Add support for multiple storage backends
  • Loading branch information
rstz authored Sep 7, 2021
2 parents 9dbe733 + 8563ab0 commit 366cd77
Show file tree
Hide file tree
Showing 11 changed files with 545 additions and 67 deletions.
8 changes: 5 additions & 3 deletions pthreadfs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The Emscripten Pthread File System (PThreadFS) unlocks using (partly) asynchrono
PThreadFS works by replacing Emscripten's file system API with a new API that proxies all file system operations to a dedicated pthread. This dedicated thread maintains a virtual file system that can use different APIs as backend (very similar to the way Emscripten's VFS is designed). In particular, PThreadFS comes with built-in support for asynchronous backends such as [OPFS Access Handles](https://docs.google.com/document/d/121OZpRk7bKSF7qU3kQLqAEUVSNxqREnE98malHYwWec/edit#heading=h.gj2fudnvy982).
Although the underlying storage API is asynchronous, PThreadFS makes it appear synchronous to the C++ application.

If OPFS Access Handles are not available, PThreadFS will attempt to use the [Storage Foundation API](https://github.com/WICG/storage-foundation-api-explainer). As a last fallback, Emscripten's MEMFS in-memory file system is used.

The code is still prototype quality and **should not be used in a production environment** for the time being.

## Enable and detect OPFS in Chrome
Expand Down Expand Up @@ -69,7 +71,7 @@ In order to use the code in a new project, you only need the three files in the
#include "pthreadfs.h"
```
- Call `emscripten_init_pthreadfs();` at the top of `main()` (or before any file system syscalls).
- PThreadFS maintains a virtual file system. The OPFS backend is mounted at `/filesystemaccess/`. Only files in this folder are persisted between sessions. All other files will be stored in-memory through MEMFS.
- PThreadFS maintains a virtual file system. The OPFS backend is mounted at `/pthreadfs/`. Only files in this folder are persisted between sessions. All other files will be stored in-memory through MEMFS.

### Build process changes

Expand Down Expand Up @@ -102,8 +104,8 @@ See `pthreadfs/examples/emscripten-tests/fsafs.cpp` for exemplary usage.

## Known Limitations

- All files to be stored using the file system access Access Handles must be stored in the `/filesystemaccess` folder.
- Files in the `/filesystemaccess` folder cannot interact through syscalls with other files (e.g. moving, copying, etc.).
- All files to be stored using the file system access Access Handles must be stored in the `/pthreadfs` folder.
- Files in the `/pthreadfs` folder cannot interact through syscalls with other files (e.g. moving, copying, etc.).
- The code is still prototype quality and **should not be used in a production environment** yet. It is possible that the use of PThreadFS might lead to subtle bugs in other libraries.
- PThreadFS requires PROXY_TO_PTHREAD to be active. In particular, no system calls interacting with the file system should be called from the main thread.
- Some functionality of the Emscripten File System API is missing, such as sockets, IndexedDB integration and support for XHRequests.
Expand Down
19 changes: 9 additions & 10 deletions pthreadfs/examples/emscripten-tests/fsafs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,31 @@

int main () {
emscripten_init_pthreadfs();
std::cout << "std::cout works fine.\n";
std::cout << "Proof that stdout works fine.\n";
std::ofstream myfile;
myfile.open ("filesystemaccess/example");
myfile << "Writing a few characters to the example file.\n";
myfile.open ("pthreadfs/example");
myfile << "Writing a few characters.\n";
myfile.close();

std::string line;
std::ifstream myfile_read ("filesystemaccess/example");
std::ifstream myfile_read ("pthreadfs/example");

if (myfile_read.is_open()) {
std::getline(myfile_read, line);
EM_ASM({
console.log("Read line " + UTF8ToString($0));
EM_ASM({console.log("Read line" + UTF8ToString($0));
}, line.c_str());
myfile_read.close();
}

std::ofstream stream1 ("filesystemaccess/multistreamexample");
std::ofstream stream2 ("filesystemaccess/multistreamexample");
std::ofstream stream1 ("pthreadfs/multistreamexample");
std::ofstream stream2 ("pthreadfs/multistreamexample");
stream1 << "Write a line through stream1.\n";
stream2 << "Write a line through stream2.\n";
stream1.close();
stream2.close();

std::remove("filesystemaccess/multistreamexample");
bool can_open_deleted_file = (bool) std::ifstream("filesystemaccess/multistreamexample");
std::remove("pthreadfs/multistreamexample");
bool can_open_deleted_file = (bool) std::ifstream("pthreadfs/multistreamexample");
if(!can_open_deleted_file) {
std::cout << "Opening deleted file failed, as expected.\n";
}
Expand Down
6 changes: 3 additions & 3 deletions pthreadfs/examples/emscripten-tests/multiple_threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
void threadMain(int msg) {
size_t thread_id = std::hash<std::thread::id>{}(std::this_thread::get_id());
std::ofstream myfile;
myfile.open ("filesystemaccess/multi_threading_example", std::ios_base::app);
myfile.open ("pthreadfs/multi_threading_example", std::ios_base::app);
myfile << "Writing from thread " << msg << " Id: " << thread_id << " ";
myfile.close();
EM_ASM({console.log(`Wrote on thread ${$0}`);}, thread_id);
Expand All @@ -21,7 +21,7 @@ void threadMain(int msg) {
int main () {
emscripten_init_pthreadfs();
EM_ASM({console.log("Hello from main")});
std::remove("filesystemaccess/multi_threading_example");
std::remove("pthreadfs/multi_threading_example");

constexpr int number_of_threads = 10;

Expand All @@ -35,7 +35,7 @@ int main () {
}

std::ofstream myfile;
myfile.open ("filesystemaccess/multi_threading_example");
myfile.open ("pthreadfs/multi_threading_example");
myfile << "Writing the main thread.\n";
myfile.close();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ var Module = Module || {};
Module['arguments'] = Module['arguments'] || [];
Module['arguments'].push('--size');
Module['arguments'].push('40');
Module['arguments'].push(`/filesystemaccess/db${Math.random()}`);
Module['arguments'].push(`/pthreadfs/db${Math.random()}`);
Loading

0 comments on commit 366cd77

Please sign in to comment.