Open harryfei opened 7 years ago
Haven't tried it yet. Sciter has become thread-safe not so long ago (since 3.3.1.9) and had issues at the beginning with it.
Okay, I will take a look. Or you can make a PR with corresponding improvements and examples.
I will try. :smile:
I hope make sciter::Element
multi thread friendly first, using working thread update dom is very common way to avoid blocking ui thread.
Partly true, because UI thread can be blocked by Sciter itself (that's how thread safe API calls are implemented). But not always, of course.
As for Send+Sync
candidates - it is sciter::Element
and sciter::Value
.
macro_rules! MAKE_HANDLE {
($name:ident, $inner:ident) => {
#[repr(C)]
pub struct $inner { _unused: usize }
pub type $name = *mut $inner;
};
}
...
MAKE_HANDLE!(HELEMENT, _HELEMENT);
...
pub struct Element {
he: HELEMENT,
}
It seems like HELEMENT
is a raw pointer comes from sciter.dll
and all Element
api pass it back to sciter.dll
. I think since sciter is thread-safe, send or sync Element
between threads should also be fine.
There we go: #18 for the Element
.
And for the Value
. However, Value API is not thread safe, so it can be marked as Send
only, but not as Sync
.
Since 0.4.21 version.
Hmm. You should isolate value received from UI before passing it to another thread.
I am not sure how to make this guarantee in Rust. May be via some handle/wrapper, which is Send
-able and which calls ValueIsolate
for its underlaying value.
sciter::SafeValue
? :)
May be via some handle/wrapper
This. Also it comes with Deref
, so it's quite easy to use:
let v = Value::map();
let mut v = v.isolate();
std::thread::spawn(move || {
v.set_item("five", 5);
println!("{:?}", *v);
});
It's not so easy. It is messy, actually.
Part of the Value API is thread safe (e.g. function calls), the rest of it is not (e.g. map/array access).
Moreover, a Value
can hold a reference to a DOM resource which must be accessed only from the GUI thread.
And the last: arrays and maps from script come as Object/Array and Object/Object types, so you can't distinguish them from class instances. And you must isolate them if you want to store or pass between threads.
Need to think.
impl Value {
fn to_function(&self) -> Option<Function> {
//check type...
Some(Function { ... })
}
}
struct Function {
raw: Value
}
impl Function {
fn call(&self,...) -> Result<...> {
...
}
}
// function call is thread safe
unsafe impl Send for Function {}
unsafe impl Sync for Function {}
Is this a solution?
Moreover, a Value can hold a reference to a DOM resource which must be accessed only from the GUI thread.
As you say, sciter::Value
also shouldn't be Send
.
You see, some values can be sent to another thread, some - don't:
So, some sciter::Value
can be sent, other - need isolate
. But isolate
converts the value to plain JSON, so it's not an option to isolate everything.
I think, the only options is to have an ability to mark an intention to send a value (isolated or not). Some kind of an unsafe wrapper.
I think the native sciter sdk(c++ library) is multiple thread friendly. However, it sucks when I use this rust binding in a multiple thead situation.
Currently both
sciter::Window
andsciter::Host
are notSync
orSend
. Do you have any plan to change this?