Some of the threaded Unicon programs that I've got that used to run fine are
now producing runtime errors related to locking/unlocking mutexes. However,
the error message is being reported at the point where the mutex is being
created, not where it's being used. Anyone have any idea what might be
off? I've attached one of the offending programs (it creates and then solves
mazes by searching for solutions in parallel). The runtime error is on line
94:
every !!region := mutex()
The error is:
->qmazer --showmice
Lock/Unlock mutex error-: The current thread does not own the mutex.
System error at line 94 in qmazer.icn
(The is under CentOS 6.5 on a 64-bit AMD system.) Unicon features are:
Unicon Version 12.1. April 13, 2013
UNIX
POSIX
DBM
ASCII
co-expressions
concurrent threads
dynamic loading
environment variables
event monitoring
external functions
keyboard functions
large integers
multiple programs
pipes
pseudo terminals
system function
messaging
graphics
3D graphics
X Windows
libz file compression
JPEG images
PNG images
SQL via ODBC
CCompiler gcc 4.4.7
Revision 3624
Arch x86_64
Binaries at /opt/unicon/bin/
I'm actually suspicious of the (recent) upgrade to CentOS 6.5 as I've got
other issues because of that (VmWare crashes the system). So if the program
works on your machine, I'd like to know that!
Thanks!
--
Steve Wampler -- swamp...@noao.edu
The gods that smiled on your birth are now laughing out loud.
global showMice
import Utils
link printf
procedure main(A)
Args(A)
if \Args().get("help","yes") then helpMesg()
showMice := Args().get("showmice","yes") # Show movements of all mice
mh := Args().get("rows") | 32 # Maze height (rows)
mw := Args().get("cols") | 48 # Maze width (columns)
mz := DisplayMaze(GenerateMaze(mh,mw)) # Build and show maze
QMouse(mz.maze,findStart(mz.maze),&null,0) # Start first quantum mouse
waitForCompletion() # block until all quantum mice have finished
# Mark the best path into the maze and display it.
if showPath(mz.maze) then DisplayMazeSolution(mz)
else write("No path found for maze!")
end
procedure helpMesg()
write(&errout,"Usage: qSolve [--showmice] [--cols=C] [--rows=R]")
write(&errout,"\twhere:")
write(&errout,"\t\t--showmice # displays all mice paths as they search")
write(&errout,"\t\t--cols=C # sets maze width to C (default 16) columns")
write(&errout,"\t\t--rows=R # sets maze height to R (default 12) rows")
stop()
end
# A "Quantum-mouse" for traversing mazes. Each mouse lives for exactly one
# cell, but can spawn additional mice to examine adjacent cells as needed.
global showMice, qMice, bestMouse, bestMouseLock, region, qMiceEmpty
record Position(r,c)
# Must match values used in maze generation!
$define FINISH 64 # exit
$define START 32 # entrance
$define PATH 128
$define SEEN 16 # bread crumbs for generator
$define NORTH 8 # sides ...
$define EAST 4
$define SOUTH 2
$define WEST 1
$define EMPTY 0 # like new
class QMouse(maze, loc, parent, len, val)
method getLoc(); return loc; end
method getParent(); return \parent; end
method getLen(); return len; end
method atEnd(); return EMPTY ~= iand(val, FINISH); end
method goNorth()
if EMPTY ~= iand(val,NORTH) then return visit(loc.r-1, loc.c)
end
method goSouth()
if EMPTY ~= iand(val,SOUTH) then return visit(loc.r+1, loc.c)
end
method goEast()
if EMPTY ~= iand(val,EAST) then return visit(loc.r, loc.c+1)
end
method goWest()
if EMPTY ~= iand(val,WEST) then return visit(loc.r, loc.c-1)
end
method visit(r,c)
# Only visit a cell if it makes sense to do so (not already seen and
# not on a path longer than the best known solution).
critical region[r,c]: if EMPTY = iand(maze[r,c],SEEN) then {
if /bestMouse | (len <= bestMouse.getLen()) then { # Keep going
mark(maze, r,c)
unlock(region[r,c])
return Position(r,c)
}
}
end
initially (m, l, p, n)
initial { # Construct critical region mutexes and completion condvar
qMice := mutex(set())
qMiceEmpty := condvar()
bestMouseLock := mutex()
region := list(*m) # Minimize critical region size
every r := 1 to *m do region[r] := list(*m[1])
every !!region := mutex()
}
maze := m
loc := l
parent := p
len := n+1
val := maze[loc.r,loc.c] | fail # Fail if outside maze
insert(qMice, self)
thread {
if atEnd() then {
critical bestMouseLock:
if /bestMouse | (len < bestMouse.getLen()) then bestMouse :=
self
}
else { # Try to spawn more mice to look for finish
QMouse(maze, goNorth(), self, len)
QMouse(maze, goSouth(), self, len)
QMouse(maze, goEast(), self, len)
QMouse(maze, goWest(), self, len)
}
delete(qMice, self)
if *qMice=0 then signal(qMiceEmpty)
}
end
procedure mark(maze, r,c)
ior(maze[r,c],SEEN)
if \showMice then markCell(r,c,"grey",5)
return Position(r,c)
end
procedure clearMaze(maze) # Clear out dregs from maze creation
every r := 1 to *maze & c := 1 to *maze[1] do # remove breadcrumbs
maze[r,c] := iand(maze[r,c],NORTH+EAST+SOUTH+WEST+START+FINISH)
end
procedure findStart(maze) # Anywhere in maze
clearMaze(maze) # Remove breadcrumbs
every r := 1 to *maze & c := 1 to *maze[1] do # Locate START cell
if EMPTY ~= iand(maze[r,c],START) then return mark(maze, r,c)
end
procedure showPath(maze)
if path := \bestMouse then { # Mark it in maze
repeat {
loc := path.getLoc()
maze[loc.r,loc.c] +:= PATH
path := \path.getParent() | break
}
return
}
end
procedure waitForCompletion()
critical qMiceEmpty: while *qMice > 0 do wait(qMiceEmpty)
end
procedure GenerateMaze(r,c) #: Depth First Maze Generation
static maze,h,w,rd
if /maze then { # BEGING - No maze yet
/h := integer(1 < r) | runerr(r,205) # valid size 2x2 or better
/w := integer(1 < c) | runerr(r,205)
every !(maze := list(h)) := list(w,EMPTY) # shinny new empty maze
start := [?h,?w,?4-1,START] # random [r,c] start & finish
finish := [?h,?w,(start[3]+2)%4,FINISH] # w/ opposite side exponent
every x := start | finish do {
case x[3] := 2 ^ x[3] of { # get side from exponent and
NORTH : x[1] := 1 # project r,c to selected edge
EAST : x[2] := w
SOUTH : x[1] := h
WEST : x[2] := 1
}
maze[x[1],x[2]] +:= x[3] + x[4] # transcribe s/f to maze
}
rd := [NORTH, EAST, SOUTH, WEST] # initial list of directions
GenerateMaze(start[1],start[2]) # recurse through maze
return 1(.maze,maze := &null) # return maze, reset for next
}
else { # ----------------------- recursed to clear insize of maze
if iand(maze[r,c],SEEN) = 0 then { # in bounds and not SEEN yet?
maze[r,c] +:= SEEN # Mark current cell as visited
every !rd :=: ?rd # randomize list of directions
every d := !rd do
case d of { # try all, succeed & clear wall
NORTH : maze[r,c] +:= ( GenerateMaze(r-1,c), NORTH)
EAST : maze[r,c] +:= ( GenerateMaze(r,c+1), EAST)
SOUTH : maze[r,c] +:= ( GenerateMaze(r+1,c), SOUTH)
WEST : maze[r,c] +:= ( GenerateMaze(r,c-1), WEST)
}
return # signal success to caller
}
}
end
$define CELL 20 # cell size in pixels
$define BORDER 30 # border size in pixels
record mazeinfo(window,maze,filename) # keepers
procedure DisplayMaze(maze) #: show it off
if CELL < 8 then runerr(205,CELL) # too small
wh := (ch := (mh := *maze ) * CELL) + 2 * BORDER # win, cell, maze height
ww := (cw := (mw := *maze[1]) * CELL) + 2 * BORDER # win, cell, maze width
wparms := [ sprintf("Maze %dx%d",*maze,*maze[1]), # window parameters
"g","bg=white","canvas=hidden",
sprintf("size=%d,%d",ww,wh),
sprintf("dx=%d",BORDER),
sprintf("dy=%d",BORDER)]
&window := open!wparms | stop("Unable to open Window")
Fg("black") # Draw full grid
every DrawLine(x := 0 to cw by CELL,0,x,ch+1) # . verticals
every DrawLine(0,y := 0 to ch by CELL,cw+1,y) # . horizontals
Fg("white") # Set to erase lines
every y := CELL*((r := 1 to mh)-1) & x := CELL*((c := 1 to mw)-1) do {
WAttrib("dx="||x+BORDER,"dy="||y+BORDER) # position @ cell r,c
if iand(maze[r,c],NORTH) > 0 then DrawLine(2,0,CELL-1,0)
if iand(maze[r,c],EAST) > 0 then DrawLine(CELL,2,CELL,CELL-1)
if iand(maze[r,c],SOUTH) > 0 then DrawLine(2,CELL,CELL-1,CELL)
if iand(maze[r,c],WEST) > 0 then DrawLine(0,2,0,CELL-1)
}
WAttrib(&window,"canvas=normal")
until Event() == &lpress
return mazeinfo(&window,maze,sprintf("maze-%dx%d-%d.gif",r,c,&now))
end
procedure DisplayMazeSolution(mz) #: draw marked PATH
&window := mz.window
maze := mz.maze
WAttrib("dx="||(dxy:=BORDER+CELL/2),"dy="||dxy)
every (r := 1 to *maze) & (c := 1 to *maze[1]) do {
if fg ~=== "blue" then fg := "blue"
if iand(maze[r,c],START) > 0 then fg := "red"
if iand(maze[r,c],FINISH) > 0 then fg := "green"
if iand(maze[r,c],PATH) > 0 then markCell(r,c,fg,3)
}
until Event() == &lpress
close(&window)
return mz
end
procedure markCell(r,c,fg,sz)
initial WAttrib("dx="||(dxy:=BORDER+CELL/2),"dy="||dxy)
Fg(fg)
FillCircle(CELL*(c-1),CELL*(r-1),CELL/sz)
end
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Unicon-group mailing list
Unicon-group@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/unicon-group