You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+43-24
Original file line number
Diff line number
Diff line change
@@ -10,27 +10,36 @@
10
10
11
11
Serialisable closures.
12
12
13
-
This library provides macros to wrap closures such that they can serialised and sent between other processes running the same binary.
13
+
This library provides macros to wrap closures such that they can serialised and
14
+
sent between other processes running the same binary.
14
15
15
16
```rust
16
17
fnsum_of_squares(input:&[i32]) ->i32 {
17
18
input.dist_iter()
18
-
.map(Fn!(|i:&_|*i**i))
19
+
.map(Fn!(|&i|i*i))
19
20
.sum()
20
21
}
21
22
```
22
23
23
-
For example, if you have the same binary running on each of a cluster of machines, this library would help you to send closures between them.
24
+
For example, if you have the same binary running on each of a cluster of
25
+
machines, this library would help you to send closures between them.
24
26
25
-
This library aims to work in as simple and un-magical a way as possible. It currently requires nightly Rust for the `unboxed_closures` and `fn_traits` features (rust issue [#29625](https://github.com/rust-lang/rust/issues/29625)).
27
+
This library aims to work in as simple and un-magical a way as possible. It
28
+
currently requires nightly Rust for the `unboxed_closures` and `fn_traits`
29
+
features (rust issue [#29625](https://github.com/rust-lang/rust/issues/29625)).
26
30
27
-
* There are three macros, [FnOnce](https://docs.rs/serde_closure/0.1.0/serde_closure/macro.FnOnce.html), [FnMut](https://docs.rs/serde_closure/0.1.0/serde_closure/macro.FnMut.html) and [Fn](https://docs.rs/serde_closure/0.1.0/serde_closure/macro.Fn.html), corresponding to the three types of Rust closure.
28
-
* The *captured variables*, i.e. those variables that are referenced by the closure but are declared outside of it, must be explicitly listed.
29
-
* The closure is coerced to a function pointer, which is serialized as an `isize` relative to a known base address.
30
-
* It is deserialised by adding this isize to the known base address, and transmuting to a function pointer.
31
-
* This is the only necessitation of unsafety, and is reliant upon the function pointer being positioned identically relative to the base in both processes – hence both binaries must be identical.
32
-
* To the best of my knowledge this holds in Rust for a given binary. If somehow the known base and the function pointer are in different objects and are loaded at different relative addresses, then this will fail, very likely as a segfault.
33
-
* A solution in this case would be to compile a statically linked executable – in Rust this currently means adding `--target x86_64-unknown-linux-musl` or similar to the cargo or rustc command line.
* The *captured variables*, i.e. those variables that are referenced by the
37
+
closure but are declared outside of it, must be explicitly listed.
38
+
* There are currently some minor limitations of syntax over normal closure
39
+
syntax, which are documented below.
40
+
* The closure is coerced to a function pointer, which is wrapped by
41
+
[relative::Pointer](https://docs.rs/relative) such that it can safely be sent
42
+
between processes.
34
43
35
44
## Examples of wrapped closures
36
45
**Inferred, non-capturing closure:**
@@ -56,7 +65,9 @@ move |a| num += a
56
65
letmutnum=0;
57
66
FnMut!([num] move|a|*num+=a)
58
67
```
59
-
Note: If any variables are captured then the `move` keyword must be present. As this is a FnMut closure, `num` is a mutable reference, and must be dereferenced to use.
68
+
Note: If any variables are captured then the `move` keyword must be present. As
69
+
this is a FnMut closure, `num` is a mutable reference, and must be dereferenced
70
+
to use.
60
71
61
72
**Capturing `hello` requiring extra annotation:**
62
73
```rust
@@ -79,33 +90,41 @@ Note: `hello` needs its type annotated in the closure.
As visible above, there are currently some limitations that often necessitate extra annotation that you might typically expect to be redundant.
102
-
* Type inference doesn't work as well as normal, hence extra type annotations might be needed;
103
-
* The captured variables in FnMut and FnRef closures are references, so need to be dereferenced;
112
+
As visible above, there are currently some limitations that often necessitate
113
+
extra annotation that you might typically expect to be redundant.
114
+
* Type inference doesn't work as well as normal, hence extra type annotations
115
+
might be needed;
116
+
* The captured variables in FnMut and Fn closures are references, so need to be
117
+
dereferenced;
104
118
* Types cannot be annotated in the list of captured variables;
105
-
* Either none or all of the closure arguments must be annotated; though `_` can be used;
119
+
* If any of the closure arguments are annotated with types (i.e. `|a:i32|0`)
120
+
then all must be (though `_` can be used), and patterns can no longer be used
121
+
(i.e. `|&a:&i32|0` will not work).
106
122
* The `move` keyword must be present if any variables are captured.
107
123
108
124
## License
109
-
Licensed under Apache License, Version 2.0, ([LICENSE.txt](LICENSE.txt) or http://www.apache.org/licenses/LICENSE-2.0).
125
+
Licensed under Apache License, Version 2.0, ([LICENSE.txt](LICENSE.txt) or
126
+
http://www.apache.org/licenses/LICENSE-2.0).
110
127
111
-
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions.
128
+
Unless you explicitly state otherwise, any contribution intentionally submitted
129
+
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
130
+
licensed as above, without any additional terms or conditions.
0 commit comments