Skip to content

Modules

Harmony modules provide convenient access to various data structures, algorithms, and synchronization paradigms. They are all implemented in the Harmony language itself (so you can look at their code) although some methods have also been implemented directly into the underlying model checker for more efficient model checking.

Currently there are the following modules:

Module Description
action support for action-based specifications
alloc dynamic memory allocation
bag multi-sets
fork fork/join interface to threads
hoare Hoare module interface
list common operations on lists
set common operations on sets
synch synchronization

The action module

The action module supports action-based specification. Such a specification consists of a explicit global state and rules for how to make state transitions. Chapter 28 provides an example. The module has only one method:

Method Description
explore(x) explore the state space

Here x is a set of lambdas, each of which can return a set of closures, each representing a possible action (state change). The union of the results of the lambdas should generate all possible actions. A closure represents a method and its arguments that updates the state accordingly.

The alloc module

The alloc module supports thread-safe (but not interrupt-safe) dynamic allocation of shared memory locations. There are just two methods:

Method Description
malloc(v) return a pointer to a memory location initialized to v
free(p) free an allocated memory location p

The usage is similar to malloc and free in C. malloc() is specified to return None when running out of memory, although this is an impossible outcome in the current implementation of the module.

The bag module

The bag module has various useful methods that operate on bags or multisets:

Method Description
empty() returns an empty bag
fromSet(s) create a bag from set s
fromList(t) convert list t into a bag
multiplicity(b, e) count how many times e occurs in bag b
bchoose(b) like choose(s), but applied to a bag
add(b, e) add one copy of e to bag b
remove(b, e) remove one copy of e from bag b
combinations(b, k) return set of all subbags of size k

The fork module

The fork module implements the fork/join interface to threads.

Method Description
fork(closure) spawn closure and return a thread handle
join(handle) wait for the thread to finish and return its result

For example, the following code doubles each element of data in parallel and then sums the result when done.

from fork import *
from list import *

data = { 1, 2, 4 }

def main():
    let double = lambda x: 2*x end
    let map = { fork(?double(k)) for k in data }:
        print sum(join(t) for t in map)

spawn main()

The hoare module

The hoare module implements support for Hoare-style monitors and condition variables.

Method Description
Monitor() return a monitor mutex
enter(m) enter a monitor. m points to a monitor mutex
exit(m) exit a monitor
Condition() return a condition variable
wait(c, m) wait on condition variable pointed to by c in monitor pointed to by m
signal(c, m) signal a condition variable

The list module

The list module has various useful methods that operate on lists or tuples:

Method Description
subseq(t, b, f) return a slice of list t starting at index b and ending just before \(f\)
append(t, e) append e to list t
head(t) return the first element of list t
tail(t) return all but the first element of list t
index(t, e) return the index of element e in list t
startswith(t, s) returns whether s is a prefix of t
reversed(t) reverse a list
sorted(t) sorted set or list
set(t) convert a list into a set
list(t) convert set into a list
values(t) convert values of a dict into a list sorted by key
items(t) convert dict into (key, value) list sorted by key
enumerate(t) like Python enumerate
sum(t) returns the sum of all elements in t
qsort(t) sort list t using quicksort
foldl(t, f, z) left fold with f a binary method and z the initial value
foldr(t, f, z) right fold with f a binary method and z the initial value
reduce(f, t, z) same as foldl(t, f, z)

The set module

The set module implements the following methods:

Method Description
issubseteq(s, t) returns whether s is a subset of t
issubsetstrict(s, t) returns whether s is a strict subset of t
issubset(s, t) same as issubseteq(s, t)
issuperseteq(s, t) returns whether s is a superset of t
issupersetstrict(s, t) returns whether s is a strict superset of t
issuperset(s, t) same as issuperseteq(s, t)
add(s, e) returns \(s \cup \{ e \}\)
remove(s, e) returns \(s \backslash \{ e \}\)
subsets(s) returns the set of subsets of s
union(s) returns the union of the elements of s
cartesian(d) d is a list of sets. Returns the Cartesian product.
combinations(s, k) returns set of all subsets of size k
reduce(f, t, z}>) same as Python's functools reduce()

For Python programmers: note that s \(<=\) t does not check if s is a subset of t when s and t are sets, as "\(<=\)" implements a total order on all Harmony values including sets (and the subset relation is not a total order).

The synch module

The synch module provides the following methods:

Method Description
atomic_load(p) atomically evaluate !p
atomic_store(p, v) atomically assign !p = v
tas(lk) test-and-set on !lk
cas(ptr, old, new) compare-and-swap on !ptr
BinSema(v) return a binary semaphore initialized to v
Lock() return a binary semaphore initialized to False
acquire(bs) acquire binary semaphore !bs
release(bs) release binary semaphore !bs
Condition() return a condition variable
wait(c, lk) wait on condition variable !c and lock lk
notify(c) notify a thread waiting on condition variable !c
notifyAll(c) notify all threads waiting on condition variable !c
Semaphore(cnt) return a counting semaphore initialized to cnt
P(sema) procure !sema
V(sema) vacate !sema
Queue() return a synchronized queue object
get(q) return next element of q, blocking if empty
put(q, item) add item to a