Browse Source

Initial version, for FSM 1.6

Frederic G. Marand 17 years ago
parent
commit
b27f682cf6
1 changed files with 136 additions and 0 deletions
  1. 136 0
      Background_Application.php

+ 136 - 0
Background_Application.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ *
+ * This version relies on OSInet FSM >= 1.5
+ *
+ * @copyright  (c) 2007 OSI
+ * @license    Licensed under the CeCILL 2.0
+ * @version    CVS: $Id: Background_Application.php,v 1.1 2007-05-08 21:48:13 marand Exp $
+ * @link       http://wiki.audean.com/
+ * @since      Not applicable yet
+ */
+
+error_reporting(E_ALL|E_STRICT);
+
+/**
+ * Base application class for an application able to perform background work
+ * based on an OSInet FSM (finite state machine).
+ * Concrete implementations should include a constructor defining the
+ * backgroundGoals array along the FSM graph.
+ */
+abstract class Background_Application
+  {
+  /**
+   * Trace operation to stdout
+   *
+   * @var boolean
+   */
+  public $backgroundTrace = FALSE ;
+
+  /**
+   * This is the FSM sequencing the background operation
+   * @var Finite_State_Machine
+   */
+  public $finiteStateMachine;
+
+  /**
+   * event name for background work along the FSM
+   * @var string
+   */
+  public $backgroundPath = NULL;
+
+  /**
+   * gtk::idle_add/idle_remove id
+   * @var int
+   */
+  protected $_backgroundId;
+
+  /**
+   * path/state pairs
+   *
+   * These define the various background trajectories available for background
+   * work within the FSM graph. In each pair, the "path" is the constant event
+   * string applying until a goal is reached, and the "goal" is the terminating
+   * state for the background work.
+   * Sample:
+   * $backgroundGoals = array('up' => 'live', 'down' => 'final');
+   *
+   * @var array
+   */
+  public $backgroundGoals = NULL;
+
+  /**
+   * Perform background work. Must return TRUE to be invoked again.
+   * Do NOT loop inside: this freezes the event loop. Return instead, the
+   * function will be invoked again anyway.
+   *
+   * It has to be public, otherwise gtk can't invoke it after idle_add.
+   *
+   * Returning false disables background work without removing it.
+   *
+   * @throws Exception [if background work is requested without a goals array]
+   * @return boolean
+   */
+  public function backgroundDo()
+    {
+    $ret = TRUE;
+    while(Gtk::events_pending())
+      Gtk::main_iteration();
+
+    if (!is_array($this->backgroundGoals))
+      throw new Exception('Background_Application needs an array of goals to be set before background work can run.');
+
+    $msg = "background work: ";
+    $event = $this->backgroundPath;
+    if (!array_key_exists($event, $this->backgroundGoals))
+      {
+      $msg = "Nothing to do for now. Stop idling";
+      $ret = FALSE;
+      }
+    elseif ($this->finiteStateMachine->get_state() != $this->backgroundGoals[$event])
+      {
+      $msg .= "state " . $this->finiteStateMachine->get_state() . "($event)";
+      $result = $this->finiteStateMachine->apply_event($event);
+      $msg .= "[$result->fsm_return] => $result->fsm_state";
+      if (!empty($result->fsm_action))
+        $msg .= " / $result->fsm_action";
+      }
+    else
+      {
+      $msg .= "End of scheduled work";
+      $this->backgroundStop();
+      $ret = FALSE;
+      }
+
+    if ($this->backgroundTrace)
+      echo $msg . PHP_EOL;
+
+    return $ret;
+    }
+
+  /**
+   * Activate background processing along an event path
+   *
+   * @throws Exception [if background work is requested without a goals array]
+   * @param string $path
+   * @return void
+   */
+  function backgroundStart($path = NULL)
+    {
+    if (!is_array($this->backgroundGoals))
+      throw new Exception('Background_Application needs an array of goals to be set before background work can be started.');
+
+    $this->backgroundPath = $path;
+    $this->_backgroundId = Gtk::idle_add(array($this, 'backgroundDo'));
+    }
+
+  /**
+   * Stop idle processing and remove idle processor
+   * @return void
+   */
+  function backgroundStop()
+    {
+    Gtk::idle_remove($this->_backgroundId);
+    $this->_backgroundId = NULL;
+    }
+  }