8000 [breaking] daemon: Fix concurrency and streamline access to PackageManager by cmaglie · Pull Request #1828 · arduino/arduino-cli · GitHub
[go: up one dir, main page]

Skip to content

[breaking] daemon: Fix concurrency and streamline access to PackageManager #1828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Aug 26, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

8000
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Created a coreInstancesContainer
This container will handle all the atomic access to the instances map.
  • Loading branch information
cmaglie committed Aug 23, 2022
commit 4db186ee0b48f0c13ed8b958c7b25c78c4b3f067
74 changes: 48 additions & 26 deletions commands/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ import (

var tr = i18n.Tr

// this map contains all the running Arduino Core Services instances
// referenced by an int32 handle
var instances = map[int32]*CoreInstance{}
var instancesCount int32 = 1
var instancesMux sync.Mutex

// CoreInstance is an instance of the Arduino Core Services. The user can
// instantiate as many as needed by providing a different configuration
// for each one.
Expand All @@ -60,18 +54,55 @@ type CoreInstance struct {
lm *librariesmanager.LibrariesManager
}

// coreInstancesContainer has methods to add an remove instances atomically.
type coreInstancesContainer struct {
instances map[int32]*CoreInstance
instancesCount int32
instancesMux sync.Mutex
}

// instances contains all the running Arduino Core Services instances
var instances = &coreInstancesContainer{
instances: map[int32]*CoreInstance{},
instancesCount: 1,
}

// GetInstance returns a CoreInstance for the given ID, or nil if ID
// doesn't exist
func GetInstance(id int32) *CoreInstance {
instancesMux.Lock()
defer instancesMux.Unlock()
return instances[id]
func (c *coreInstancesContainer) GetInstance(id int32) *CoreInstance {
c.instancesMux.Lock()
defer c.instancesMux.Unlock()
return c.instances[id]
}

// AddAndAssignID saves the CoreInstance and assign an unique ID to
// retrieve it later
func (c *coreInstancesContainer) AddAndAssignID(i *CoreInstance) int32 {
c.instancesMux.Lock()
defer c.instancesMux.Unlock()
id := c.instancesCount
c.instances[id] = i
c.instancesCount++
return id
}

// RemoveID removed the CoreInstance referenced by id. Returns true
// if the operation is successful, or false if the CoreInstance does
// not exists
func (c *coreInstancesContainer) RemoveID(id int32) bool {
c.instancesMux.Lock()
defer c.instancesMux.Unlock()
if _, ok := c.instances[id]; !ok {
return false
}
delete(c.instances, id)
return true
}

// GetPackageManager returns a PackageManager for the given ID, or nil if
// ID doesn't exist
func GetPackageManager(id int32) *packagemanager.PackageManager {
i := GetInstance(id)
i := instances.GetInstance(id)
if i == nil {
return nil
}
Expand All @@ -82,7 +113,7 @@ func GetPackageManager(id int32) *packagemanager.PackageManager {
// explorer holds a read lock on the underlying PackageManager and it should
// be released by calling the returned "release" function.
func GetPackageManagerExplorer(instance rpc.InstanceCommand) (explorer *packagemanager.Explorer, release func()) {
i := GetInstance(instance.GetInstance().GetId())
i := instances.GetInstance(instance.GetInstance().GetId())
if i == nil {
return nil, nil
}
Expand All @@ -91,7 +122,7 @@ func GetPackageManagerExplorer(instance rpc.InstanceCommand) (explorer *packagem

// GetLibraryManager returns the library manager for the given instance ID
func GetLibraryManager(id int32) *librariesmanager.LibrariesManager {
i := GetInstance(id)
i := instances.GetInstance(id)
if i == nil {
return nil
}
Expand Down Expand Up @@ -154,11 +185,7 @@ func Create(req *rpc.CreateRequest, extraUserAgent ...string) (*rpc.CreateRespon
)

// Save instance
instancesMux.Lock()
instanceID := instancesCount
instances[instanceID] = instance
instancesCount++
instancesMux.Unlock()
instanceID := instances.AddAndAssignID(instance)

return &rpc.CreateResponse{
Instance: &rpc.Instance{Id: instanceID},
Expand All @@ -178,7 +205,7 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
if reqInst == nil {
return &arduino.InvalidInstanceError{}
}
instance := GetInstance(reqInst.GetId())
instance := instances.GetInstance(reqInst.GetId())
if instance == nil {
return &arduino.InvalidInstanceError{}
}
Expand Down Expand Up @@ -430,14 +457,9 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro

// Destroy FIXMEDOC
func Destroy(ctx context.Context, req *rpc.DestroyRequest) (*rpc.DestroyResponse, error) {
id := req.GetInstance().GetId()

instancesMux.Lock()
defer instancesMux.Unlock()
if _, ok := instances[id]; !ok {
if ok := instances.RemoveID(req.GetInstance().GetId()); !ok {
return nil, &arduino.InvalidInstanceError{}
}
delete(instances, id)
return &rpc.DestroyResponse{}, nil
}

Expand Down Expand Up @@ -473,7 +495,7 @@ func UpdateLibrariesIndex(ctx context.Context, req *rpc.UpdateLibrariesIndexRequ

// UpdateIndex FIXMEDOC
func UpdateIndex(ctx context.Context, req *rpc.UpdateIndexRequest, downloadCB rpc.DownloadProgressCB) (*rpc.UpdateIndexResponse, error) {
if GetInstance(req.GetInstance().GetId()) == nil {
if instances.GetInstance(req.GetInstance().GetId()) == nil {
return nil, &arduino.InvalidInstanceError{}
}

Expand Down
0