I'm trying to use an agent callback concurrently. Unfortunately, no matter what I do it always seems to run sequentially instead of parallel. (without the agent it doesn't)
main class(APPLICATION):
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Run application.
local
a1 : separate PROCEDURE
a2 : separate PROCEDURE
do
create my_counter.make (1, 100_000_000)
create my_counter2.make (2, 100_000_000)
launch_counter(my_counter)
launch_counter(my_counter2)
end
feature -- Launch
launch_counter(c: separate COUNTER)
do
c.run (5, agent print_hello)
end
print_hello
do
print("Hello!%N")
end
feature -- Access
my_counter : separate COUNTER
my_counter2 : separate COUNTER
end
counter class:
class
COUNTER
inherit
EXECUTION_ENVIRONMENT
create
make
feature -- Initilzation
make (i: INTEGER; delay: INTEGER)
do
id := i
delay_time := delay
end
feature -- Stuff
run (times: INTEGER; p: separate PROCEDURE)
local
c : INTEGER
do
from
c := times
until
c = 0
loop
print("COUNTER: " + id.out)
p.call
sleep(delay_time)
c := c - 1
end
end
feature {NONE} -- Access
delay_time : INTEGER
id: INTEGER
end
expected output:
COUNTER: 1Hello!
COUNTER: 2Hello!
COUNTER: 1Hello!
etc.
actual output:
COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 1Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!
COUNTER: 2Hello!
What would I have to change to make this run as expected?
The agent object keeps a reference to the target, in your example to the root object of type APPLICAITON, therefore all calls to print_hello get synchronized. To avoid that, the objects on which the agent is called should be recorded in a COUNTER object and used from there.
This can be achieved by adding an attribute action to the class COUNTER and updating its creation procedure
make (i: INTEGER; delay: INTEGER; a: separate PROCEDURE)
do
id := i
delay_time := delay
action := a
end
...
action: separate PROCEDURE
Then instead of p.call in COUNTER.run the following code will be used (the feature run has no argument p anymore):
separate action as p do
p.call
end
Now p is not locked on entry to the feature run and therefore callbacks can be executed alternately by different processors.
Related
I am developing unit tests in Lua and a major part of these tests is changing package.loaded. This goes from
a = require "parser"
a.b = nil
to
package.loaded["checker"] = function() return true end
And the situation where I modify an entry of package.loaded that was loaded before the test started.
I would like to reset package.loaded after every test. But I have a hard time. I tried wrapping require, which solves some problems, but does not solve the problem of the second and the third example. How can I properly make a savepoint of package.loaded right before the tests and reload that savepoint just before I start a new test? Or just roll back package.loaded to the one just after the interpeter started?
This is actually the answer of #EgorSkriptunoff, but he placed it as a comment.
For me, it was good enough to just make a shallow-copy of bot the package.loaded and the _G. Shallow-copy can be found here: http://lua-users.org/wiki/CopyTable:
function shallowcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
The actual testing then looks like this:
local packageLoadedCopy = shallowcopy(package.loaded)
local gCopy = shallowcopy(_G)
for _, test in ipairs(tests) do
-- Do the actual test
-- Clean up the environment
local markDeletion = {}
local markModify = {}
for name in pairs(package.loaded) do
if not packageLoadedCopy[name] then
table.insert(markDeletion, name)
elseif packageLoadedCopy[name] ~= package.loaded[name] then
table.insert(markModify, name)
end
end
for _, name in pairs(markDeletion) do
package.loaded[name] = nil
end
for _, name in pairs(markModify) do
package.loaded[name] = packageLoadedCopy[name]
end
markDeletion, markModify = {}, {}
for name in pairs(_G) do
if not gCopy[name] then
table.insert(markDeletion, name)
elseif _G[name] ~= gCopy[name] then
table.insert(markModify, name)
end
end
for _, name in pairs(markDeletion) do
_G[name] = nil
end
for _, name in pairs(markModify) do
_G[name] = gCopy[name]
end
end
Do note that simply
package.loaded = packageLoadedCopy
_G = gCopy
Does not work, and I am not sure why.
I have programmed a langton's ant and it work nice.
Now I want to run 2 ant simultaneously.I have a run function how make the computation and ant's movement and it's a infinite run loop.
How can I run 2 of this loop at once ?
I have try to look on Thread but i'm not sure that it's the best for my case.
This is some example of my code :
Run function :
let run(f,tab2 : t_fourmi*int array array) =
f.xx := !(f.x);
f.yy := !(f.y);
let d = ref 0
and z = ref 0
and o = ref 0
(* 1 = de bas, 2 = de droite, 3 = de haut, 4 = de gauche *)
in
if tab2.(!(f.x)/5).(!(f.y)/5) = 0
then move_right(f,1,tab2);
if !(f.xx) + 5 = !(f.x)
then d := 4
else if !(f.xx) - 5 = !(f.x)
then d := 2
else if !(f.yy) + 5 = !(f.y)
then d := 1
else if !(f.yy) - 5 = !(f.y)
then d := 3;
while true
do
(*
print_string "step : ";
print_int !o;
print_newline(); *)
o := !o + 1;
f.xx := !(f.x);
f.yy := !(f.y);
z := tab2.(!(f.x)/5).(!(f.y)/5);
if !z = 0
then move_right(f,!d,tab2)
else if !z = 1
then move_left(f,!d,tab2)
else if !z = 2
then move_right(f,!d,tab2)
else if !z = 3
then move_right(f,!d,tab2);
if !(f.xx) + 5 = !(f.x)
then d := 4
else if !(f.xx) - 5 = !(f.x)
then d := 2
else if !(f.yy) + 5 = !(f.y)
then d := 1
else if !(f.yy) - 5 = !(f.y)
then d := 3;
done;
;;
Example of move function :
let move_left(f,d,tab2 : t_fourmi*int*int array array) = (* d = direction d'ou la fourmi viens *)
(* 1 = de bas, 2 = de droite, 3 = de haut, 4 = de gauche *)
f.xx := !(f.x);
f.yy := !(f.y);
if d = 1
then f.x := !(f.x) - 5
else if d = 2
then f.y := !(f.y) - 5
else if d = 3
then f.x := !(f.x) + 5
else if d = 4
then f.y := !(f.y) + 5;
if !(f.x) >= 995
then f.x := 5
else if !(f.x) <= 5
then f.x := 995;
if !(f.y) >= 995
then f.y := 5
else if !(f.y) <= 5
then f.y := 995;
create_fourmi(f);
let n = tab2.(!(f.xx)/5).(!(f.yy)/5) in
drawinv(!(f.xx),!(f.yy),n,tab2);
;;
If you need more function, ask me.
Thanks
If I understand your code correctly (it's unfortunately not very readable), it could be outlined as essentially:
let init params =
...
let step state =
...
let move thing state =
...
let run params thing =
let state = ref (init params) in
while true do
let state := step state in
move thing state
done
where I've factored init, step and move out into separate function, which should be pretty straight-forward to do. And by doing so we can replace the run function with a run_two function that can run two instances virtually at the same time, though not entirely in parallel. They won't run independently, but in synchrony, iteration by iteration:
let run_two params1 thing1 params2 thing2 =
let state1 = ref (init params1) in
let state2 = ref (init params2) in
while true do
state1 := step !state1;
state2 := step !state2;
move !state1;
move !state2;
done
This doesn't use any threads or other complicated concurrency primitives. It's just ordinary code organized in a way that allows composition. It also allows the init and step function to be completely pure, which makes them easy to test and reason about. You could even make the move functions pure, if you factor out the drawing.
You can use threads, though it will open a pandora box for you. You have to synchronize your ants, since probably you want them to move in the same world.
Running two ants in different threads
First of all, you have to represent each ant process as an ever-looping function of type ant -> unit, where ant is the type that describes ant's initial position, moving parameters, and so on (if you don't need this, then just use unit instead. So suppose we have a function val run : ant -> unit. Next, we need to make sure, that we do not write to the same board at the same time from different threads, so we need to create a mutex, using Mutex.create, we then need to update our run function and do Mutex.lock before updating our board, and Mutex.unlock after. Finally, we should ensure that no ants will starve for the board, and that once an ant finishes it moves it yields the control to another ant, we could do this using Thread.delay if we want our simulation to be smooth (i.e., if we want to artificially slow it down to human-observable speed). Otherwise, we can just use Thread.yield. (Note, normally threads are preempted (forced to yield) by the system, but this is done in special yield points. When we do system programming there are usually lots of yield points, but this is not our case, so we have to implement this cooperation explicitly). Finally, our updated run function is ready to be run in a thread, with Thread.createrun ant. This function will return to our main thread of execution, so we can run a second ant and so on. Once all ants start running we have to call Thread.join to wait for all of them. Ideally, this function should never return.
I hope, that the above outline provided enough information for you, and you can enjoy the coding yourself. Feel free to ask questions int the comment section if anything is unclear. Probably, the first question would be how to compile it. It is (there are simpler ways, of course, but the most basic is, assuming that your program is in the ant.ml):
ocamlopt -thread unix.cmxa threads.cmxa ant.ml -o ant
Running two ants in co-routines
While the above will work, it seems too complicated and too system-dependent for such a simple simulation task. Why do we need to use system threads for that? We actually don't, we can be clever and implement co-routines using plain OCaml and continuation-passing style. Don't worry, a continuation is just a function. And a continuation-passing style is when we are calling another function at the end of the other function. In this approach, we will not have the run function that runs infinitely, instead, we will have a step function that advances an ant one step forward at each invocation. For the demonstration purposes, let's simplify our step function so that each ant just greets another, e.g.,
let step other yield =
print_endline ("Hello, " ^ other);
yield ()
That simple. We do our step, and then call the yield function (that is that fancy continuation) to yield the control to the next ant. Now let's tie it together in a simple infinite loop, e.g.,
let rec loop () =
step "Joe" ## fun () ->
step "Doe" ## fun () ->
loop ()
let () = loop ()
Let's make it clear. step "Joe" ## fun () -> <continue> is the same as step "Joe" (fun () -> <continue>), and this (fun () -> <continue>) is the yield function that is passed to the step function that greets Joe. Once Joe is greeted the step function calls us again and we evaluate the <continue>, which is, in our case step "Doe" ## fun () -> loop (), i.e., we pass the fun () -> loop () function as the yield argument to the step function that greets Doe, so once Doe is greeted, we call loop () ... and now we're at the begining of the loop.
In our case, we were passing a value of type unit in our continuations, but we can also pass an arbitrary value, e.g., a value that will represent the state of our simulation (the board with ant positions). This will enable a functional implementation of your simulation if you want to try it.
I have some code which I think should look like:
on Locales[0] {
var slice: domain(1) = {0..#widthOfLocaleMatrix};
on Locales[1] {
slice(0) = A.localSubdomain();
}
var localSlice: [slice(0)] int = A[slice(0)];
}
Basically, I am trying to fetch multiple slices of data from the other numLocales - 1 locales. Can I create an object to store the localSubdomain's from all other locales? I think I can work around this, but I was curious.
To store multiple domains, you'll want to create an array of domains (or some other collection of domains). Specifically, the main problem with the code above is that it is seemingly trying to index into a domain ( slice(0) ) -- keep in mind that domains are merely index sets, not arrays/maps from indices to values.
The following sample program creates a distributed array ( A ) whose distribution we want to interrogate and an array of domains ( slicePerLocale ) that we'll use to keep track of who owns what. It populates slicePerLocale via the localSubdomain() query to determine the subdomain that each locale owns and stores that in the respective element of slicePerLocale. Finally, it prints out what it has learned:
use BlockDist;
config const n = 10;
var D = {1..n, 1..n} dmapped Block({1..n, 1..n});
var A: [D] real;
var slicePerLocale: [LocaleSpace] domain(2);
coforall loc in Locales do
on loc do
slicePerLocale[loc.id] = A.localSubdomain();
for (loc, slice) in zip(LocaleSpace, slicePerLocale) do
writeln("locale ", loc, " owns: ", slice);
Running this on four locales with the default problem size of 10 results in:
locale 0 owns: {1..5, 1..5}
locale 1 owns: {1..5, 6..10}
locale 2 owns: {6..10, 1..5}
locale 3 owns: {6..10, 6..10}
In Ada 2012, I want to have a linked list inside a declared array, rather than allocated. I want to have the linking pointers set by a procedure.
I have simplified my program to the following that demonstrates the principle I want to use but I cannot get this to compile in Gnat 4.9.2 (Debian Jessie) running on Raspi...
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Ch'First .. Ch'Last - 1 loop
Ch (I).Next := Ch (I + 1)'Access; -- ERROR HERE
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
I get this compiler error:
"non-local pointer cannot point to local object" at the line indicated above.
I know I'm trying to do something a bit odd but I plan on having a few other functions that perform the linking in different ways (backwards, or randomly etc) based on which procedure I pass this array of cells to.
How do I fix this code so that it compiles? Can't quite get my head around this one (I'm still a novice but enjoying the learning process).
As you are not actually allocating & freeing memory, in dont see the need for pointers. I would achieve the same functionality by doing something like this:
procedure Arr is
type Cell_Index is new Integer range 0 .. 100;
subtype Valid_Cell_Index is Cell_Index range 1 .. Cell_Index'Last;
type Cell is
record
Number : Integer := 0;
Next : Cell_Index := 0;
end record;
type Chain is array (Valid_Cell_Index) of Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Valid_Cell_Index'First .. Valid_Cell_Index'Last - 1 loop
Ch (I).Next := I+1;
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
This way you are still using Next as an index into the same array, and can pre-load your array with whatever linking pattern you want.
Instead of using ’Access, use ’Unrestricted_Access. This is one of GNAT’s “implementation-defined” attributes:
The Unrestricted Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute.
I figured it out in the end. The following code is a modified version of the one in the OP. It does what I originally wanted without doing anything unpleasant...
with Ada.Integer_Text_IO, Ada.Text_IO;
use Ada.Integer_Text_IO, Ada.Text_IO;
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
type Chain_Ptr is access all Chain;
procedure Make_Links (CP : in out Chain_Ptr);
procedure Make_Links (CP : in out Chain_Ptr) is
begin
for I in CP'First .. CP'Last - 1 loop
CP.all (I).Next := CP.all (I + 1)'Access;
end loop;
end Make_Links;
My_Chain : aliased Chain;
My_CP : Chain_Ptr := null;
My_C : Cell_Ptr := null;
begin
My_CP := My_Chain'Access;
Make_Links (My_CP);
-- verify that the code works by writing values into the array
for I in My_Chain'Range loop
My_Chain (I).Number := 1000 * I;
end loop;
-- and read them back out using the pointer links
My_C := My_Chain (My_Chain'First)'Access;
while My_C /= null loop
Put (My_C.Number);
Put_Line ("");
My_C := My_C.Next;
end loop;
end Arr;
Instead of passing the array directly, I passed a pointer to the array instead, which Gnat seems happy with. I think what I was trying to do before was being scuppered by the "pass by copy" rules for procedure parameters.
I've wrote the following spec
"An IP4 address" should "belong to just one class" in {
val addrs = for {
a <- Gen.choose(0, 255)
b <- Gen.choose(0, 255)
c <- Gen.choose(0, 255)
d <- Gen.choose(0, 255)
} yield s"$a.$b.$c.$d"
forAll (addrs) { ip4s =>
var c: Int = 0
if (IP4_ClassA.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassB.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassC.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassD.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassE.unapply(ip4s).isDefined) c = c + 1
c should be (1)
}
}
That is very clear in its scope.
The test passes successfully but when I force it to fail (for example by commenting out one of the if statements) then ScalaCheck correctly reports the error but the message doesn't mention correctly the actual value used to evaluate the proposition. More specifically I get:
[info] An IP4 address
[info] - should belong to just one class *** FAILED ***
[info] TestFailedException was thrown during property evaluation.
[info] Message: 0 was not equal to 1
[info] Location: (NetSpec.scala:105)
[info] Occurred when passed generated values (
[info] arg0 = "" // 4 shrinks
[info] )
where you can see arg0 = "" // 4 shrinks doesn't show the value.
I've tried to add even a simple println statement to review the cases but the output appears to be trimmed. I get something like this
192.168.0.1
189.168.
189.
1
SOLUTION
import org.scalacheck.Prop.forAllNoShrink
import org.scalatest.prop.Checkers.check
"An IP4 address" should "belong to just one class" in {
val addrs = for {
a <- Gen.choose(0, 255)
b <- Gen.choose(0, 255)
c <- Gen.choose(0, 255)
d <- Gen.choose(0, 255)
} yield s"$a.$b.$c.$d"
check {
forAllNoShrink(addrs) { ip4s =>
var c: Int = 0
if (IP4.ClassA.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassB.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassC.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassD.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassE.unapply(ip4s).isDefined) c = c + 1
c == (1)
}
}
}
This is caused by ScalaCheck's test case simplification feature. ScalaCheck just sees that your generator produces a string value. Whenever it finds a value that makes your property false, it tries to simplify that value. In your case, it simplifies it four times until it ends up with an empty string, that still makes your property false.
So this is expected, although confusing, behavior. But you can improve the situation in three different ways.
You can select another data structure to represent your IP addresses. This will make ScalaCheck able to simplify your test cases in a more intelligent way. For example, use the following generator:
val addrs = Gen.listOfN(4, Gen.choose(0,255))
Now ScalaCheck knows that your generator only produces lists of length 4, and that it only contains numbers between 0 and 255. The test case simplification process will take this into account and not create any values that couldn't have been produced by the generator from start. You can do the conversion to string inside your property instead.
A second method is to add a filter directly to your generator, which tells ScalaCheck how an IP address string should look like. This filter is used during test case simplification. Define a function that checks for valid strings and attach it to your existing generator this way:
def validIP(ip: String): Boolean = ...
val validAddrs = addrs.suchThat(validIP)
forAll(validAddrs) { ... }
The third method is to simply disable the test case simplification feature altogether by using forAllNoShrink instead of forAll:
Prop.forAllNoShrink(addrs) { ... }
I should also mention that the two first methods require ScalaCheck version >= 1.11.0 to function properly.
UPDATE:
The listOfN list length is actually not respected by the shrinker any more, due to https://github.com/rickynils/scalacheck/issues/89. Hopefully this can be fixed in a future version of ScalaCheck.