For every value V that has been put onto the queue p times and returned by take q times, there must be p-q copies of this value on the queue. This only holds if p >= q.
No value should ever be returned by take if it was not first passed to put by some thread.
If a thread puts value A and then puts value B, and no other thread puts these specific values, B must not be taken from the queue before taking A.
The dictionary is implemented as an array of linked lists, where each node of each linked list represents a key-value pair. The array-index for a given key is generated by computing a hash function on that key. With an array that is much larger than the number of values stored, we can expect each bucket of the array to contain one or less elements, on average.
Each array index has its own lock. This means that all accesses to separate array buckets can occur concurrently. If multiple elements reside on the same linked-list array index, these elements cannot be accessed concurrently by any of the dictionary functions. Accesses to elements which are stored in the same array index must be ordered in serial. One Dictionary operation on an element in index x must fully complete before executing another operation in index x. As explained above, this means that in a sufficiently large array very few elements will have to be accessed in serial. Most elements will be accessible in parallel to each other.
If a key A has been set and has not since been removed, dict_contains(A) should return true. If the key has been removed and not reset, dict_contains(A) should return false.
If a key A has been set with a value B, and has not been modified since, dict_get(A) returns B
If any thread resets the value of a key from A to B, dict_get should return B when called by any thread.
If a key has been removed, dict_get should return -1