Change the write side into a series of short running operations rather than a single operation looping while listening.

This commit is contained in:
Jeremy Rand 2022-03-23 22:41:25 -04:00
parent c61b9c0729
commit b732007d68
4 changed files with 38 additions and 59 deletions

View File

@ -68,8 +68,8 @@ class GSConnection : ObservableObject {
private let writeQueue = OperationQueue() private let writeQueue = OperationQueue()
private var mainQueue = OperationQueue.main private var mainQueue = OperationQueue.main
private var condition = NSCondition()
private var canSend = true private var canSend = true
private var lastSent = ""
private func changeState(newState : GSConnectionState) private func changeState(newState : GSConnectionState)
{ {
@ -154,10 +154,10 @@ class GSConnection : ObservableObject {
do { do {
let unpacked = try unpack("<h", data) let unpacked = try unpack("<h", data)
if (unpacked[0] as? Int == GSConnection.LISTEN_SEND_MORE) { if (unpacked[0] as? Int == GSConnection.LISTEN_SEND_MORE) {
condition.lock() mainQueue.addOperation {
canSend = true self.canSend = true
condition.broadcast() self.trySend()
condition.unlock() }
} else { } else {
logger.error("Unexpected message on socket from \(self.destination)") logger.error("Unexpected message on socket from \(self.destination)")
errorOccurred(title: "Protocol Error", message: "Unexpected message from the GS") errorOccurred(title: "Protocol Error", message: "Unexpected message from the GS")
@ -193,13 +193,10 @@ class GSConnection : ObservableObject {
stopListening() stopListening()
} }
condition.lock()
if (client != nil) { if (client != nil) {
client!.close() client!.close()
self.client = nil self.client = nil
} }
condition.broadcast()
condition.unlock()
waitForWriteQueue() waitForWriteQueue()
waitForReadQueue() waitForReadQueue()
@ -212,12 +209,11 @@ class GSConnection : ObservableObject {
speechForwarder.stopListening() speechForwarder.stopListening()
self.speechForwarder = nil self.speechForwarder = nil
} }
condition.lock()
if (state == .listening) { if (state == .listening) {
changeState(newState: .stoplistening) changeState(newState: .stoplistening)
condition.broadcast() trySend()
} }
condition.unlock()
} }
private func sendListenMsg(isListening: Bool) -> Bool { private func sendListenMsg(isListening: Bool) -> Bool {
@ -236,6 +232,7 @@ class GSConnection : ObservableObject {
func listen(speechForwarder: SpeechForwarderProtocol) { func listen(speechForwarder: SpeechForwarderProtocol) {
textHeard = "" textHeard = ""
lastSent = ""
writeQueue.addOperation { writeQueue.addOperation {
if (!self.sendListenMsg(isListening: true)) { if (!self.sendListenMsg(isListening: true)) {
self.errorOccurred(title: "Write Error", message: "Unable to send data to the GS") self.errorOccurred(title: "Write Error", message: "Unable to send data to the GS")
@ -252,57 +249,39 @@ class GSConnection : ObservableObject {
} }
self.speechForwarder = speechForwarder self.speechForwarder = speechForwarder
} }
}
self.send() }
_ = self.sendListenMsg(isListening: false) private func trySend() {
if (textHeard == lastSent) {
self.mainQueue.addOperation { if (state == .stoplistening) {
if (self.state == .stoplistening) { writeQueue.addOperation {
self.changeState(newState: .connected) _ = self.sendListenMsg(isListening: false)
}
changeState(newState: .connected)
}
return
}
if (!canSend) {
return
}
canSend = false
let stringToSend = textHeard
writeQueue.addOperation {
if self.send(latestText: stringToSend, lastSent: self.lastSent) {
self.mainQueue.addOperation {
self.lastSent = stringToSend
self.trySend()
} }
} }
} }
} }
func set(text:String) func set(text:String) {
{
condition.lock()
textHeard = text textHeard = text
condition.broadcast() trySend()
condition.unlock()
}
private func send() {
var stringLastSent = ""
var stringToSend = ""
while true {
condition.lock()
guard client != nil else {
condition.unlock()
return
}
if ((stringLastSent == textHeard) && (state == .stoplistening)) {
condition.unlock()
return
}
if ((!canSend) ||
(stringLastSent == textHeard)) {
condition.wait()
condition.unlock()
continue
}
stringToSend = textHeard
condition.unlock()
if send(latestText: stringToSend, lastSent: stringLastSent) {
stringLastSent = stringToSend
condition.lock()
canSend = false
condition.unlock()
}
}
} }
private func send(latestText : String, lastSent: String) -> Bool { private func send(latestText : String, lastSent: String) -> Bool {

View File

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0</string> <string>1.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>598</string> <string>619</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string> <string>public.app-category.utilities</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>

View File

@ -80,7 +80,6 @@ struct Webview: UIViewRepresentable {
decisionHandler(WKNavigationActionPolicy.cancel) decisionHandler(WKNavigationActionPolicy.cancel)
return return
} }
print("no link")
decisionHandler(WKNavigationActionPolicy.allow) decisionHandler(WKNavigationActionPolicy.allow)
} }
} }

View File

@ -103,9 +103,10 @@ class ListenerGSTests: XCTestCase {
XCTAssertEqual(connection.textHeard, "Hello, everyone!") XCTAssertEqual(connection.textHeard, "Hello, everyone!")
XCTAssert(server.sendMore()) XCTAssert(server.sendMore())
connection.waitForMain()
connection.waitForWriteQueue()
XCTAssertEqual(server.getText(), "\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}everyone!") XCTAssertEqual(server.getText(), "\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}\u{7f}everyone!")
connection.waitForWriteQueue()
connection.waitForMain() connection.waitForMain()
XCTAssert(server.getListenState(isListening: false)) XCTAssert(server.getListenState(isListening: false))