cloud-game/pkg/lock/lock.go
sergystepanov 980a97a526
Handle no config situation for workers (#253)
(experimental feature)

Before a worker can start, it should have a configuration file. In case if such a file is not found it may request configuration from the coordinator to which it connected.

Added example logic if a worker is needed to be blocked until a successful packet exchange with a coordinator is being made.

* Add error return for config loader

* Add config loaded flag to worker

* Add zone flag

* Add a custom mutex lock with timout

* Refactor worker runtime

* Refactor internal api

* Extract monitoring server config

* Extract worker HTTP(S) server

* Add generic sub-server interface

* Add internal coordinator API

* Add internal routes and handlers to worker

* Add internal worker API

* Refactor worker run

* Migrate serverId call to new API

* Add packet handler to cws

* Extract handlers for internal worker routes in coordinator

* Pass worker to the worker internal heandlers

* Cleanup worker handlers in coordinator

* Add closeRoom packet handler to the API

* Add GetRoom packet handler to the API

* Add RegisterRoom packet handler to the API

* Add IceCandidate packet handler to the API (internal and browser)

* Add Heartbeat packet handler to the API (internal and browser)

* Rename worker routes init function

* Extract worker/coordinator internal ws handlers

* Update timed locker

* Allow sequential timed locks

* Add config request from workers

* Add nil check for the route registration functions
2021-01-03 21:23:55 +03:00

48 lines
929 B
Go

package lock
import (
"sync/atomic"
"time"
)
type TimeLock struct {
l chan struct{}
locked int32
}
// NewLock returns new lock (mutex) with a timeout option.
func NewLock() *TimeLock {
return &TimeLock{l: make(chan struct{}, 1)}
}
// Lock unconditionally blocks the execution.
func (tl *TimeLock) Lock() {
if tl.isLocked() {
return
}
tl.lock()
<-tl.l
}
// LockFor blocks the execution at most for
// the given period of time.
func (tl *TimeLock) LockFor(d time.Duration) {
tl.lock()
select {
case <-tl.l:
case <-time.After(d):
}
}
// Unlock removes the current block if any.
func (tl *TimeLock) Unlock() {
if !tl.isLocked() {
return
}
tl.unlock()
tl.l <- struct{}{}
}
func (tl *TimeLock) isLocked() bool { return atomic.LoadInt32(&tl.locked) == 1 }
func (tl *TimeLock) lock() { atomic.StoreInt32(&tl.locked, 1) }
func (tl *TimeLock) unlock() { atomic.StoreInt32(&tl.locked, 0) }