79 lines · 1.3 KB · Go
RawDownload
package pluginhost import (	"context"	"fmt"	"sync") type guardedPluginClient struct {	mu     sync.Mutex	cond   *sync.Cond	inner  pluginClient	calls  int	closed bool} func newGuardedPluginClient(inner pluginClient) pluginClient {	client := &guardedPluginClient{inner: inner}	client.cond = sync.NewCond(&client.mu)	return client} func (c *guardedPluginClient) Call(ctx context.Context, method string, request []byte) ([]byte, error) {	inner, errAcquire := c.acquire()	if errAcquire != nil {		return nil, errAcquire	}	defer c.release()	return inner.Call(ctx, method, request)} func (c *guardedPluginClient) acquire() (pluginClient, error) {	if c == nil {		return nil, fmt.Errorf("plugin client is closed")	}	c.mu.Lock()	defer c.mu.Unlock()	if c.closed || c.inner == nil {		return nil, fmt.Errorf("plugin client is closed")	}	c.calls++	return c.inner, nil} func (c *guardedPluginClient) release() {	c.mu.Lock()	c.calls--	if c.calls == 0 {		c.cond.Broadcast()	}	c.mu.Unlock()} func (c *guardedPluginClient) Shutdown() {	if c == nil {		return	} 	var inner pluginClient	c.mu.Lock()	if c.closed {		for c.calls > 0 {			c.cond.Wait()		}		c.mu.Unlock()		return	}	c.closed = true	for c.calls > 0 {		c.cond.Wait()	}	inner = c.inner	c.inner = nil	c.mu.Unlock() 	if inner != nil {		inner.Shutdown()	}}