Break out of event waiting loop based on Java-side boolean value

This commit is contained in:
hedgecrw85 2020-02-19 11:47:39 -06:00
parent 5e41067f00
commit 8c9e671c43
1 changed files with 28 additions and 19 deletions

View File

@ -2,7 +2,7 @@
* SerialPort_Windows.c * SerialPort_Windows.c
* *
* Created on: Feb 25, 2012 * Created on: Feb 25, 2012
* Last Updated on: Feb 18, 2020 * Last Updated on: Feb 19, 2020
* Author: Will Hedgecock * Author: Will Hedgecock
* *
* Copyright (C) 2012-2020 Fazecast, Inc. * Copyright (C) 2012-2020 Fazecast, Inc.
@ -46,7 +46,7 @@ jfieldID serialPortHandleField;
jfieldID comPortField; jfieldID comPortField;
jfieldID friendlyNameField; jfieldID friendlyNameField;
jfieldID portDescriptionField; jfieldID portDescriptionField;
jfieldID isOpenedField; jfieldID eventListenerRunningField;
jfieldID disableConfigField; jfieldID disableConfigField;
jfieldID isDtrEnabledField; jfieldID isDtrEnabledField;
jfieldID isRtsEnabledField; jfieldID isRtsEnabledField;
@ -350,7 +350,7 @@ JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrar
comPortField = env->GetFieldID(serialCommClass, "comPort", "Ljava/lang/String;"); comPortField = env->GetFieldID(serialCommClass, "comPort", "Ljava/lang/String;");
friendlyNameField = env->GetFieldID(serialCommClass, "friendlyName", "Ljava/lang/String;"); friendlyNameField = env->GetFieldID(serialCommClass, "friendlyName", "Ljava/lang/String;");
portDescriptionField = env->GetFieldID(serialCommClass, "portDescription", "Ljava/lang/String;"); portDescriptionField = env->GetFieldID(serialCommClass, "portDescription", "Ljava/lang/String;");
isOpenedField = env->GetFieldID(serialCommClass, "isOpened", "Z"); eventListenerRunningField = env->GetFieldID(serialCommClass, "eventListenerRunning", "Z");
disableConfigField = env->GetFieldID(serialCommClass, "disableConfig", "Z"); disableConfigField = env->GetFieldID(serialCommClass, "disableConfig", "Z");
isDtrEnabledField = env->GetFieldID(serialCommClass, "isDtrEnabled", "Z"); isDtrEnabledField = env->GetFieldID(serialCommClass, "isDtrEnabled", "Z");
isRtsEnabledField = env->GetFieldID(serialCommClass, "isRtsEnabled", "Z"); isRtsEnabledField = env->GetFieldID(serialCommClass, "isRtsEnabled", "Z");
@ -387,7 +387,7 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
{ {
// Configure the port parameters and timeouts // Configure the port parameters and timeouts
if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, (jlong)serialPortHandle)) if (Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, (jlong)serialPortHandle))
env->SetBooleanField(obj, isOpenedField, JNI_TRUE); env->SetLongField(obj, serialPortHandleField, (jlong)serialPortHandle);
else else
{ {
// Close the port if there was a problem setting the parameters // Close the port if there was a problem setting the parameters
@ -395,7 +395,7 @@ JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(
PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); PurgeComm(serialPortHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
while (!CloseHandle(serialPortHandle) && (numRetries-- > 0)); while (!CloseHandle(serialPortHandle) && (numRetries-- > 0));
serialPortHandle = INVALID_HANDLE_VALUE; serialPortHandle = INVALID_HANDLE_VALUE;
env->SetBooleanField(obj, isOpenedField, JNI_FALSE); env->SetLongField(obj, serialPortHandleField, -1l);
} }
} }
@ -566,33 +566,43 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_waitForEvent(JNI
} }
// Wait for a serial port event // Wait for a serial port event
DWORD eventMask = 0, numBytesRead, errorsMask, readResult = WAIT_FAILED; BOOL listenerRunning = TRUE;
DWORD eventMask = 0, numBytesRead = 0, errorsMask, readResult = WAIT_FAILED;
if (WaitCommEvent(serialPortHandle, &eventMask, &overlappedStruct) == FALSE) if (WaitCommEvent(serialPortHandle, &eventMask, &overlappedStruct) == FALSE)
{ {
if (GetLastError() != ERROR_IO_PENDING) // Problem occurred if (GetLastError() != ERROR_IO_PENDING) // Problem occurred
{ {
// Problem reading, close port // Problem reading, close port
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD); Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
serialPortHandle = INVALID_HANDLE_VALUE; listenerRunning = FALSE;
} }
else else
{ {
BOOL continueWaiting = TRUE; do
while (continueWaiting)
{ {
readResult = WaitForSingleObject(overlappedStruct.hEvent, 750); listenerRunning = env->GetBooleanField(obj, eventListenerRunningField);
continueWaiting = ((readResult == WAIT_TIMEOUT) && (env->GetIntField(obj, eventFlagsField) != 0)); if (listenerRunning)
} readResult = WaitForSingleObject(overlappedStruct.hEvent, 500);
else
{
CancelIo(serialPortHandle);
readResult = WaitForSingleObject(overlappedStruct.hEvent, INFINITE);
}
} while ((readResult == WAIT_TIMEOUT) && listenerRunning);
if ((readResult != WAIT_OBJECT_0) || (GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, FALSE) == FALSE)) if ((readResult != WAIT_OBJECT_0) || (GetOverlappedResult(serialPortHandle, &overlappedStruct, &numBytesRead, FALSE) == FALSE))
numBytesRead = 0; numBytesRead = 0;
} }
} }
// Ensure that new data actually was received // Ensure that new data actually was received
COMSTAT commInfo; if (listenerRunning)
if ((serialPortHandle != INVALID_HANDLE_VALUE) && !ClearCommError(serialPortHandle, &errorsMask, &commInfo)) {
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD); COMSTAT commInfo;
numBytesRead = commInfo.cbInQue; if (!ClearCommError(serialPortHandle, &errorsMask, &commInfo))
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, obj, serialPortFD);
else
numBytesRead = commInfo.cbInQue;
}
// Return type of event if successful // Return type of event if successful
CloseHandle(overlappedStruct.hEvent); CloseHandle(overlappedStruct.hEvent);
@ -619,11 +629,10 @@ JNIEXPORT jboolean JNICALL Java_com_fazecast_jSerialComm_SerialPort_closePortNat
// Close the port // Close the port
int numRetries = 10; int numRetries = 10;
while (env->GetBooleanField(obj, isOpenedField) && !CloseHandle(serialPortHandle) && (GetLastError() != ERROR_INVALID_HANDLE) && (numRetries-- > 0)); while (!CloseHandle(serialPortHandle) && (GetLastError() != ERROR_INVALID_HANDLE) && (numRetries-- > 0));
if (numRetries > 0) if (numRetries > 0)
{ {
env->SetLongField(obj, serialPortHandleField, -1l); env->SetLongField(obj, serialPortHandleField, -1l);
env->SetBooleanField(obj, isOpenedField, JNI_FALSE);
return JNI_TRUE; return JNI_TRUE;
} }
@ -707,7 +716,7 @@ JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_readBytes(JNIEnv
CloseHandle(overlappedStruct.hEvent); CloseHandle(overlappedStruct.hEvent);
env->SetByteArrayRegion(buffer, offset, numBytesRead, (jbyte*)readBuffer); env->SetByteArrayRegion(buffer, offset, numBytesRead, (jbyte*)readBuffer);
free(readBuffer); free(readBuffer);
return (result == TRUE) && (env->GetBooleanField(obj, isOpenedField)) ? numBytesRead : -1; return (result == TRUE) ? numBytesRead : -1;
} }
JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset) JNIEXPORT jint JNICALL Java_com_fazecast_jSerialComm_SerialPort_writeBytes(JNIEnv *env, jobject obj, jlong serialPortFD, jbyteArray buffer, jlong bytesToWrite, jlong offset)