Getting reference to shared data in async closure [duplicate] - concurrency

I have something like this:
use std::sync::Arc;
fn main() {
let arc = Arc::new(42);
move || { arc.clone() };
move || { arc.clone() };
}
I am getting:
error[E0382]: capture of moved value: `arc`
--> src/main.rs:6:19
|
5 | move || { arc.clone() };
| ------- value moved (into closure) here
6 | move || { arc.clone() };
| ^^^ value captured here after move
|
= note: move occurs because `arc` has type `std::sync::Arc<i32>`, which does not implement the `Copy` trait
I understand why I am getting this: the clone isn't called before arc is passed to the closure. I can fix this by defining each closure in a function and clone the Arc before passing it to the closure, but is there another option?

There is no way around it. You should clone the Arc before it is used in a closure. The common pattern is to re-bind the cloned Arc to the same name in a nested scope:
use std::sync::Arc;
fn main() {
let arc = Arc::new(42);
{
let arc = arc.clone();
move || { /* do something with arc */ };
}
{
let arc = arc.clone();
move || { /* do something else with arc */ };
}
}
This is usually done together with thread::spawn():
use std::sync::{Arc, Mutex};
use std::thread;
const NUM_THREADS: usize = 4;
fn main() {
let arc = Arc::new(Mutex::new(42));
for _ in 0..NUM_THREADS {
let arc = arc.clone();
thread::spawn(move || {
let mut shared_data = arc.lock().unwrap();
*shared_data += 1;
});
}
}

is there another option?
Because this pattern of cloning things before defining a closure is somewhat common, some people have proposed adding something like clone || as an analog to move ||. I wouldn't hold out hope for this happening, but a number of comments there point out that macros can solve the case fairly well.
Several crates provide some form of this macro:
closet
capture
clone_all
It's likely that many projects define their own macro to do something similar. For example, the WASM example rust-todomvc defines:
macro_rules! enclose {
( ($( $x:ident ),*) $y:expr ) => {
{
$(let $x = $x.clone();)*
$y
}
};
}
Which can be used as:
fn main() {
let arc = Arc::new(42);
enclose! { (arc) move || arc };
enclose! { (arc) move || arc };
}

Related

Preventing a Fn from being invoked again while it's already running

I am using inputbot to write a program that provides some global macros for my computer. For example, when I press the h key, it should execute the macro typing
Hello World
into the current application. I tried to implement it like this:
extern crate inputbot;
fn main() {
let mut callback = || {
inputbot::KeySequence("Hello World").send();
};
inputbot::KeybdKey::HKey.bind(callback);
inputbot::handle_input_events();
}
However, when I pressed the h key what I actually got was:
hHHHHHHHHHHHHHHHHHHHHHHHHHEHEHhEhEEHHhEhEhEHhEHHEHHEEHhEHlhEHEHHEHLEHLHeeleleelelelllelelleelehlhehlleeheehelheelleeleelhllllllellelolelellelleoleloloelellololol olollollelllolllol lloo ol o oo l lo lolooloooloo loo LOWOLO O L OLW WOWO L WLLOLOW L O O O O o WOWW low o oOow WWW WOW wowooWWWO oOWRWOoor W RoW oOWorororWRRWLR rLROwoRWLWOworo WorrrRWl ow o WRLR OLw o OWLDol rollWWLDWowDLlroWWo r oWDWOL dorRrwrolrdrrorlrLWDRdodRLowdllrllolrdlrddolrdlrldowldorowlrdlrorloLDLWDLoddlrddlrdldldldrrdordldrlrddrodlrrldoldlrlddldlrdlldlrdlddrlddldddlddlddd
The macro was triggering itself each time it sent the h key event. 😬
How can I prevent a Fn from being invoked again while another instance of it is still running? This is the main functionality of a small application, so there's nothing else to really worry about compatibility with.
My naive attempt to fix
this was to add a mut running variable in main, which callback would set to true while it was running, or immediately return if it was already true:
extern crate inputbot;
use std::time::Duration;
use std::thread::sleep;
fn main() {
let mut running = false;
let mut callback = || {
if running { return };
running = true;
inputbot::KeySequence("Hello World").send();
// wait to make sure keyboard events are done.
sleep(Duration::from_millis(125));
running = false;
};
inputbot::KeybdKey::HKey.bind(callback);
inputbot::handle_input_events();
}
However, this doesn't compile:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
After some reading, my understanding is now that a Fn closure (required by inputbot's .bind() methods) can't own any mutable data, like a captured mut variable.
Maybe it's possible to wrap the variable in some kind of non-mut value? Perhaps some kind-of lock, to make the potential concurrency safe, like this pseudocde?
fn main() {
let mut running = false;
let lockedRunning = example::Lock(&running);
let mut callback = || {
{
let mut running = lockedRunning.acquire();
if running { return };
running = true;
}
inputbot::KeySequence("Hello World").send();
// wait to make sure keyboard events are done.
sleep(Duration::from_millis(125));
{
let mut running = lockedRunning.acquire();
running = false;
}
};
}
What you want here is that the function is mutually exclusive to itself.
Rust allows you to do this with the Mutex struct. It allows you to hold a lock that when acquired stops anyone else from taking it until you release it.
Specifically the functionality you want is the try_lock method which would allow you to check if the lock has already been acquired and would allow you to handle that case.
let lock = mutex.try_lock();
match lock {
Ok(_) => {
// We are the sole owners here
}
Err(TryLockError::WouldBlock) => return,
Err(TryLockError::Poisoned(_)) => {
println!("The mutex is poisoned");
return
}
}
Using an atomic value is a bit simpler than a Mutex as you don't need to worry about failure cases and it can easily be made into a static variable without using lazy-static:
use std::sync::atomic::{AtomicBool, Ordering};
fn main() {
let is_being_called = AtomicBool::new(false);
bind(move || {
if !is_being_called.compare_and_swap(false, true, Ordering::SeqCst) {
print!("I'm doing work");
is_being_called.store(false, Ordering::SeqCst);
}
});
}
I have a hunch that this is also more efficient than using a Mutex as no heap allocations need to be made, but I didn't benchmark it.
If you are in a single-threaded context and your callback is somehow (accidentally?) recursive (which closures cannot be) you can also use a Cell:
use std::cell::Cell;
fn main() {
let is_being_called = Cell::new(false);
bind(move || {
if !is_being_called.get() {
is_being_called.set(true);
print!("doing work");
is_being_called.set(false);
}
})
}
If you happen to have a FnMut closure, you don't even need the Cell and can just use a boolean:
fn main() {
let mut is_being_called = false;
bind(move || {
if !is_being_called {
is_being_called = true;
print!("doing work");
is_being_called = false;
}
})
}

How to get an arrow function's body as a string?

How to get code as string between {} of arrow function ?
var myFn=(arg1,..,argN)=>{
/**
*Want to parse
* ONLY which is between { and }
* of arrow function
*/
};
If it is easy to parse body of simple function : myFn.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]; is enough . However, Arrow function does not contains function keyword in its definition .
I came looking for a solution because I didn't feel like writing one, but I wasn't sold on the accepted answer. For anyone interested in an ES6 1-liner, I wrote this method, which handles all the cases I needed - both normal functions and arrow functions.
const getFunctionBody = method => method.toString().replace(/^\W*(function[^{]+\{([\s\S]*)\}|[^=]+=>[^{]*\{([\s\S]*)\}|[^=]+=>(.+))/i, '$2$3$4');
This is my attempt:
function getArrowFunctionBody(f) {
const matches = f.toString().match(/^(?:\s*\(?(?:\s*\w*\s*,?\s*)*\)?\s*?=>\s*){?([\s\S]*)}?$/);
if (!matches) {
return null;
}
const firstPass = matches[1];
// Needed because the RegExp doesn't handle the last '}'.
const secondPass =
(firstPass.match(/{/g) || []).length === (firstPass.match(/}/g) || []).length - 1 ?
firstPass.slice(0, firstPass.lastIndexOf('}')) :
firstPass
return secondPass;
}
const K = (x) => (y) => x;
const I = (x) => (x);
const V = (x) => (y) => (z) => z(x)(y);
const f = (a, b) => {
const c = a + b;
return c;
};
const empty = () => { return undefined; };
console.log(getArrowFunctionBody(K));
console.log(getArrowFunctionBody(I));
console.log(getArrowFunctionBody(V));
console.log(getArrowFunctionBody(f));
console.log(getArrowFunctionBody(empty));
It's probably more verbose than it needs to be because I tried to be generous about white space. Also, I'd be glad to hear if anyone knows how to skip the second pass. Finally, I decided not to do any trimming, leaving that to the caller.
Currently only handles simple function parameters. You'll also need a browser that natively supports arrow functions.

sweet.js: transforming occurrences of a repeated token

I want to define a sweet macro that transforms
{ a, b } # o
into
{ o.a, o.b }
My current attempt is
macro (#) {
case infix { { $prop:ident (,) ... } | _ $o } => {
return #{ { $prop: $o.$prop (,) ... } }
}
}
However, this give me
SyntaxError: [patterns] Ellipses level does not match in the template
I suspect I don't really understand how ... works, and may need to somehow loop over the values of $prop and build syntax objects for each and somehow concatenate them, but I'm at a loss as to how to do that.
The problem is the syntax expander thinks you're trying to expand $o.$prop instead of $prop: $o.$prop. Here's the solution:
macro (#) {
rule infix { { $prop:ident (,) ... } | $o:ident } => {
{ $($prop: $o.$prop) (,) ... }
}
}
Notice that I placed the unit of code in a $() block of its own to disambiguate the ellipse expansion.
Example: var x = { a, b } # o; becomes var x = { a: o.a, b: o.b };.

How to remove the attributes from a function type?

In the following sample the first test fails because of the function type attributes. The second test overrides the problem but it's too syntactically heavy.
import std.traits;
bool test1(T)()
{
// clean but does not work !
alias Fun = bool function(dchar);
return (is(Unqual!T == Fun));
}
bool test2(T)()
{
// super heavy !
return (isSomeFunction!T && is(ReturnType!T == bool) &&
Parameters!T.length == 1 && is(Parameters!T[0] == dchar)
);
}
void main(string[] args)
{
import std.ascii: isAlpha;
assert(test1!(typeof(&isAlpha)));
assert(test2!(typeof(&isAlpha)));
}
Is there a way to remove the attributes, just like Unqual does to storage classes ?
Check this out: http://dlang.org/phobos/std_traits.html#SetFunctionAttributes
std.traits.SetFunctionAttributes
alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T);
auto assumePure(T)(T t)
if (isFunctionPointer!T || isDelegate!T)
{
enum attrs = functionAttributes!T | FunctionAttribute.pure_;
return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
}
That example adds the attribute pure but a similar pattern can remove attributes too.

Comparing variables in two instances of a class

i have what i hope is a quick question about some code i am building out.. basically i want to compare the variables amongst two instances of a class (goldfish) to see if one is inside the territory of another. they both have territory clases which in turn use a point clase made up of an x and y data-point.
now i was curious to know why the below doesnt work please:
(this bit of code compares two points: a & b, each with two points, a north-east (ne) and south-west (sw) and their x and y plots)
if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
(a->x_sw => b->x_sw && a->y_sw => b-> sw)) {
return true;
} else return false;
I can think of a work around (for instance, by having a get location method), and using a function in the main body to compare, but im curious to know --as a budding c++ programmer -- why the above, or a similar implementation doesnt appear to work.
and also, what would be the CLEANEST and most elegant way to accomplish the above? have a friend function perhaps?
many thanks
edit: added some comments to (hopefully make the variables clearer)
// class point {
// public:
// float x;
// float y;
// point(float x_in, float y_in) { //the 2 arg constructor
// x = x_in;
// y = y_in;
// }
// };
// class territory {
// private:
// point ne, sw;
// public:
// territory(float x_ne, float y_ne, float x_sw, float y_sw)
// : ne(x_ne, y_ne), sw(x_sw,y_sw) {
// }
// bool contain_check(territory a, territory b) {
// //checks if a is contained in b (in THAT order!)
// if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
// (a->x_sw => b->x_sw && a->y_sw => b-> sw)) {
// return true;
// } else return false;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// };
// class goldfish {
// protected:
// float size;
// point pos;
// territory terr;
// public:
// goldfish(float x, float y) : pos(x,y), terr(x-1,y-1,x+1,y+1) { //constructor
// size = 2.3;
// }
// void retreat() { //what happens in the case of loss in attack
// /*
// if(goldfish.size[1] - goldfish.size[2] <= 1 && goldfish.size[1] - goldfish.size[2] > 0) {
// size = size - 0.2;
// }
// */
// }
// void triumph() {
// }
// void attack() {
// }
// // void goldfish()
// };
On first glance: There isn't a => operator. It's called >=
Assuming that your territories are rectangles and your are detecting overlap by comparing the corners of the two classes (ne and nw) you are only checking the northwest and northeast corners which have a region of a line. As #Éric Malenfant mentioned, you have structures as the class members which are accessed by the '.' operator. Those members are ne and sw so to reference them would be: "a.ne.x"
So starting with this:
if ((a->x_ne <= b->x_ne && a->y_ne <= b-> ne) &&
(a->x_nw => b->x_nw && a->y_nw => b-> nw)) {
return true;
} else return false;
Change it to:
return ( (a.ne.x <= b.ne.x && a.ne.y <= b.ne.y)
&& (a.sw.x >= b.sw.x && a.sw.y >= b.sw.y));
What do you mean by "doesnt work"? I does not compile?
If contain_check is written as shown in your post, a problem is that you are using the arrow operator on non-pointers. Use dot instead:
if ((a.x_ne <= b.x_ne && a.y_ne <= b.ne) //etc.
I noticed two possible problems right off (note: not a C++ expert):
You use => for "greater than or equal to", where it should be >=.
Also, I think b->ne should be b->y_ne.
bool contain_check(territory a, territory b)
You're passing in two territory objects, not pointers to territory objects. Consequently, you'll want to use the . operator to access members instead of the -> operator. Something like:
a.ne
Additionally, you've declared the ne and sw members private, which means that they won't be accessible to unrelated functions. They would need to be public for the contain_check() function to access them.
sorry, i was clearly (very) confused. thanks guys! below works:
if ((a.ne.x <= b.ne.x && a.ne.y <= b.ne.y) &&
(a.sw.x >= b.sw.x && a.sw.y >= b.sw.y)) {
return true;
} else return false;
}
the method bool territory::contain_check(const territory &a, const territory &b); should be declared as static. it makes sense.
or, better, write it as standalone function, because it has nothing to do with the class territory; it checks some kind of relation between two instances, right?