Comments (5)
Can you add a console.log
to the end of write_data
function and just before the call the emscripten_sleep
to confirm that write_data
doesn't return to the caller until after the last of the 3 await
statements?
I imagine what is happening here is that the webserial API requires you to return to event loop in order to do what i needs to do. emscripten_sleep
is just one way to return to the event loop. You could also try using emscripten_set_main_loop
.
BTW is this code running in on the main browser thread? If so I guess you have to be returning to the event loops anyway.
As always, could you share the full set of link flags you are using?
from emscripten.
Thank you for your reply!
First I'll give some more context, I am porting avrdude to webassembly, and yes it runs on the main browser thread, but I get the same results using pthread.
Here are my flags for with pthread:
-- CMAKE_CXX_FLAGS: -fPIC -s ALLOW_BLOCKING_ON_MAIN_THREAD -s PROXY_TO_PTHREAD -s EXPORT_NAME=avrdude -pthread -s ASYNCIFY_IMPORTS=['serialPortWrite','serialPortRecv'] -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s MAIN_MODULE -s WASM=1 -s FORCE_FILESYSTEM -s ASYNCIFY=1 -s INVOKE_RUN=0 -s WASM_BIGINT=1 -s MODULARIZE=1 -s EXPORT_KEEPALIVE=1 --bind -s "EXPORTED_FUNCTIONS=['_startAvrdude','_main','_malloc']" -s EXPORTED_RUNTIME_METHODS='["cwrap", "writeStringToMemory", "FS", "allocate", "intArrayFromString"]'
And without:
-- CMAKE_CXX_FLAGS: -fPIC -s ASYNCIFY_IMPORTS=['serialPortWrite','serialPortRecv'] -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s MAIN_MODULE -s WASM=1 -s FORCE_FILESYSTEM -s ASYNCIFY=1 -s INVOKE_RUN=0 -s WASM_BIGINT=1 -s MODULARIZE=1 -s EXPORT_KEEPALIVE=1 --bind -s "EXPORTED_FUNCTIONS=['_startAvrdude','_main','_malloc']" -s EXPORTED_RUNTIME_METHODS='["cwrap", "writeStringToMemory", "FS", "allocate", "intArrayFromString"]'
My first thought was also that the write_data function was completed later or something but it is not sadly. But here is the updated code and respective output just to make sure.
EM_ASYNC_JS(void, write_data, (EM_VAL data), {
data = new Uint8Array(Emval.toValue(data));
console.log("Sending: ", data);
const port = window.activePort;
await window.writeStream.ready;
await window.writeStream.write(data);
await window.writeStream.ready;
console.log("Data sent");
});
void serialPortWrite(const unsigned char *buf, size_t len) {
std::vector<unsigned char> data(buf, buf + len);
write_data(val(typed_memory_view(data.size(), data.data())).as_handle());
printf("Data sent from C\n");
emscripten_sleep(0);
}
Output:
Sending: Uint8Array(2) [48, 32, buffer: ArrayBuffer(2), byteLength: 2, byteOffset: 0, length: 2, Symbol(Symbol.toStringTag): 'Uint8Array'] avrdude.js:8 Data sent avrdude.js:8 Data sent from C
from emscripten.
What is your program doing right after the serialPortWrite
? Assuming its sitting the event loop then I don't see who emscripten_sleep
can be helping since all it does is return to the event loop anyway.
from emscripten.
It runs some more webassembly code it sends the 48,32 packet three times to my arduino. When it is done with those operations it will read the return data of the arduino.
EM_ASYNC_JS(void, read_data, (int timeoutMs), {
const reader = window.activePort.readable.getReader();
console.log("Reading data");
async function receive() {
const { value } = await reader.read();
return value;
}
async function timeout(timeoutMs) {
await new Promise(resolve => setTimeout(resolve, timeoutMs));
return "timeout";
}
var returnBuffer = new Uint8Array();
while (true) {
let result = await Promise.race([receive(), timeout(timeoutMs)]);
if (result instanceof Uint8Array) {
// check if it is twice the same data so check if the first half is the same as the second half if so remove the second half
let firstHalf = result.slice(0, result.length / 2);
let secondHalf = result.slice(result.length / 2, result.length);
if (firstHalf.every((value, index) => value === secondHalf[index])) {
result = firstHalf;
}
console.log("Received: ", result);
const ptr = window.funcs._malloc(result.length * Uint8Array.BYTES_PER_ELEMENT);
window.funcs.HEAPU8.set(result, ptr);
// Call the C++ function with the pointer and the length of the array
window.funcs._dataCallback(ptr, result.length);
break;
} else {
console.log("Timeout", result);
break;
}
}
reader.releaseLock();
return;
});
int serialPortRecv(unsigned char *buf, size_t len, int timeoutMs) {
std::vector<unsigned char> data = {};
data.reserve(len);
// check if there is leftover data from previous reads
if (!readBuffer.empty()) {
if (readBuffer.size() >= len) {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.begin() + len);
readBuffer.erase(readBuffer.begin(), readBuffer.begin() + len);
std::copy(data.begin(), data.end(), buf);
return 0;
} else {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.end());
readBuffer.clear();
}
}
read_data(timeoutMs);
if (!readBuffer.empty()) {
// check how much data is needed and add that much to the buffer
if (readBuffer.size() >= len) {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.begin() + len);
readBuffer.erase(readBuffer.begin(), readBuffer.begin() + len);
} else {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.end());
readBuffer.clear();
}
}
if (data.empty()) {
// fill data buf with 1s if no data was received
printf("No data received\n");
return -1;
} else {
std::copy(data.begin(), data.end(), buf);
}
return 0;
}
from emscripten.
Related Issues (20)
- Using UTF8ToString with Wasm64 HOT 4
- loading-workers error HOT 2
- emprofile generates an HTML with a syntax error HOT 1
- WebGPU: Missing enumeration(s) in WGPUBlendFactor compared to Dawn HOT 1
- SAFE_HEAP should default maximum memory to 1 block less than 2GB HOT 4
- Uncaught TypeError: Failed to execute 'uniform4fv' on 'WebGL2RenderingContext': Overload resolution failed. HOT 9
- /dev/zero is missing HOT 1
- undefined symbol `__cpp_exception` without enabled exceptions HOT 2
- emscripten_dlopen fails on Safari HOT 12
- std::vector<MyBoundType> returns UnboundTypeError HOT 5
- Crashes / misexecutions or miscompilations with growable memory and atomics HOT 37
- dlopen + pthreads with FS not working HOT 1
- CGAL freezes on boolean operations HOT 1
- put_time returning time zone as "Easter" HOT 8
- sphinx==2.4.4 is imcompatatible with some dependencies after installing requirements-dev.txt
- Invalid assertion in acorn-optimizer - firebaseui web sdk HOT 2
- No transitive dependency with emscripten ports HOT 6
- Template Instantiation Error in system/lib/libcxx/include/__memory/pointer_traits.h HOT 1
- File-related syscalls, like readdir, can not handle empty directories properly HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from emscripten.