I need Mutex in Dart - locking

I have an application that use a lot of socketio request and I make bulk request. When receiving the data, I have to iterate through a list to add and remove item:
List carlist;
void receiveData(Map data) {
// Need a lock here
for (var i = 0; i < carlist.lenght;) {
if (data[carlist[i]['name']]['color'] == carlist[i]['color']) {
carlist.removeAt(i);
onDeleteCar(data); // Update the UI.
}
}
// Need a release lock here
}
Because I need to modified the list, I can't work without mutex in here.
Anyone have an idea?

Dart has no concurrent threads so a simple boolean variable can work as a mutex.
If you need another async execution to wait until the lock is released and continue then instead of just return, it becomes a bit more complicated.
bool mutex = false;
void receiveData(Map data) {
// Need a lock here
if(mutex) {
return;
} else {
mutex = true;
}
for (var i = 0; i < carlist.lenght;) {
if (data[carlist[i]['name']]['color'] == carlist[i]['color']) {
carlist.removeAt(i);
onDeleteCar(data); // Update the UI.
}
}
// Need a release lock here
mutex = false;
}
If your method is called from an event handler that produces a lot of events very fast and you want to process each execution but still only one by one you can queue the calls like:
import 'dart:async' as async;
import 'dart:collection' as coll;
import 'dart:math' as math;
void main() {
int j = 0;
int delay = 0;
for(int i = 0; i < 100; i++) {
new async.Future.delayed(
new Duration(milliseconds: delay += rnd.nextInt(150)),
() => receiveData({'${j++}': j}, j)
).catchError((e) => print('Error: $e'));
}
}
//List carlist = [];
WorkQueue workQueue = new WorkQueue(timeout: new Duration(milliseconds: 270));
math.Random rnd = new math.Random();
// had to made this async to make the timeout functionality work
// otherwise Dart would have evaluated the timeouts only after all other
// code has already been finished
async.Future receiveData(Map data, int id) {
// ensure that the code passed to add isn't entered by another async thread
// while it is already executed
// id is just for debugging purposes
return workQueue.add(id, () {
async.Completer completer = new async.Completer();
print('$id start');
// for (var i = 0; i < carlist.length;) {
// carlist.add(data);
// if (data[carlist[i]['name']]['color'] == carlist[i]['color']) {
// carlist.removeAt(i);
// onDeleteCar(data); // Update the UI.
// }
// }
// dummy task to burn time
new async.Future.delayed(new Duration(milliseconds: rnd.nextInt(100)), () {
var val = rnd.nextDouble();
// add some fun - check if code that throws is handled correctly
if(val > 0.9) {
completer.completeError('artifical error ${id}');
print('$id end with error');
} else {
completer.complete();
print('$id end');
}
});
return completer.future;
});
// Need a release lock here
}
// just holds a completer and a closure
class Task {
// complete after f was executed
async.Completer completer = new async.Completer();
// this code should only be entered by one thread at a time
Function f;
// only for debugging purposes
int id;
// ignore timeout if f has already been invoked
bool isInvoked = false;
Task(this.id, this.f, Duration timeout){
if(timeout != null) {
completer.future.timeout(timeout, onTimeout: () {
if(!completer.isCompleted && !isInvoked) {
completer.completeError('${id} timed out');
}
})
// future.timeout creates a new Future which also throws when
// the completer is completed with completeError
// not handling this error ends the app with unhandled exception
.catchError((_) {});
}
}
}
class WorkQueue {
// enque all calls
coll.Queue q = new coll.Queue();
// currently executing?
bool isExecuting = false;
// throw when the execution is delayed longer than the provide timeout
Duration timeout;
WorkQueue({this.timeout});
// enqueue a new execution
async.Future add(int id, Function f) {
print('add $id - queue length: ${q.length}');
var t = new Task(id, f, timeout);
q.add(t);
// ensure that the queue is processed
new async.Future(release);
return t.completer.future;
}
// execute next waiting thread if any
void release() {
// do nothing if closure is currently being executed or queue is empty
if(!isExecuting && !q.isEmpty) {
isExecuting = true;
Task t = q.removeFirst();
// check if t hasn't alredy timed out
if(!t.completer.isCompleted) {
// ignore timeout because we are already being invoked
t.isInvoked = true;
// invoke the closure
new async.Future(t.f)
// handle errors in closure
.catchError((e) {
t.completer.completeError(e);
})
// process next Task in queue
.then((_) {
isExecuting = false;
new async.Future(release);
if(!t.completer.isCompleted) {
t.completer.complete();
}
});
}
}
}
}
example output
add 1 - queue length: 0
1 start
1 end
add 2 - queue length: 0
2 start
add 3 - queue length: 0
2 end
3 start
3 end
add 4 - queue length: 0
4 start
4 end with error
Error: artifical error 4
add 5 - queue length: 0
5 start
5 end
add 6 - queue length: 0
6 start
add 7 - queue length: 0
6 end
7 start
7 end
add 8 - queue length: 0
8 start
add 9 - queue length: 0
add 10 - queue length: 1
8 end with error
Error: artifical error 8
9 start
9 end
10 start
add 11 - queue length: 0
10 end
11 start
add 12 - queue length: 0
add 13 - queue length: 1
11 end
12 start
12 end
13 start
13 end
add 14 - queue length: 0
14 start
14 end
add 15 - queue length: 0
15 start
add 16 - queue length: 0
15 end
16 start
16 end with error
Error: artifical error 16
add 17 - queue length: 0
17 start
17 end
add 18 - queue length: 0
18 start
18 end
add 19 - queue length: 0
19 start
add 20 - queue length: 0
19 end
20 start
add 21 - queue length: 0
20 end
21 start
add 22 - queue length: 0
21 end
22 start
22 end
add 23 - queue length: 0
23 start
23 end
add 24 - queue length: 0
24 start
add 25 - queue length: 0
add 26 - queue length: 1
add 27 - queue length: 2
24 end with error
Error: artifical error 24
25 start
add 28 - queue length: 2
add 29 - queue length: 3
25 end
26 start
add 30 - queue length: 3
26 end
27 start
27 end
28 start
add 31 - queue length: 2
28 end
29 start
29 end
30 start
30 end
31 start
add 32 - queue length: 0
31 end
32 start
32 end
add 33 - queue length: 0
33 start
33 end
add 34 - queue length: 0
34 start
34 end
add 35 - queue length: 0
35 start
35 end
add 36 - queue length: 0
36 start
add 37 - queue length: 0
36 end
37 start
add 38 - queue length: 0
37 end
38 start
add 39 - queue length: 0
38 end with error
Error: artifical error 38
39 start
39 end with error
Error: artifical error 39
add 40 - queue length: 0
40 start
add 41 - queue length: 0
40 end
41 start
41 end with error
Error: artifical error 41
add 42 - queue length: 0
42 start
add 43 - queue length: 0
add 44 - queue length: 1
add 45 - queue length: 2
42 end with error
Error: artifical error 42
43 start
add 46 - queue length: 2
43 end
44 start
add 47 - queue length: 2
add 48 - queue length: 3
add 49 - queue length: 4
44 end
45 start
add 50 - queue length: 4
45 end with error
Error: artifical error 45
46 start
46 end
47 start
add 51 - queue length: 3
47 end
48 start
Error: 49 timed out
48 end
add 52 - queue length: 2
Error: 50 timed out
add 53 - queue length: 3
add 54 - queue length: 4
add 55 - queue length: 5
Error: 51 timed out
add 56 - queue length: 6
Error: 52 timed out
add 57 - queue length: 7
Error: 53 timed out
Error: 54 timed out
add 58 - queue length: 8
Error: 55 timed out
add 59 - queue length: 9
Error: 56 timed out
Error: 57 timed out
add 60 - queue length: 10
Error: 58 timed out
add 61 - queue length: 11
Error: 59 timed out
add 62 - queue length: 12
add 63 - queue length: 13
Error: 60 timed out
add 64 - queue length: 14
Error: 61 timed out
Error: 62 timed out
add 65 - queue length: 15
Error: 63 timed out
add 66 - queue length: 16
Error: 64 timed out
add 67 - queue length: 17
Error: 65 timed out
add 68 - queue length: 18
Error: 66 timed out
add 69 - queue length: 19
add 70 - queue length: 20
add 71 - queue length: 21
Error: 67 timed out
add 72 - queue length: 22
Error: 68 timed out
add 73 - queue length: 23
Error: 69 timed out
Error: 70 timed out
Error: 71 timed out
add 74 - queue length: 24
Error: 72 timed out
Error: 73 timed out
add 75 - queue length: 25
add 76 - queue length: 26
Error: 74 timed out
add 77 - queue length: 27
add 78 - queue length: 28
Error: 75 timed out
Error: 76 timed out
add 79 - queue length: 29
add 80 - queue length: 30
Error: 77 timed out
Error: 78 timed out
add 81 - queue length: 31
add 82 - queue length: 32
add 83 - queue length: 33
Error: 79 timed out
Error: 80 timed out
add 84 - queue length: 34
Error: 81 timed out
add 85 - queue length: 35
Error: 82 timed out
Error: 83 timed out
add 86 - queue length: 36
Error: 84 timed out
add 87 - queue length: 37
Error: 85 timed out
add 88 - queue length: 38
add 89 - queue length: 39
add 90 - queue length: 40
add 91 - queue length: 41
Error: 86 timed out
add 92 - queue length: 42
Error: 87 timed out
Error: 88 timed out
add 93 - queue length: 43
Error: 89 timed out
Error: 90 timed out
Error: 91 timed out
Error: 92 timed out
add 94 - queue length: 44
add 95 - queue length: 45
add 96 - queue length: 46
add 97 - queue length: 47
Error: 93 timed out
add 98 - queue length: 48
Error: 94 timed out
Error: 95 timed out
Error: 96 timed out
add 99 - queue length: 49
Error: 97 timed out
add 100 - queue length: 50
Error: 98 timed out
Error: 99 timed out
Error: 100 timed out

Just use package Mutex!
flutter pub add mutex
List carlist;
final locker = Mutex();
void receiveData(Map data) {
// Need a lock here
locker.acquire();
try {
for (var i = 0; i < carlist.lenght;) {
if (data[carlist[i]['name']]['color'] == carlist[i]['color']) {
carlist.removeAt(i);
onDeleteCar(data); // Update the UI.
}
}
} finally {
// Need a release lock here
locker.release();
}
}

Related

CUnit return 0 on test fail

I built a simple program that executes a test in CUnit.
The main function is:
int main()
50 {
51 CU_pSuite pSuite = NULL;
52
53 /* initialize the CUnit test registry */
54 if (CUE_SUCCESS != CU_initialize_registry())
55 return CU_get_error();
56
57 /* add a suite to the registry */
58 pSuite = CU_add_suite("Suite_1", init_suite1, clean_suite1);
59 if (NULL == pSuite) {
60 CU_cleanup_registry();
61 return CU_get_error();
62 }
63
64 if ((NULL == CU_add_test(pSuite, "test of fprintf()", test_parse))) {
65 CU_cleanup_registry();
66 return CU_get_error();
67 }
68
69 /* Run all tests using the CUnit Basic interface */
70 CU_basic_set_mode(CU_BRM_VERBOSE);
71 CU_basic_run_tests();
72 CU_cleanup_registry();
73 printf("ERROR CODE: %d", CU_get_error());
74 return CU_get_error();
75 }
The test_parse function uses CU_ASSERT_FATAL. The test fails, but the output of main is the following:
CUnit - A unit testing framework for C - Version 2.1-3
http://cunit.sourceforge.net/
Suite: Suite_1
Test: test of fprintf() ...FAILED
1. /home/fedetask/Desktop/curl/tests/main.c:42 - parsed == 3
Run Summary: Type Total Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 1 1 0 1 0
asserts 5 5 4 1 n/a
Elapsed time = 0.000 seconds
ERROR CODE: 0
The main() returns 0. It returns 0 also if the test passes. What am I doing wrong?
My error: CU_get_error() returns an error code only if a framework function had an error, not the tests. To get test results, follow http://cunit.sourceforge.net/doc/running_tests.html
Ran into the same issue with this. Indeed, CU_get_error() will be 0 even if a testcase if failing. The following variables store the results as shown in the doc
unsigned int CU_get_number_of_suites_run(void)
unsigned int CU_get_number_of_suites_failed(void)
unsigned int CU_get_number_of_tests_run(void)
unsigned int CU_get_number_of_tests_failed(void)
unsigned int CU_get_number_of_asserts(void)
unsigned int CU_get_number_of_successes(void)
unsigned int CU_get_number_of_failures(void)
So a simple approach for checking if there has been any error, would be something like:
if (CU_get_number_of_tests_failed() != 0){
// Do Something
}

how to pass a class method as argument to another method of the class in perl 6

I have a script like the below. Intent is to have different filter methods to filter a list.
Here is the code.
2
3 class list_filter {
4 has #.my_list = (1..20);
5
6 method filter($l) { return True; }
7
8 # filter method
9 method filter_lt_10($l) {
10 if ($l > 10) { return False; }
11 return True;
12 }
13
14 # filter method
15 method filter_gt_10($l) {
16 if ($l < 10) { return False; }
17 return True;
18 }
19
20 # expecting a list of (1..10) to be the output here
21 method get_filtered_list_lt_10() {
22 return self.get_filtered_list(&{self.filter_lt_10});
23 }
24
25 # private
26 method get_filtered_list(&filter_method) {
27 my #newlist = ();
28 for #.my_list -> $l {
29 if (&filter_method($l)) { push(#newlist, $l); }
30 }
31 return #newlist;
32 }
33 }
34
35 my $listobj = list_filter.new();
36
37 my #outlist = $listobj.get_filtered_list_lt_10();
38 say #outlist;
Expecting [1..10] to be the output here. But getting following error.
Too few positionals passed; expected 2 arguments but got 1
in method filter_lt_10 at ./b.pl6 line 9
in method get_filtered_list_lt_10 at ./b.pl6 line 22
in block <unit> at ./b.pl6 line 37
What am I doing wrong here?
Passing a method as a parameter in Perl 6 either requires you to use MOP (Meta-Object Protocol) methods, or pass the method by name (which would then do the lookup for you at runtime).
But why use methods if you're not really doing something with the object in those methods? They might as well be subs then, which you can pass as a parameter.
Perhaps this is best by example:
class list_filter {
has #.my_list = 1..20; # don't need parentheses
sub filter($ --> True) { } # don't need code, signature is enough
# filter sub
sub filter_lt_10($l) { not $l > 10 }
# filter sub
sub filter_gt_10($l) { not $l < 10 }
# private
method !get_filtered_list(&filter_sub) {
#.my_list.grep(&filter_sub);
}
# expecting a list of (1..10) to be the output here
method get_filtered_list_lt_10() {
self!get_filtered_list(&filter_lt_10);
}
}
my $listobj = list_filter.new();
my #outlist = $listobj.get_filtered_list_lt_10();
say #outlist; # [1 2 3 4 5 6 7 8 9 10]
The first sub filter, which only returns a constant value (in this case True), can be represented much more easily in the signature with an empty body.
The filter_lt_10 and filter_gt_10 subs only need the condition negated, hence the use of the not.
The get_filtered_list method is supposed to be private, so make it a private method by prefixing !.
In the get_filtered_list_lt_10 you now need to call get_filtered_list with a ! instead of a .. And you pass the filter_lt_10 sub as a parameter by prefixing the & (otherwise it would be considered a call to the sub without any parameters, which would fail).
Change the get_filtered_listto use the built-in grep method: this takes a Callable block that takes a single parameter and which should return something True to include the value of the list it works upon. Since a sub taking a single parameter is a Callable, we can just specify the sub there directly.
Hope this made sense. I tried to stay as close as possible to the intended semantics.
Some general programming remarks: it feels to me that the naming of the subs is confusing: it feels to me that they should be called filter_le_10 and filter_ge_10, because that's really what they do it appears to me. Also, if you really don't want any ad-hoc filtering, but only filtering from a specific set of predefined filters, you would probably be better of by creating a dispatch table using constants or enums, and use that to indicate which filter you want, rather than encoding this information in the name of yet another method to make and maintain.
Hope this helps.
TL;DR You told P6 what arguments to expect when calling your filter method. Then you failed to pass the agreed argument(s) when you called it. So P6 complained on your behalf. To resolve the issue, either pass the argument(s) you told P6 to expect or stop telling P6 to expect them. :)
The message says expected 2, got 1, rather than expected 1 got 0.
This is because self is implicitly passed and added to the "expected" and "got" totals in this appended bit of message detail, bumping both up by one. (This detail is perhaps Less Than Awesome, i.e. something we should perhaps consider fixing.)
When I run your code on tio I get:
Too few positionals passed; expected 2 arguments but got 1
in method filter at .code.tio line 27
in method print_filtered_list at .code.tio line 12
in block <unit> at .code.tio line 42
The method declaration method filter($l) {...} at line 27 tells P6 to expect two arguments for each .filter method call:
The invocant. (This will be bound to self.) Let's call that argument A.
A positional argument. (This will be bound to the $l parameter). Let's call that argument B.
But in &{self.filter} in line 12, while you provide the .filter method call with an argument A, i.e. an invocant argument, you don't provide an argument B, i.e. a positional argument (after filter, e.g. &{self.filter(42)}).
Hence Too few positionals passed; expected 2 arguments but got 1.
The &{self.method} syntax was new to me, so thanks for that. Unfortunately it doesn't work if parameters are needed. You can use sub as other posters mentioned, but if you need to use methods, you can get a method by calling self.^lookup, which is the use of the meta-object protocol that Elizabeth mentioned. ('^' means you're not calling a method that's part of that class, but rather part of the "shadow" class which contains the main class's guts / implementation details.)
To get a method, use run obj.^lookup(method name), and call it by passing in the object itself (often "self") as the first parameter, then the other parameters. To bind the object to the function so it doesn't need to be explicitly added each time, use the assuming function.
class MyClass {
method log(Str $message) { say now ~ " $message"; }
method get-logger() { return self.^lookup('log').assuming(self); }
}
my &log = MyClass.get-logger();
log('hello'); # output: Instant:1515047449.201730 hello
Found it. this is what worked for me.
3 class list_filter {
4 has #.my_list = (1..20);
5
6 # will be overriding this in derived classes
7 method filter1($l) { return True; }
8 method filter2($l) { return True; }
9
10 # same print method I will be calling from all derived class objects
11 method print_filtered_list($type) {
12 my #outlist = self.get_filtered_list($type);
13 say #outlist;
14 }
15
16 # private
17 method get_filtered_list($type) {
18 my #newlist = ();
19 for #.my_list -> $l {
20 my $f = "filter$type";
21 if (self."$f"($l)) { push(#newlist, $l); }
22 }
23 return #newlist;
24 }
25 }
26
27 class list_filter_lt_10 is list_filter {
28 method filter1($l) {
29 if ($l > 10) { return False; }
30 return True;
31 }
32 method filter2($l) {
33 if ($l > 10) { return False; }
34 if ($l < 5) { return False; }
35 return True;
36 }
37 }
38
39 class list_filter_gt_10 is list_filter {
40 method filter1($l) {
41 if ($l < 10) { return False; }
42 return True;
43 }
44 method filter2($l) {
45 if ($l < 10) { return False; }
46 if ($l > 15) { return False; }
47 return True;
48 }
49 }
50
51 my $listobj1 = list_filter_lt_10.new();
52 $listobj1.print_filtered_list(1);
53 $listobj1.print_filtered_list(2);
54
55 my $listobj2 = list_filter_gt_10.new();
56 $listobj2.print_filtered_list(1);
57 $listobj2.print_filtered_list(2);
58
Output:
./b.pl6
[1 2 3 4 5 6 7 8 9 10]
[5 6 7 8 9 10]
[10 11 12 13 14 15 16 17 18 19 20]
[10 11 12 13 14 15]
piojo's answer looks like it would work (though I haven't tried it).
Another approach to turning a method into a variable is to use indirection:
class Foo {
method bar($a) {
$a * 2
}
}
sub twice(&f, $x) {
f f $x
}
my $foo = Foo.new();
say twice {$foo.bar: $^a}, 1

perl 6 passing methods as arguments [duplicate]

I have a script like the below. Intent is to have different filter methods to filter a list.
Here is the code.
2
3 class list_filter {
4 has #.my_list = (1..20);
5
6 method filter($l) { return True; }
7
8 # filter method
9 method filter_lt_10($l) {
10 if ($l > 10) { return False; }
11 return True;
12 }
13
14 # filter method
15 method filter_gt_10($l) {
16 if ($l < 10) { return False; }
17 return True;
18 }
19
20 # expecting a list of (1..10) to be the output here
21 method get_filtered_list_lt_10() {
22 return self.get_filtered_list(&{self.filter_lt_10});
23 }
24
25 # private
26 method get_filtered_list(&filter_method) {
27 my #newlist = ();
28 for #.my_list -> $l {
29 if (&filter_method($l)) { push(#newlist, $l); }
30 }
31 return #newlist;
32 }
33 }
34
35 my $listobj = list_filter.new();
36
37 my #outlist = $listobj.get_filtered_list_lt_10();
38 say #outlist;
Expecting [1..10] to be the output here. But getting following error.
Too few positionals passed; expected 2 arguments but got 1
in method filter_lt_10 at ./b.pl6 line 9
in method get_filtered_list_lt_10 at ./b.pl6 line 22
in block <unit> at ./b.pl6 line 37
What am I doing wrong here?
Passing a method as a parameter in Perl 6 either requires you to use MOP (Meta-Object Protocol) methods, or pass the method by name (which would then do the lookup for you at runtime).
But why use methods if you're not really doing something with the object in those methods? They might as well be subs then, which you can pass as a parameter.
Perhaps this is best by example:
class list_filter {
has #.my_list = 1..20; # don't need parentheses
sub filter($ --> True) { } # don't need code, signature is enough
# filter sub
sub filter_lt_10($l) { not $l > 10 }
# filter sub
sub filter_gt_10($l) { not $l < 10 }
# private
method !get_filtered_list(&filter_sub) {
#.my_list.grep(&filter_sub);
}
# expecting a list of (1..10) to be the output here
method get_filtered_list_lt_10() {
self!get_filtered_list(&filter_lt_10);
}
}
my $listobj = list_filter.new();
my #outlist = $listobj.get_filtered_list_lt_10();
say #outlist; # [1 2 3 4 5 6 7 8 9 10]
The first sub filter, which only returns a constant value (in this case True), can be represented much more easily in the signature with an empty body.
The filter_lt_10 and filter_gt_10 subs only need the condition negated, hence the use of the not.
The get_filtered_list method is supposed to be private, so make it a private method by prefixing !.
In the get_filtered_list_lt_10 you now need to call get_filtered_list with a ! instead of a .. And you pass the filter_lt_10 sub as a parameter by prefixing the & (otherwise it would be considered a call to the sub without any parameters, which would fail).
Change the get_filtered_listto use the built-in grep method: this takes a Callable block that takes a single parameter and which should return something True to include the value of the list it works upon. Since a sub taking a single parameter is a Callable, we can just specify the sub there directly.
Hope this made sense. I tried to stay as close as possible to the intended semantics.
Some general programming remarks: it feels to me that the naming of the subs is confusing: it feels to me that they should be called filter_le_10 and filter_ge_10, because that's really what they do it appears to me. Also, if you really don't want any ad-hoc filtering, but only filtering from a specific set of predefined filters, you would probably be better of by creating a dispatch table using constants or enums, and use that to indicate which filter you want, rather than encoding this information in the name of yet another method to make and maintain.
Hope this helps.
TL;DR You told P6 what arguments to expect when calling your filter method. Then you failed to pass the agreed argument(s) when you called it. So P6 complained on your behalf. To resolve the issue, either pass the argument(s) you told P6 to expect or stop telling P6 to expect them. :)
The message says expected 2, got 1, rather than expected 1 got 0.
This is because self is implicitly passed and added to the "expected" and "got" totals in this appended bit of message detail, bumping both up by one. (This detail is perhaps Less Than Awesome, i.e. something we should perhaps consider fixing.)
When I run your code on tio I get:
Too few positionals passed; expected 2 arguments but got 1
in method filter at .code.tio line 27
in method print_filtered_list at .code.tio line 12
in block <unit> at .code.tio line 42
The method declaration method filter($l) {...} at line 27 tells P6 to expect two arguments for each .filter method call:
The invocant. (This will be bound to self.) Let's call that argument A.
A positional argument. (This will be bound to the $l parameter). Let's call that argument B.
But in &{self.filter} in line 12, while you provide the .filter method call with an argument A, i.e. an invocant argument, you don't provide an argument B, i.e. a positional argument (after filter, e.g. &{self.filter(42)}).
Hence Too few positionals passed; expected 2 arguments but got 1.
The &{self.method} syntax was new to me, so thanks for that. Unfortunately it doesn't work if parameters are needed. You can use sub as other posters mentioned, but if you need to use methods, you can get a method by calling self.^lookup, which is the use of the meta-object protocol that Elizabeth mentioned. ('^' means you're not calling a method that's part of that class, but rather part of the "shadow" class which contains the main class's guts / implementation details.)
To get a method, use run obj.^lookup(method name), and call it by passing in the object itself (often "self") as the first parameter, then the other parameters. To bind the object to the function so it doesn't need to be explicitly added each time, use the assuming function.
class MyClass {
method log(Str $message) { say now ~ " $message"; }
method get-logger() { return self.^lookup('log').assuming(self); }
}
my &log = MyClass.get-logger();
log('hello'); # output: Instant:1515047449.201730 hello
Found it. this is what worked for me.
3 class list_filter {
4 has #.my_list = (1..20);
5
6 # will be overriding this in derived classes
7 method filter1($l) { return True; }
8 method filter2($l) { return True; }
9
10 # same print method I will be calling from all derived class objects
11 method print_filtered_list($type) {
12 my #outlist = self.get_filtered_list($type);
13 say #outlist;
14 }
15
16 # private
17 method get_filtered_list($type) {
18 my #newlist = ();
19 for #.my_list -> $l {
20 my $f = "filter$type";
21 if (self."$f"($l)) { push(#newlist, $l); }
22 }
23 return #newlist;
24 }
25 }
26
27 class list_filter_lt_10 is list_filter {
28 method filter1($l) {
29 if ($l > 10) { return False; }
30 return True;
31 }
32 method filter2($l) {
33 if ($l > 10) { return False; }
34 if ($l < 5) { return False; }
35 return True;
36 }
37 }
38
39 class list_filter_gt_10 is list_filter {
40 method filter1($l) {
41 if ($l < 10) { return False; }
42 return True;
43 }
44 method filter2($l) {
45 if ($l < 10) { return False; }
46 if ($l > 15) { return False; }
47 return True;
48 }
49 }
50
51 my $listobj1 = list_filter_lt_10.new();
52 $listobj1.print_filtered_list(1);
53 $listobj1.print_filtered_list(2);
54
55 my $listobj2 = list_filter_gt_10.new();
56 $listobj2.print_filtered_list(1);
57 $listobj2.print_filtered_list(2);
58
Output:
./b.pl6
[1 2 3 4 5 6 7 8 9 10]
[5 6 7 8 9 10]
[10 11 12 13 14 15 16 17 18 19 20]
[10 11 12 13 14 15]
piojo's answer looks like it would work (though I haven't tried it).
Another approach to turning a method into a variable is to use indirection:
class Foo {
method bar($a) {
$a * 2
}
}
sub twice(&f, $x) {
f f $x
}
my $foo = Foo.new();
say twice {$foo.bar: $^a}, 1

3des authentication no response

I send the command 1A:00 to the Mifare Ultralight C tag by using APDU command
Here is the log:
inList passive target
write: 4A 1 0
read: 4B 1 1 0 44 0 7 4 C2 35 CA 2C 2C 80
write: 40 1 1A 0
I don't know why when I send 1A 00, it did not respond with RndA?
My code is this:
bool success = nfc.inListPassiveTarget();
if (success) {
uint8_t auth_apdu[] = {
0x1A,
0x00
};
uint8_t response[255];
uint8_t responseLength = 255;
success = nfc.inDataExchange(auth_apdu, sizeof(auth_apdu), response, &responseLength);
if (success) {
Serial.println("\n Successfully sent 1st auth_apdu \n");
Serial.println("\n The response is: \n");
nfc.PrintHexChar(response, responseLength);
}
When I try to read pages with command 0x30, , it works OK, but not the authentication command: 1A:00
I don't know what I am doing wrong here
The answer is that I should use inCommunicateThru ( 0x42 ) instead of inDataExchange ( 0x40 ).
Thus the correct command should be : 0x42 1A 0

Threads and clocked threads in SystemC

While reading about the threads in SystemC, it is said that while(true) loop must be used inside the functions. Why is it so?
Can you please see the example code given below and explain why the while loop is used for threads and wait() command is used along with the loop:
1 //-----------------------------------------------------
2 // This is my second Systemc Example
3 // Design Name : first_counter
4 // File Name : first_counter.cpp
5 // Function : This is a 4 bit up-counter with
6 // Synchronous active high reset and
7 // with active high enable signal
8 //-----------------------------------------------------
9 #include "systemc.h"
10
11 SC_MODULE (first_counter) {
12 sc_in_clk clock ; // Clock input of the design
13 sc_in<bool> reset ; // active high, synchronous Reset input
14 sc_in<bool> enable; // Active high enable signal for counter
15 sc_out<sc_uint<4> > counter_out; // 4 bit vector output of the counter
16
17 //------------Local Variables Here---------------------
18 sc_uint<4> count;
19
20 //------------Code Starts Here-------------------------
21 // Below function implements actual counter logic
22 void incr_count () {
23 // For threads, we need to have while true loop
24 while (true) {
25 // Wait for the event in sensitivity list to occure
26 // In this example - positive edge of clock
27 wait();
28 if (reset.read() == 1) {
29 count = 0;
30 counter_out.write(count);
31 // If enable is active, then we increment the counter
32 } else if (enable.read() == 1) {
33 count = count + 1;
34 counter_out.write(count);
35 }
36 }
37 } // End of function incr_count
38
39 // Below functions prints value of count when ever it changes
40 void print_count () {
41 while (true) {
42 wait();
43 cout<<"#" << sc_time_stamp() <<
44 " :: Counter Value "<<counter_out.read()<<endl;
45 }
46 }
47
48 // Constructor for the counter
49 // Since this counter is a positive edge trigged one,
50 // We trigger the below block with respect to positive
51 // edge of the clock
52 SC_CTOR(first_counter) {
53 // Edge sensitive to clock
54 SC_THREAD(incr_count);
55 sensitive << clock.pos();
56 // Level Sensitive to change in counter output
57 SC_THREAD(print_count);
58 sensitive << counter_out;
59 } // End of Constructor
60
61 }; // End of Module counter
SC_THREAD or SC_CTHREAD should have infinite loop to keep the thread not being terminated. If you don't put for(;;) or while(true) in the function body, when the execution reaches the end of function scope, the thread is terminated. In such case, your thread will never be waken up by the sensitive list for processing something. Or you can it transform to equivalent SC_METHOD, then you can have no infinite loop.
SystemC is using non-preemptive thread, so if you don't use wait() to wait for something listed in static or dynamic sensitive list to happen, it causes a infinite execution in your thread. And CPU execution of your process won't get out of the function scope. Such that SystemC kernel won't able to continue to process other methods/threads and events to continue the simulation. And in the event-based simulation, the thread should only be run when the specified condition (events in the sensitive list) occur. So the wait() function can wait until the next event occurs and hand over the CPU execution to other threads/methods and SystemC kernel. Next time the event occurs, for example the positive edge of clock, wait() statement will return and continue your process.
In your example, your program is waiting for clock's positive edge trigger to increase the counter's value by 1. So, if you don't put wait() in your code, then incr_count will always increase the counter's value infinitely no matter the clock's status, and it won't stop. By using wait(), your thread will be blocked and wait for next clock positive edge trigger.
while(true) --> makes thread infinite, so that it can keep executing when it gets context
wait() --> forces the thread to lose context and allows something else to be executed