Image you have a struct that represents a resource that only one user can access at a time. Might look something like this:
type Resource struct{
InUse bool//or int32/int64 is you want to use atomics
Resource string //parameters that map to the resource, think `/dev/chardeviceXXX`
}
There are a finite number of these resources and users will request access to them randomly and concurrently so you package them in a manager
type ResourceManager struct{
Resources []*Resource //or a map
}
I am trying to figure out the optimal, safe way for the manager to create a function func (m *ResourceManager)GetUnusedResouce()(*Resouce,error) that will:
- Iterate though all the resources until one that is not InUse is found
- Mark it as InUse and return the *Resouce to the calling context/goroutine
- I'd lock to avoid any system level locking (flock) and do this all in Go
- There also needs to be a function to mark the Resouce are no longer in Use
Right now I use a mutex in the manager to lock access as I iterate through the entire slice. It is safe, but I am hoping to speed this up by being able to search for an used resource concurrently and handle two goroutines trying to mark the same resource as InUse.
Update
I am specifically wondering if making the Resource InUse field an int64 and then using atomic.CompareAndSwapInt64 would allow the Resource manager to lock right when it found an unused resource:
func (m *ResourceManager)GetUnusedResouce()(*Resouce,error){
for i := range Resources{
if atomic.CompareAndSwapInt64(&Resouces[i].InUse,1){
return Resouces[i],nil
}
}
return nil, errors.New("all resouces in use")
}
Any unit tests to better test this would also be appreciated.
atomic.CompareAndSwapInt