Skip to content

Inert "raw pointer" for JsValue #999

@RSSchermer

Description

@RSSchermer

I'm working on an abstraction around the WebGl2/OpenGL ES3 interface that I'm hoping to make thread-/worker-safe. The core concept revolves around secondary threads/workers constructing monadic Task objects which are then submitted back to the main thread (or hopefully, one day, an offscreen-canvas thread/worker). For the ergonomics of the API it's important that certain resource handles (buffers, textures, programs, etc.) can live in these secondary threads, and this is where I run into problems.

These resource handles need to be associated with the actual OpenGL GPU resources they represent. In OpenGL I can do this by storing the actual GLUints in a resource handle. Of course, the web platform chose to integrate the deletion of GPU resources with JS garbage collection by wrapping them in JS objects, which makes this not an option for WebGl.

JsValue is - understandably - not Send/Sync, which means I also cannot store the JsValue in my resource handles. With the current public wasm-bindgen interface, the only option this seems to leave is to maintain a hashtable on the main thread which maps my own identifiers to JsValues. That would however kind of duplicate wasm-bindgen's own internal hashtable lookup, which I'd rather avoid.

Given wasm-bindgen's current implementation, it seems that perhaps the idx stored inside a JsValue would be the ideal way to associate my resource handles with the WebGl objects. This left me wondering if perhaps an analogue to Box's into_raw and from_raw would be possible/desirable:

#[derive(Clone, Copy)]
struct JsId {
    idx: u32
}

impl JsValue {
    pub fn into_raw(js_value: JsValue) -> JsId {
        let idx = js_value.idx;
        
        mem::forget(js_value);

        JsId {
            idx
        }
    }

    pub unsafe fn from_raw(raw: JsId) {
        JsValue {
            idx: raw.idx,
            _marker: marker::PhantomData,
        }
    }
}

The caller of into_raw would then be responsible for freeing the JsValue entry in wasm-bindgen's hashtable by calling from_raw at a later time. The documentation for from_raw would mention that it is only safe to call it on a JsId in the same thread/worker that originally created the JsId. The JsId would be otherwise inert, it simply serves as a thread-safe identifier until its converted back into a JsValue.

Would something like this be considered? Also, would there be an alternative after the host-bindings proposal lands? Would JsValue's idx then be replaced with some sort of anyref as mentioned in the reference-types proposal? I've looked at the host-bindings, threads and reference-types proposals, but I can't quite evaluate whether or not there will be a mechanism that would prevent these anyrefs from being shared/passed between threads/workers. Perhaps someone here is more intimately involved with the inner workings of current and future WASM and knows this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions