Example #1
0
// CanLock checks if the command has the UID in it's locks list. This only
// determines if the UID is in the Locks slice - not if it is or is not actually
// locked. This is because we may have just added the lock and have not actually
// tried locking or relocking yet.
func (c *Command) CanLock(uid uid.UIDLocker) bool {
	for _, l := range c.Locks {
		if uid.IsAlso(l) {
			return true
		}
	}
	return false
}
Example #2
0
// AddLock takes a UID and adds it to the Locks slice in the correct position.
// Locks should always be acquired in unique Id sequence lowest to highest to
// avoid deadlocks. By using this method the Locks can easily be iterated via a
// range and in the correct sequence required.
//
// NOTE: We cannot add the same Lock twice otherwise we would deadlock ourselves
// when locking - currently we silently drop duplicate locks.
//
// This routine is a little cute and avoids doing any 'real' sorting to keep the
// elements in unique ID sequence. We add our UID to our slice. If we have one
// element only it's what we just added so we bail.
//
// If we have multiple elements we have the appended element on the end and need
// to check where it goes, shift the trailing elements up by one then write our
// new element in:
//
//	3 7 9 4 <- append new element 4 to end
//	3 7 9 4 <- correct place: 4 goes between 3 and 7
//	3 7 7 9 <- shift 7,9 up one overwriting our appended element
//	3 4 7 9 <- we now write our new element into our 'hole'
//
// What if we can't find an element with a unique Id greater than the one we are
// inserting?
//
//	3 7 9 10 <- append new element 10 to end
//	3 7 9 10 <- correct place: 10 goes after 9, no insert point found
//	3 7 9 10 <- No shifting is done, appended element not over-written
//	3 4 7 10 <- new element already in correct place, nothing else to do
//
// This function could be more efficient with large numbers of elements by using
// a binary search to find the insertion point for the new element. However this
// would make the code more complex and we don't expect to handle huge numbers
// of locks with this function.
func (c *Command) AddLock(uid uid.UIDLocker) {

	if uid == nil || c.CanLock(uid) {
		return
	}

	c.locksModified = true
	c.Locks = append(c.Locks, uid)

	if l := len(c.Locks); l > 1 {
		u := uid.UniqueId()
		for i := 0; i < l; i++ {
			if u > c.Locks[i].UniqueId() {
				copy(c.Locks[i+1:l], c.Locks[i:l-1])
				c.Locks[i] = uid
				break
			}
		}
	}
}