Skip to content

Commit

Permalink
Add documentation
Browse files Browse the repository at this point in the history
Add documentation for async package.
  • Loading branch information
NthPortal committed Jan 6, 2017
1 parent 1bc4612 commit 41b4716
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 2 deletions.
19 changes: 19 additions & 0 deletions src/main/scala/com/nthportal/shell/async/AsyncShell.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import java.util.concurrent.Executors

import scala.concurrent.{ExecutionContext, Future, Promise}

/**
* An asynchronous shell. It processes commands and tab-completions asynchronously.
*
* @param inputProvider the [[InputProvider]] for this asynchronous shell
* @param shell the (synchronous) shell to be managed asynchronously by this
* @param ec the [[ExecutionContext]] in which to execute this asynchronous shell
*/
final class AsyncShell private(inputProvider: InputProvider)(implicit shell: Shell, ec: ExecutionContext) {
@volatile
private var terminated: Boolean = false
Expand All @@ -17,6 +24,11 @@ final class AsyncShell private(inputProvider: InputProvider)(implicit shell: She

private def handleNextAction(): Future[Unit] = for (action <- inputProvider.nextAction) yield action.doAction

/**
* Terminates this asynchronous shell so that it will no longer process inputs.
*
* @return a Future which will be completed once the shell is fully terminated
*/
def terminate(): Future[Unit] = {
if (terminated) throw new IllegalStateException("Shell already terminated")
terminated = true
Expand All @@ -25,6 +37,13 @@ final class AsyncShell private(inputProvider: InputProvider)(implicit shell: She
}

object AsyncShell {
/**
* Creates an asynchronous shell.
*
* @param inputProvider the [[InputProvider]] for the asynchronous shell
* @param shell the (synchronous) shell to be managed asynchronously by the AsyncShell
* @return an asynchronous shell created with the given parameters
*/
def apply(inputProvider: InputProvider, shell: Shell): AsyncShell = apply(inputProvider)(shell, defaultContext)

private[shell] def apply(inputProvider: InputProvider)(implicit shell: Shell, ec: ExecutionContext): AsyncShell = {
Expand Down
34 changes: 32 additions & 2 deletions src/main/scala/com/nthportal/shell/async/InputAction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,32 @@ package async
import scala.concurrent.{Future, Promise}
import scala.util.Try

/**
* An action requested to be executed by a [[Shell]] by the
* [[InputProvider input source]] of an [[AsyncShell]].
*
* @tparam T the type of the result of the action
*/
trait InputAction[T] {
private val promise = Promise[T]

/**
* Returns a [[Future]] which will contain the result of this action.
*
* @return a Future which will contain the result of this action
*/
def future: Future[T] = promise.future

/**
* Performs this action using a shell, and makes the result
* available in [[future]]. Performs the action defined as [[action]].
*
* @param shell the shell with which to perform the action
*/
private[async] def doAction(implicit shell: Shell): Unit = promise.complete(Try(action(shell)))

/**
* Performs an action using a shell. After completing, the result of the
* action will be available in [[future]].
* Returns the result of an action performed with a [[Shell]].
*
* Note: This method should NOT be called from within [[AsyncShell]];
* use [[doAction]] instead. (It is only accessible outside of the local
Expand All @@ -26,7 +42,21 @@ trait InputAction[T] {
}

object InputAction {
/**
* Creates an input action for tab-completing a line.
*
* @param line the line to be tab-completed
* @return an input action for tab-completing the given line
* @see [[Shell.tabComplete]]
*/
def tabCompletion(line: String): InputAction[ImmutableSeq[String]] = _.tabComplete(line)

/**
* Creates an input action for executing a line.
*
* @param line the line to be executed
* @return an input action for executing the given line
* @see [[Shell.executeLine]]
*/
def execution(line: String): InputAction[Unit] = _.executeLine(line)
}
15 changes: 15 additions & 0 deletions src/main/scala/com/nthportal/shell/async/InputChannel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ package com.nthportal.shell.async

import scala.concurrent.Future

/**
* Something which transmits input between a source and an [[AsyncShell]].
*/
trait InputChannel extends InputProvider {
/**
* Sends an action to be executed asynchronously by an [[AsyncShell]].
*
* Returns a [[Future]] which will contain the result of the action.
* The Future returned SHALL be equivalent to the one returned by
* invoking the [[InputAction.future future]] method of the given
* action.
*
* @param action the action to be executed
* @tparam T the type of the result of the action to be executed
* @return a Future which will contain the result of the action
*/
def sendAction[T](action: InputAction[T]): Future[T]
}
13 changes: 13 additions & 0 deletions src/main/scala/com/nthportal/shell/async/InputProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@ package com.nthportal.shell.async

import scala.concurrent.Future

/**
* Something which provides input (asynchronously) for an [[AsyncShell]].
*/
trait InputProvider {
/**
* Returns a [[Future]] which will contain the next [[InputAction action]]
* to be executed (by an [[AsyncShell]]).
*
* Successive invocations of this method MUST NOT return Futures which will
* be completed with the same action; they MUST return Futures which will be
* completed with successive requested actions.
*
* @return a Future which will contain the next action to be executed
*/
def nextAction: Future[InputAction[_]]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ import com.nthportal.shell.async.SimpleInputChannel.ActionQueue
import scala.collection.immutable.Queue
import scala.concurrent.{ExecutionContext, Future, Promise}

/**
* A simple [[InputChannel]] implementation.
*
* This implementation uses an [[Agent]] which executes in the given
* implicit [[ExecutionContext]].
*
* @param ec the context in which to execute this
*/
final class SimpleInputChannel(implicit ec: ExecutionContext = ExecutionContext.global) extends InputChannel {
private val agent = Agent(ActionQueue(Queue.empty, Queue.empty))

Expand Down

0 comments on commit 41b4716

Please sign in to comment.