Repository: incubator-mynewt-newtmgr
Updated Branches:
refs/heads/master 7f57aa2d4 -> ad32cdd3d
nmxact - allow use of restarting ble xport
If the BLE transport is in the process of restarting, an attempt to use
it will block until either:
* The transport successfully starts; proceed with transmission.
* The transport fails to start; report an error.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/3cdf50dc
Tree:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/3cdf50dc
Diff:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/3cdf50dc
Branch: refs/heads/master
Commit: 3cdf50dcd045d3511e4cacb6d80dd0aea8d5a166
Parents: 7f57aa2
Author: Christopher Collins <[email protected]>
Authored: Mon Apr 3 19:33:59 2017 -0700
Committer: Christopher Collins <[email protected]>
Committed: Mon Apr 3 19:35:51 2017 -0700
----------------------------------------------------------------------
nmxact/nmble/ble_xport.go | 86 ++++++++++++++++++++++++++++++++----------
1 file changed, 67 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/3cdf50dc/nmxact/nmble/ble_xport.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_xport.go b/nmxact/nmble/ble_xport.go
index 32ced04..02854c6 100644
--- a/nmxact/nmble/ble_xport.go
+++ b/nmxact/nmble/ble_xport.go
@@ -4,7 +4,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
- "sync/atomic"
+ "sync"
"time"
log "github.com/Sirupsen/logrus"
@@ -47,10 +47,11 @@ func NewXportCfg() XportCfg {
}
}
-type BleXportState uint32
+type BleXportState int
const (
- BLE_XPORT_STATE_STOPPED BleXportState = iota
+ BLE_XPORT_STATE_DORMANT BleXportState = iota
+ BLE_XPORT_STATE_STOPPED
BLE_XPORT_STATE_STARTING
BLE_XPORT_STATE_STARTED
BLE_XPORT_STATE_STOPPING
@@ -58,12 +59,15 @@ const (
// Implements xport.Xport.
type BleXport struct {
- Bd *BleDispatcher
- client *unixchild.Client
- state BleXportState
- stopChan chan struct{}
- shutdownChan chan bool
- numStopListeners int
+ Bd *BleDispatcher
+ client *unixchild.Client
+ state BleXportState
+ stopChan chan struct{}
+ numStopListeners int
+ shutdownChan chan bool
+ readyChan chan error
+ numReadyListeners int
+ mtx sync.Mutex
cfg XportCfg
}
@@ -224,14 +228,53 @@ func (bx *BleXport) shutdown(restart bool, err error) {
}
}
-func (bx *BleXport) setStateFrom(from BleXportState, to BleXportState) bool {
- return atomic.CompareAndSwapUint32(
- (*uint32)(&bx.state), uint32(from), uint32(to))
+func (bx *BleXport) blockUntilReady() error {
+ bx.mtx.Lock()
+ switch bx.state {
+ case BLE_XPORT_STATE_STARTED:
+ // Already started; don't block.
+ bx.mtx.Unlock()
+ return nil
+
+ case BLE_XPORT_STATE_DORMANT:
+ // Not in the process of starting; the user will be waiting
forever.
+ bx.mtx.Unlock()
+ return fmt.Errorf("Attempt to use BLE transport without
starting it")
+
+ default:
+ }
+
+ bx.numReadyListeners++
+ bx.mtx.Unlock()
+
+ return <-bx.readyChan
}
-func (bx *BleXport) getState() BleXportState {
- u32 := atomic.LoadUint32((*uint32)(&bx.state))
- return BleXportState(u32)
+func (bx *BleXport) notifyReadyListeners(err error) {
+ for i := 0; i < bx.numReadyListeners; i++ {
+ bx.readyChan <- err
+ }
+ bx.numReadyListeners = 0
+}
+
+func (bx *BleXport) setStateFrom(from BleXportState, to BleXportState) bool {
+ bx.mtx.Lock()
+ defer bx.mtx.Unlock()
+
+ if bx.state != from {
+ return false
+ }
+
+ bx.state = to
+ switch bx.state {
+ case BLE_XPORT_STATE_STARTED:
+ bx.notifyReadyListeners(nil)
+ case BLE_XPORT_STATE_STOPPED:
+ bx.notifyReadyListeners(fmt.Errorf("BLE transport stopped"))
+ default:
+ }
+
+ return true
}
func (bx *BleXport) Stop() error {
@@ -356,9 +399,14 @@ func (bx *BleXport) startOnce() error {
}
func (bx *BleXport) Start() error {
+ if !bx.setStateFrom(BLE_XPORT_STATE_DORMANT, BLE_XPORT_STATE_STOPPED) {
+ return nmxutil.NewXportError("BLE xport started twice")
+ }
+
// Try to start the transport. If this first attempt fails, report the
// error and don't retry.
if err := bx.startOnce(); err != nil {
+ bx.setStateFrom(BLE_XPORT_STATE_STOPPED,
BLE_XPORT_STATE_DORMANT)
log.Debugf("Error starting BLE transport: %s",
err.Error())
return err
@@ -374,6 +422,8 @@ func (bx *BleXport) Start() error {
// explicit stop call (instead of an unexpected error),
stop
// restarting the transport.
if !bx.cfg.BlehostdRestart || !restart {
+ bx.setStateFrom(BLE_XPORT_STATE_STOPPED,
+ BLE_XPORT_STATE_DORMANT)
break
}
@@ -402,10 +452,8 @@ func (bx *BleXport) txNoSync(data []byte) {
}
func (bx *BleXport) Tx(data []byte) error {
- if bx.getState() != BLE_XPORT_STATE_STARTED {
- return nmxutil.NewXportError(
- fmt.Sprintf("Attempt to transmit before BLE xport fully
started; "+
- "state=%d", bx.getState()))
+ if err := bx.blockUntilReady(); err != nil {
+ return err
}
bx.txNoSync(data)