javalistenersynchronousjssc

Synchronous execution between methods and listener in java


Assuming i have to write 10 times consecutively to a serial port.

for (int i = 1; i <= 10; i++) {
     serialPort.writeInt(i);
// wait until SerialPortEventListener receives something then write again
    }

or:

void writeMoreDate(){
         serialPort.writeInt(something);
    // wait until SerialPortEventListener receives something then write again
         serialPort.writeInt(something;
    // wait until SerialPortEventListener receives something then write again
         serialPort.writeInt(something);
}

And i have a Serial Port Event Listener, that fires every time i write something to it, and calls .map() method.

 @Override
    public void serialEvent(SerialPortEvent event) {
        if (event.isRXCHAR() && event.getEventValue() > 0) {

 //when data arrived do something and notify that next method can execute!            
        } 
    }

How can i make method to wait until serialEvent receives something?

-This is how i handled this until now using java.util.concurrent.Semaphore:

ex:

  Semaphore semaphore = new Semaphore(MAX_CONCURRENT_THREADS, true);

        void writeMoreDate(){
           Runnable runnable () -> { 
             serialPort.writeInt(something);
             semaphore.acquire();
             serialPort.writeInt(something;
             semaphore.acquire();
             serialPort.writeInt(something);
             semaphore.acquire();
            }
               new Thread(runnable).start();
           }

and on Serial Listener:

 @Override
    public void serialEvent(SerialPortEvent event) {
        if (event.isRXCHAR() && event.getEventValue() > 0) {
               semaphore.release();
        } 
    }

But I'm not sure if that is right solution. Thanks.


Solution

  • I would try doing it a bit more recursively instead of using a for loop. Something along the lines of:

    private int activeIndex = -1;
    private int maxIndex = -1;
    
    private void write(int currentIndex, int maxIndex){
        if(maxIndex < currentIndex)
            return;
    
        activeIndex = currentIndex;
        maxIndex = maxIndex;
    
        serialPort.writeInt(currentIndex);
    }
    

    And then in your event listener you would trigger the next write event after the last event has finished...

    public void serialEvent(SerialPortEvent event) {
        if (event.isRXCHAR() && event.getEventValue() > 0) {
            .....
    
            write(activeIndex + 1, maxIndex);
        } 
    }
    

    It would be much cleaner if you could somehow pass the current/max indices through the SerialPortEvent instead of using class variables to hold the data, but I'm not familiar enough with those classes to know if that's possible.

    So, from your example, you could use it with:

    write(0, 10);