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

Reply via email to