aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/scala
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2017-01-15 16:57:39 -0800
committerJakob Odersky <jakob@odersky.com>2017-01-15 16:57:39 -0800
commitf9e6f877f67050af93334a687ce86c4baf19fc8a (patch)
tree7d758a1d8c3f65c54a6b2354f2dfa2c2924d87f6 /core/src/main/scala
parent5acd9c7939381606b438a22565d860facc57ef2b (diff)
downloadakka-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')
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/Parity.scala9
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/Serial.scala2
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/SerialConnection.scala140
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/SerialManager.scala1
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/SerialOperator.scala5
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/SerialSettings.scala10
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/UnsafeSerial.scala108
-rw-r--r--core/src/main/scala/ch/jodersky/akka/serial/exceptions.scala19
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)