diff options
author | Jakob Odersky <jakob@odersky.com> | 2017-01-15 16:57:39 -0800 |
---|---|---|
committer | Jakob Odersky <jakob@odersky.com> | 2017-01-15 16:57:39 -0800 |
commit | f9e6f877f67050af93334a687ce86c4baf19fc8a (patch) | |
tree | 7d758a1d8c3f65c54a6b2354f2dfa2c2924d87f6 /core/src/main/scala | |
parent | 5acd9c7939381606b438a22565d860facc57ef2b (diff) | |
download | akka-serial-f9e6f877f67050af93334a687ce86c4baf19fc8a.tar.gz akka-serial-f9e6f877f67050af93334a687ce86c4baf19fc8a.tar.bz2 akka-serial-f9e6f877f67050af93334a687ce86c4baf19fc8a.zip |
Create sync project and rename native project
Diffstat (limited to 'core/src/main/scala')
8 files changed, 5 insertions, 289 deletions
diff --git a/core/src/main/scala/ch/jodersky/akka/serial/Parity.scala b/core/src/main/scala/ch/jodersky/akka/serial/Parity.scala deleted file mode 100644 index 4e90744..0000000 --- a/core/src/main/scala/ch/jodersky/akka/serial/Parity.scala +++ /dev/null @@ -1,9 +0,0 @@ -package ch.jodersky.akka.serial - -/** Specifies available parities used in serial communication. */ -object Parity extends Enumeration { - type Parity = Value - val None = Value(0) - val Odd = Value(1) - val Even = Value(2) -} diff --git a/core/src/main/scala/ch/jodersky/akka/serial/Serial.scala b/core/src/main/scala/ch/jodersky/akka/serial/Serial.scala index 889d3b0..f0c9602 100644 --- a/core/src/main/scala/ch/jodersky/akka/serial/Serial.scala +++ b/core/src/main/scala/ch/jodersky/akka/serial/Serial.scala @@ -127,6 +127,6 @@ object Serial extends ExtensionKey[SerialExt] { * * @param value set to enable debugging */ - def debug(value: Boolean) = UnsafeSerial.debug(value) + def debug(value: Boolean) = sync.UnsafeSerial.debug(value) } diff --git a/core/src/main/scala/ch/jodersky/akka/serial/SerialConnection.scala b/core/src/main/scala/ch/jodersky/akka/serial/SerialConnection.scala deleted file mode 100644 index 6481ee6..0000000 --- a/core/src/main/scala/ch/jodersky/akka/serial/SerialConnection.scala +++ /dev/null @@ -1,140 +0,0 @@ -package ch.jodersky.akka.serial - -import java.nio.ByteBuffer -import java.util.concurrent.atomic.AtomicBoolean - -/** - * Represents a serial connection in a more secure and object-oriented style than `UnsafeSerial`. In - * contrast to the latter, this class encapsulates and secures any pointers used to communicate with - * the native backend and is thread-safe. - * - * The underlying serial port is assumed open when this class is initialized. - */ -private[serial] class SerialConnection private ( - unsafe: UnsafeSerial, - val port: String -) { - - private var reading: Boolean = false - private val readLock = new Object - - private var writing: Boolean = false - private val writeLock = new Object - - private val closed = new AtomicBoolean(false) - - /** - * Checks if this serial port is closed. - */ - def isClosed = closed.get() - - /** - * Closes the underlying serial connection. Any callers blocked on read or write will return. - * A call of this method has no effect if the serial port is already closed. - * @throws IOException on IO error - */ - def close(): Unit = this.synchronized { - if (!closed.get) { - closed.set(true) - unsafe.cancelRead() - readLock.synchronized { - while (reading) this.wait() - } - writeLock.synchronized { - while (writing) this.wait() - } - unsafe.close() - } - } - - /** - * Reads data from underlying serial connection into a ByteBuffer. - * Note that data is read into the buffer's memory, its attributes - * such as position and limit are not modified. - * - * A call to this method is blocking, however it is interrupted - * if the connection is closed. - * - * This method works for direct and indirect buffers but is optimized - * for the former. - * - * @param buffer a ByteBuffer into which data is read - * @return the actual number of bytes read - * @throws PortInterruptedException if port is closed while reading - * @throws IOException on IO error - */ - def read(buffer: ByteBuffer): Int = readLock.synchronized { - if (!closed.get) { - try { - reading = true - unsafe.read(buffer) - } finally { - reading = false - if (closed.get) readLock.notify() - } - } else { - throw new PortClosedException(s"${port} is closed") - } - } - - /** - * Writes data from a ByteBuffer to underlying serial connection. - * Note that data is read from the buffer's memory, its attributes - * such as position and limit are not modified. - * - * The write is non-blocking, this function returns as soon as the data is copied into the kernel's - * transmission buffer. - * - * This method works for direct and indirect buffers but is optimized - * for the former. - * - * @param buffer a ByteBuffer from which data is taken - * @return the actual number of bytes written - * @throws IOException on IO error - */ - def write(buffer: ByteBuffer): Int = writeLock.synchronized { - if (!closed.get) { - try { - writing = true - unsafe.write(buffer, buffer.position) - } finally { - writing = false - if (closed.get) writeLock.notify() - } - } else { - throw new PortClosedException(s"${port} is closed") - } - } - -} - -private[serial] object SerialConnection { - - /** - * Opens a new connection to a serial port. - * This method acts as a factory to creating serial connections. - * - * @param port name of serial port to open - * @param settings settings with which to initialize the connection - * @return an instance of the open serial connection - * @throws NoSuchPortException if the given port does not exist - * @throws AccessDeniedException if permissions of the current user are not sufficient to open port - * @throws PortInUseException if port is already in use - * @throws InvalidSettingsException if any of the specified settings are invalid - * @throws IOException on IO error - */ - def open( - port: String, - settings: SerialSettings - ): SerialConnection = synchronized { - val pointer = UnsafeSerial.open( - port, - settings.baud, - settings.characterSize, - settings.twoStopBits, - settings.parity.id - ) - new SerialConnection(new UnsafeSerial(pointer), port) - } - -} diff --git a/core/src/main/scala/ch/jodersky/akka/serial/SerialManager.scala b/core/src/main/scala/ch/jodersky/akka/serial/SerialManager.scala index a6647cd..1f0a82d 100644 --- a/core/src/main/scala/ch/jodersky/akka/serial/SerialManager.scala +++ b/core/src/main/scala/ch/jodersky/akka/serial/SerialManager.scala @@ -3,6 +3,7 @@ package ch.jodersky.akka.serial import akka.actor.{ Actor, ActorLogging, OneForOneStrategy } import akka.actor.SupervisorStrategy.{ Escalate, Stop } import scala.util.{ Failure, Success, Try } +import sync.SerialConnection /** * Entry point to the serial API. Actor that manages serial port creation. Once opened, a serial port is handed over to diff --git a/core/src/main/scala/ch/jodersky/akka/serial/SerialOperator.scala b/core/src/main/scala/ch/jodersky/akka/serial/SerialOperator.scala index 1cfc703..e099e80 100644 --- a/core/src/main/scala/ch/jodersky/akka/serial/SerialOperator.scala +++ b/core/src/main/scala/ch/jodersky/akka/serial/SerialOperator.scala @@ -4,6 +4,8 @@ import akka.actor.{ Actor, ActorLogging, ActorRef, Props, Terminated } import akka.util.ByteString import java.nio.ByteBuffer +import sync.SerialConnection + /** * Operator associated to an open serial port. All communication with a port is done via an operator. Operators are created though the serial manager. * @see SerialManager @@ -21,8 +23,7 @@ private[serial] class SerialOperator(connection: SerialConnection, bufferSize: I while (!connection.isClosed && !stop) { try { buffer.clear() - val length = connection.read(buffer) - buffer.limit(length) + connection.read(buffer) val data = ByteString.fromByteBuffer(buffer) client.tell(Serial.Received(data), self) } catch { diff --git a/core/src/main/scala/ch/jodersky/akka/serial/SerialSettings.scala b/core/src/main/scala/ch/jodersky/akka/serial/SerialSettings.scala deleted file mode 100644 index e5ab797..0000000 --- a/core/src/main/scala/ch/jodersky/akka/serial/SerialSettings.scala +++ /dev/null @@ -1,10 +0,0 @@ -package ch.jodersky.akka.serial - -/** - * Groups settings used in communication over a serial port. - * @param baud baud rate to use with serial port - * @param characterSize size of a character of the data sent through the serial port - * @param twoStopBits set to use two stop bits instead of one - * @param parity type of parity to use with serial port - */ -case class SerialSettings(baud: Int, characterSize: Int = 8, twoStopBits: Boolean = false, parity: Parity.Parity = Parity.None) diff --git a/core/src/main/scala/ch/jodersky/akka/serial/UnsafeSerial.scala b/core/src/main/scala/ch/jodersky/akka/serial/UnsafeSerial.scala deleted file mode 100644 index 91d8be6..0000000 --- a/core/src/main/scala/ch/jodersky/akka/serial/UnsafeSerial.scala +++ /dev/null @@ -1,108 +0,0 @@ -package ch.jodersky.akka.serial - -import java.nio.ByteBuffer - -import ch.jodersky.jni.nativeLoader - -/** - * Low-level wrapper of native serial backend. - * - * WARNING: Methods in this class allocate native structures and deal with pointers. These - * pointers are handled as longs by java and are NOT checked for correctness, therefore passing - * invalid pointers may have unexpected results, including but not limited to SEGFAULTing the VM. - * - * See SerialConnection for a higher-level, more secured wrapper - * of serial communication. - * - * @param serialAddr address of natively allocated serial configuration structure - */ -@nativeLoader("flow4") -private[serial] class UnsafeSerial(final val serialAddr: Long) { - - final val ParityNone: Int = 0 - final val ParityOdd: Int = 1 - final val ParityEven: Int = 2 - - /** - * Reads from a previously opened serial port into a direct ByteBuffer. Note that data is only - * read into the buffer's allocated memory, its position or limit are not changed. - * - * The read is blocking, however it may be interrupted by calling cancelRead() on the given - * serial port. - * - * @param buffer direct ByteBuffer to read into - * @return number of bytes actually read - * @throws IllegalArgumentException if the ByteBuffer is not direct - * @throws PortInterruptedException if the call to this function was interrupted - * @throws IOException on IO error - */ - @native def read(buffer: ByteBuffer): Int - - /** - * Cancels a read (any caller to read or readDirect will return with a - * PortInterruptedException). This function may be called from any thread. - * - * @param serial address of natively allocated serial configuration structure - * @throws IOException on IO error - */ - @native def cancelRead(): Unit - - /** - * Writes data from a direct ByteBuffer to a previously opened serial port. Note that data is - * only taken from the buffer's allocated memory, its position or limit are not changed. - * - * The write is non-blocking, this function returns as soon as the data is copied into the kernel's - * transmission buffer. - * - * @param serial address of natively allocated serial configuration structure - * @param buffer direct ByteBuffer from which data is taken - * @param length actual amount of data that should be taken from the buffer (this is needed since the native - * backend does not provide a way to query the buffer's current limit) - * @return number of bytes actually written - * @throws IllegalArgumentException if the ByteBuffer is not direct - * @throws IOException on IO error - */ - @native def write(buffer: ByteBuffer, length: Int): Int - - /** - * Closes an previously open serial port. Natively allocated resources are freed and the serial - * pointer becomes invalid, therefore this function should only be called ONCE per open serial - * port. - * - * A port should not be closed while it is used (by a read or write) as this - * results in undefined behaviour. - * - * @param serial address of natively allocated serial configuration structure - * @throws IOException on IO error - */ - @native def close(): Unit - -} - -private[serial] object UnsafeSerial { - - /** - * Opens a serial port. - * - * @param port name of serial port to open - * @param characterSize size of a character of the data sent through the serial port - * @param twoStopBits set to use two stop bits instead of one - * @param parity type of parity to use with serial port - * @return address of natively allocated serial configuration structure - * @throws NoSuchPortException if the given port does not exist - * @throws AccessDeniedException if permissions of the current user are not sufficient to open port - * @throws PortInUseException if port is already in use - * @throws InvalidSettingsException if any of the specified settings are invalid - * @throws IOException on IO error - */ - @native def open(port: String, baud: Int, characterSize: Int, twoStopBits: Boolean, parity: Int): Long - - /** - * Sets native debugging mode. If debugging is enabled, detailed error messages - * are printed (to stderr) from native method calls. - * - * @param value set to enable debugging - */ - @native def debug(value: Boolean): Unit - -} diff --git a/core/src/main/scala/ch/jodersky/akka/serial/exceptions.scala b/core/src/main/scala/ch/jodersky/akka/serial/exceptions.scala deleted file mode 100644 index 47a59e4..0000000 --- a/core/src/main/scala/ch/jodersky/akka/serial/exceptions.scala +++ /dev/null @@ -1,19 +0,0 @@ -package ch.jodersky.akka.serial - -/** The requested port could not be found. */ -class NoSuchPortException(message: String) extends Exception(message) - -/** The requested port is in use by someone else. */ -class PortInUseException(message: String) extends Exception(message) - -/** Permissions are not sufficient to open a serial port. */ -class AccessDeniedException(message: String) extends Exception(message) - -/** The settings specified are invalid. */ -class InvalidSettingsException(message: String) extends Exception(message) - -/** A blocking operation on a port was interrupted, most likely indicating that the port is closing. */ -class PortInterruptedException(message: String) extends Exception(message) - -/** The specified port has been closed. */ -class PortClosedException(message: String) extends Exception(message) |