| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 | package appimport (	"errors"	"sync/atomic"	"github.com/v2ray/v2ray-core/common")var (	ErrorMissingApplication = errors.New("App: Failed to found one or more applications."))type ID int// Context of a function call from proxy to app.type Context interface {	CallerTag() string}type Caller interface {	Tag() string}type Application interface {	common.Releasable}type ApplicationInitializer func() error// A Space contains all apps that may be available in a V2Ray runtime.// Caller must check the availability of an app by calling HasXXX before getting its instance.type Space interface {	Initialize() error	InitializeApplication(ApplicationInitializer)	HasApp(ID) bool	GetApp(ID) Application	BindApp(ID, Application)}type spaceImpl struct {	cache      map[ID]Application	initSignal chan struct{}	initErrors chan error	appsToInit int32	appsDone   int32}func NewSpace() Space {	return &spaceImpl{		cache:      make(map[ID]Application),		initSignal: make(chan struct{}),		initErrors: make(chan error, 1),	}}func (this *spaceImpl) InitializeApplication(f ApplicationInitializer) {	atomic.AddInt32(&(this.appsToInit), 1)	go func() {		<-this.initSignal		err := f()		if err != nil {			this.initErrors <- err		}		count := atomic.AddInt32(&(this.appsDone), 1)		if count == this.appsToInit {			close(this.initErrors)		}	}()}func (this *spaceImpl) Initialize() error {	close(this.initSignal)	if err, open := <-this.initErrors; open {		return err	}	return nil}func (this *spaceImpl) HasApp(id ID) bool {	_, found := this.cache[id]	return found}func (this *spaceImpl) GetApp(id ID) Application {	obj, found := this.cache[id]	if !found {		return nil	}	return obj}func (this *spaceImpl) BindApp(id ID, application Application) {	this.cache[id] = application}
 |