[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash/cygnal ACT/ACT.hpp ACT/Change_Log.txt ACT...
From: |
Eric Hughes |
Subject: |
[Gnash-commit] gnash/cygnal ACT/ACT.hpp ACT/Change_Log.txt ACT... |
Date: |
Tue, 10 Jul 2007 14:09:12 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Eric Hughes <eh9> 07/07/10 14:09:12
Modified files:
cygnal/ACT : ACT.hpp Change_Log.txt Cygnal_Instances.cpp
Scheduler.cpp Scheduler.hpp
Scheduling_Queue.hpp Service.cpp Service.hpp
cygnal/ACT/test_support: Action_Tracing.hpp
Listening_Actions.cpp
Listening_Actions.hpp
Simple_Actions.cpp Simple_Actions.hpp
cygnal/ACT/unit_tests: Test_ACT.cpp Test_Scheduler.cpp
Test_Scheduling_Queue.cpp
cygnal/HTTP : HTTP_Behavior.cpp HTTP_Behavior.hpp
HTTP_Parse.cpp HTTP_Parse.hpp URI.cpp URI.hpp
cygnal/HTTP/unit_tests: Test_HTTP.cpp
cygnal/IO : IO_Device.hpp IO_Generator.cpp IO_Generator.hpp
Stream_Consumer.cpp Stream_Consumer.hpp
cygnal/IO/test_support: Null_Device.cpp Null_Device.hpp
Null_Filter.cpp Null_Filter.hpp
String_Device.cpp String_Device.hpp
String_Generator.cpp
String_Generator.hpp
cygnal/IO/unit_tests: Test_Service.cpp
cygnal/Net : Net.hpp Old_Device.hpp socket_device.cpp
socket_device.hpp
cygnal/Net/unit_tests: Test_socket_device.cpp
cygnal/unit_tests: Permutation.hpp Random_Permutation.cpp
Test_Support.hpp
Added files:
cygnal/ACT : ACT.doxygen.txt Handle.cpp Handle.hpp
Listen.T.cpp Listen.hpp Pause_Demon.cpp
Pause_Demon.hpp Scheduler.T.cpp
cygnal/ACT/test_support: Supplied_Service.cpp
Supplied_Service.hpp
cygnal/HTTP : Change_Log.txt
cygnal/Net : Change_Log.txt
cygnal : Aspect.hpp Change_Log.txt mainpage.doxygen.txt
cygnal/doc : Doxyfile
Removed files:
cygnal/ACT : Pause_Service.cpp Pause_Service.hpp
Log message:
ACT module to alpha quality. Two major steps were to get listener
actions and monitors working and to get the aspect templates and white box
testing working.
Performed a few renamings and retypings of fundamental concepts, so
textual changes are extensive.
Wrote a first pass of module documentation, so things aren't completely
opaque.
Added Change_Log.txt in each module; see them for details.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/ACT.hpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Change_Log.txt?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Cygnal_Instances.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduler.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduler.hpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduling_Queue.hpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Service.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Service.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/ACT.doxygen.txt?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Handle.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Handle.hpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Listen.T.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Listen.hpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Pause_Demon.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Pause_Demon.hpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduler.T.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Pause_Service.cpp?cvsroot=gnash&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Pause_Service.hpp?cvsroot=gnash&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Action_Tracing.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Listening_Actions.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Listening_Actions.hpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Simple_Actions.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Simple_Actions.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Supplied_Service.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Supplied_Service.hpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/unit_tests/Test_ACT.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/unit_tests/Test_Scheduler.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/unit_tests/Test_Scheduling_Queue.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/HTTP_Behavior.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/HTTP_Behavior.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/HTTP_Parse.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/HTTP_Parse.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/URI.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/URI.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/Change_Log.txt?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/HTTP/unit_tests/Test_HTTP.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/IO_Device.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/IO_Generator.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/IO_Generator.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/Stream_Consumer.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/Stream_Consumer.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/Null_Device.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/Null_Device.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/Null_Filter.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/Null_Filter.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/String_Device.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/String_Device.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/String_Generator.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/test_support/String_Generator.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/IO/unit_tests/Test_Service.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Net/Net.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Net/Old_Device.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Net/socket_device.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Net/socket_device.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Net/Change_Log.txt?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Net/unit_tests/Test_socket_device.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/unit_tests/Permutation.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/unit_tests/Random_Permutation.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/unit_tests/Test_Support.hpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Aspect.hpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/Change_Log.txt?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/mainpage.doxygen.txt?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/doc/Doxyfile?cvsroot=gnash&rev=1.1
Patches:
Index: ACT/ACT.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/ACT.hpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/ACT.hpp 1 Jul 2007 10:53:50 -0000 1.3
+++ ACT/ACT.hpp 10 Jul 2007 14:09:08 -0000 1.4
@@ -19,7 +19,7 @@
//
/** \file ACT.hpp
- * Asynchronous Computation Task
+ * \brief Asynchronous Computation Task
*/
#pragma once
@@ -31,21 +31,83 @@
using boost::shared_ptr ;
namespace ACT {
-
- class wakeup_listener ;
-
//-------------------------
- /** \enum act_state
- * \brief Generically relevant ACT states.
+ /** \class ACT_State
+ * \brief Generically state of an ACT as a scheduler and other
actions see it.
*
- * There are exactly three generic ACT states.
- * Particular kinds of ACT may refine this set of states, but they
must also preserve the meaning of these three.
- * - Working. Not yet finished.
- * - Completed. Finished normally.
- * - Bad. Finished abnormally.
+ * This enumeration is at the core of the control flow idiom of
the ACT environment.
+ * When a scheduler or another action calls an action, the action
may complete its call before it completes its embodied operation.
+ * The states break down as follows:
+ * - Action is not finished.
+ * In this case, the operation is not yet finished and is
still working.
+ * Further calls to this action will be necessary to get
to a finished state,
+ * which will not happen autonomously.
+ * This state comes in two varieties.
+ * - Ready.
+ * The action spontaneously yielded control.
+ * An immediate call to this action would
immediately continue.
+ * - Waiting.
+ * The action returned because it would block
otherwise.
+ * An immediate call to this action is unlikely to
do anything else.
+ * - Action has finished.
+ * One way or another, this action has finished its
processing.
+ * Further calls to this action do nothing.
+ * - Completed.
+ * The action has finished and its ordinary
postconditions may be relied upon.
+ * - Bad.
+ * The action has entered an abnormal state and
its ordinary postconditions need not be true.
+ * As a rule, actions in this state terminated
early.
+ *
+ * An important aspect of the Waiting state is that an action that
returns this state
+ * has accepted responsibility for setting in motion its
own later wake-up.
+ * The scheduler does not do this, since it doesn't deal in
specifics.
*/
- enum act_state { Working, Completed, Bad } ;
+ class ACT_State
+ {
+ public:
+ /// Symbolic names for the return states of an action.
+ enum state {
+ /// Not finished. Ready to continue immediately.
+ Ready,
+ /// Not finished. Presumed not ready.
+ Would_Block,
+ /// Finished normally.
+ Completed,
+ /// Abnormal termination; now finished.
+ Bad
+ } ;
+
+ private:
+ /// This class is a wrapper around this state.
+ state x ;
+
+ public:
+ /// Ordinary constructor
+ ACT_State( state x ) : x( x ) {} ;
+
+ /// Ordinary assignment
+ ACT_State & operator=( state y ) { x = y ; return * this ; }
+
+ /// Convenience test.
+ inline bool ready() const { return x == Ready ; }
+
+ /// Convenience test.
+ inline bool would_block() const { return x == Would_Block ; }
+
+ /// Convenience test.
+ inline bool completed() const { return x == Completed ; }
+
+ /// Convenience test.
+ inline bool bad() const { return x == Bad ; }
+ /// Test whether state is an unfinished (i.e. still working)
state.
+ /// If true, it's either Ready or Waiting.
+ inline bool working() const { return x <= Would_Block ; }
+ } ;
+
+ //-------------------------
+ // Forward
+ class wakeup_listener ;
//-------------------------
/** \class basic_act
* \brief Base class for specific ACT uses.
@@ -72,7 +134,6 @@
* The basic idea of an ACT splits the keyword "return" into two
different kinds.
* - The ordinary "return", which indicates completion of the task.
* This is represented by the states \c Completed and \c
Bad.
- * This kind of
* - An interruption "yield", which indicates not-yet-completion
of the task.
* This is represented by the state \c Working.
*
@@ -104,47 +165,53 @@
*/
class basic_act {
/// Child classes may access and alter the internal state.
- act_state the_state ;
+ ACT_State the_state ;
protected:
/// Protected constructor for child classes.
basic_act()
- : the_state( Working )
+ : the_state( ACT_State::Ready )
{}
/// Protected setter for subclass implementation.
- inline act_state set_working() { return the_state = Working ; }
+ inline ACT_State set_ready() { return the_state =
ACT_State::Ready ; }
/// Protected setter for subclass implementation.
- inline act_state set_completed() { return the_state = Completed
; }
+ inline ACT_State set_would_block() { return the_state =
ACT_State::Would_Block ; }
/// Protected setter for subclass implementation.
- inline act_state set_bad() { return the_state = Bad ; }
+ inline ACT_State set_completed() { return the_state =
ACT_State::Completed ; }
+
+ /// Protected setter for subclass implementation.
+ inline ACT_State set_bad() { return the_state = ACT_State::Bad
; }
/// Protected arbitrary setter for subclasses that filter.
- inline act_state set_state( act_state x ) { return the_state =
x ; }
+ inline ACT_State set_state( ACT_State x ) { return the_state =
x ; }
public:
///
- inline act_state internal_state() { return the_state ; }
+ inline ACT_State internal_state() { return the_state ; }
///
- inline bool working() const { return the_state == Working ; }
+ inline bool ready() const { return the_state.ready() ; }
///
- inline bool completed() const
- {
- return the_state == Completed ;
- }
+ inline bool would_block() const { return
the_state.would_block() ; }
+
+ /// Return is whether this action is in an unfinished state
(either Ready or Waiting)
+ inline bool working() const { return the_state.working() ; }
+
+ ///
+ inline bool completed() const { return the_state.completed() ; }
///
- inline bool bad() const { return the_state == Bad ; }
+ inline bool bad() const { return the_state.bad() ; }
///
- virtual act_state operator()( void ) =0 ;
+ virtual ACT_State operator()( void ) =0 ;
///
- virtual act_state operator()( wakeup_listener * ) =0 ;
+ virtual ACT_State operator()( wakeup_listener * ) =0 ;
} ;
@@ -161,13 +228,13 @@
* It is reasonable to consider this as an analogue of a
thread body.
*
* \pre
- * - the_state == Working.
+ * - the_state is working.
* (Note: operator(), acting as a facade, ensures
this predicate.)
* \post
* - the_state == Working implies success conditions are
not yet met nor are they yet precluded.
* - return == internal_state().
*/
- virtual act_state run( void ) =0 ;
+ virtual ACT_State run( void ) =0 ;
public:
/** \brief operator() is a facade for the body of an ACT.
@@ -176,13 +243,13 @@
* - the_state == Working implies success conditions are
not yet met nor are they yet precluded.
* - return == internal_state().
*/
- inline act_state operator()( void )
+ inline ACT_State operator()( void )
{
if ( ! working() ) return internal_state() ;
return run() ;
}
- inline act_state operator()( wakeup_listener * )
+ inline ACT_State operator()( wakeup_listener * )
{
return operator()() ;
}
@@ -212,7 +279,7 @@
* wakeup_listener may be called when progress on
the ACT is possible.
*
* \note
- * The postcondition is not a guarantee that a \c
wakeup_listener <b>will</b> be called,
+ * The postcondition is not a guarantee that a
wakeup_listener <b>will</b> be called,
* but rather that a reliance upon the caller that
this instance <b>may</b> call
* the listener (assuming it's not null).
* Certain ACT's may provide such a guarantee that they
will call.
@@ -220,7 +287,7 @@
* when I/O is available.
*
* \note
- * The input parameter \c wakeup_listener may indeed be
zero.
+ * The input parameter wakeup_listener may indeed be zero.
* The intent behind this choice is to enable a scheduler
to forbid an ACT
* from setting up a background poll or
notification.
* Should a scheduler do this, it must assume the
responsibility for checking back later.
@@ -236,19 +303,22 @@
* recently executed" policy for selecting the
next ACT to run.
* Furthermore, these policies might be blended, putting
"slow" operations into
* notification mode and "fast" operations into
direct retry mode.
+ *
+ * \sa
+ * ACT_State: For more detailed information on the meaning
of the return value.
*/
- virtual act_state run( wakeup_listener * ) =0 ;
+ virtual ACT_State run( wakeup_listener * ) =0 ;
public:
///
- inline act_state operator()( wakeup_listener * w )
+ inline ACT_State operator()( wakeup_listener * w )
{
if ( ! working() ) return internal_state() ;
return run( w ) ;
}
/// Convenience zero-parameter operator() ;
- inline act_state operator()() { return operator()( 0 ) ; }
+ inline ACT_State operator()() { return operator()( 0 ) ; }
} ;
//-------------------------
@@ -257,7 +327,7 @@
* Allows hiding 'new' allocation and avoiding defective memory
management.
* Enables passing ACT instances by copying pointers.
*
- * \inv
+ * \invariant
* the_body != 0
*
*/
@@ -288,7 +358,7 @@
/** Proxy for the body's function operator
*/
- act_state operator()( wakeup_listener * x ) {
+ ACT_State operator()( wakeup_listener * x ) {
if ( working() ) {
return the_body -> operator()( x ) ;
}
Index: ACT/Change_Log.txt
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Change_Log.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- ACT/Change_Log.txt 19 Jun 2007 18:52:25 -0000 1.1
+++ ACT/Change_Log.txt 10 Jul 2007 14:09:08 -0000 1.2
@@ -1,3 +1,133 @@
+Change Log for GNU Cygnal, Module ACT
+=====================================
+
+2007-07-10 Eric Hughes <address@hidden>
+ * Pause_Demon.[hc]pp: Renamed from Pause_Service.[hc]pp.
+ * ACT/unit_tests/Test_Scheduler.cpp: Added finished_at_bound() to
scheduler test aspect. (Re-)Wrote a proper pause demon test.
+ * ACT/ACT.doxygen.txt: Added more environment documentation.
+
+2007-07-09 Eric Hughes <address@hidden>
+ * Scheduler.hpp, Scheduler.cpp, Scheduler.T.cpp: Renamed scheduler
category Service to Demon to get rid of a name collision.
+
+2007-07-06 Eric Hughes <address@hidden>
+ * ACT.hpp, Handle.cpp, Listen.T.cpp, Pause_Service.hpp, Scheduler.hpp,
Scheduler.T.cpp, Scheduling_Queue.hpp, Service.hpp,
test_support/Action_Tracing.hpp, test_support/Simple_Actions.hpp,
test_support/Supplied_Service.hpp: Comment cleanup for doxygen.
+ * unit_tests/Test_Scheduler.cpp: Put everything into namespace
ACT_Test. New doxygen comments.
+
+2007-07-05 Eric Hughes <address@hidden>
+ * ../Aspect.hpp: Put declarations within namespace \c aspect.
+ * Cygnal_Instances.cpp, Handle.hpp, Scheduler.hpp, Service.hpp,
test_support/Supplied_Service.hpp, unit_tests/Test_Scheduler.cpp: Added aspect
namespace declarations. Put specializations of null aspects into proper
namespace block.
+
+2007-07-04 Eric Hughes <address@hidden>
+ * Scheduler.T.cpp: Renamed from Scheduler_T.cpp.
+ * Cygnal_Instances.cpp, unit_tests/Test_Scheduler.cpp,
unit_tests/Test_Scheduling_Queue.cpp: Changed file name references.
+ * Listen.hpp: Added documentation.
+ * Listen.cpp: Added documentation. Slightly changed removal loop.
+ * test_support/Listening_Actions.[hc]pp: Moved null constructor to
header. Fixed comments. Removed unused member.
+
+2007-07-04 Eric Hughes <address@hidden>
+ * Listen.hpp, Listen.T.cpp, test_support/Listening_Actions.[hc]pp:
Factored out monitor base class from N_to_completion_Monitor.
+
+2007-07-04 Eric Hughes <address@hidden>
+ * Listen.hpp, Listen.T.cpp, test_support/Listening_Actions.[hc]pp:
Extracted generic listening base class from N_to_completion.
+
+2007-07-03 Eric Hughes <address@hidden>
+ * Scheduler_T.cpp: Renamed from Scheduler_Templated.cpp.
+ * Cygnal_Instances.cpp, unit_tests/Test_Scheduler.cpp: Renamed file
name references.
+
+2007-07-03 Eric Hughes <address@hidden>
+ * Scheduler.hpp, Scheduler_Templated.cpp: Removed execution loop with
bound. Augmented aspect points.
+ * unit_tests/Test_Scheduler.cpp: Wrote test aspect for scheduler with
an execution bound. Converted all test cases to use it.
+
+2007-07-02 Eric Hughes <address@hidden>
+ * Scheduler.hpp: Made Scheduler and wakeup_listener virtual base
classes.
+ * Scheduler.hpp, Scheduling_Queue.hpp: Added template parameters to
wakeup_listener_allocated and Basic_Wakeup_Listener.
+ * Scheduler.hpp, Scheduler_Templated.cpp: Added aspect to
Basic_Scheduler.
+ * Scheduler_Templated.cpp, Scheduler.cpp: Moved wake up listener code
from non-template to template source.
+ * Cygnal_Instances.cpp: Instantiate Basic_Scheduler directly, now that
Scheduler is an interface.
+ * Handle.hpp: Added inline declarations for aspect class.
+ * unit_tests/Test_Scheduler.cpp: Added test aspect for Basic_Scheduler.
+ * unit_tests/Test_Scheduling_Queue.cpp: Added more explicit template
instantiations.
+
+2007-06-30 Eric Hughes <address@hidden>
+ * test_support/Listening_Actions.[hc]pp: Changed follower registry for
listening monitors to use weak pointers.
+
+2007-06-30 Eric Hughes <address@hidden>
+ * Service.[hc]pp: Enabled testing a Generator for completion so that a
Service may complete.
+ * test_support/Supplied_Service.[hc]pp: Added shutdown completion to
Supplied_Service.
+ * unit_tests/Test_Scheduler.cpp: Augmented service test to add shutdown.
+
+2007-06-29 Eric Hughes <address@hidden>
+ * Scheduler.[hc]pp, Scheduler_Templated.cpp: renamed enumeration
identifier Service to action_Service.
+ * Service.[hc]pp: Added aspect to class Service. Base aspect defines
two points, one each at the beginning and end of run().
+ * Supplied_Service.[hc]pp: Used Service aspect to enable tracking of
Service::run().
+
+2007-06-29 Eric Hughes <address@hidden>
+ * Cygnal_Instances.cpp: Included Handle.cpp to get the handle class
instantiated also.
+ * Scheduler.hpp, Scheduler_Templated.hpp: Added Handled as parent class
of Basic_Scheduler.
+ * test_support/Listening_Actions.[hc]pp: Used Handle_Registry_Follower
to enable one monitor per scheduler, rather than one monitor per class.
+ * test_support/Supplied_Service.hpp, unit_tests/Test_Scheduler.cpp:
Added tracker to Supplied_Service constructor.
+
+2007-06-29 Eric Hughes <address@hidden>
+ * ../Aspect.hpp: Cleaned up set_owner definitions and inheritance
idiom. Renamed Aspect_Base to Null_Aspect_Base.
+ * Scheduler.hpp: Added aspect to Basic_Scheduler (as-yet unused). Made
typedef so that external code can just use symbol 'Scheduler'.
+ * Scheduler.cpp, Scheduler_Templated.cpp, Cyngal_Instances.cpp: Split
template member definitions into separate file for inclusion and explicit
instantiation. Avoids multiple definitions of non-template classes.
+ * Handle.hpp, unit_tests/Test_Scheduler.cpp: Split null aspect for
Handled as per new idiom. Cleaned up test aspect definitions accordingly.
+ * Pause_Service.hpp, Service.[ch]pp, test_support/Supplied_Service.hpp,
unit_tests/Test_Scheduler.cpp: Replaced 'Basic_Scheduler' with 'Scheduler'.
+
+2007-06-28 Eric Hughes <address@hidden>
+ * ../Aspect.hpp: Added arity-2 null aspect.
+ * Handle.[hc]pp: Added Marker classes for Handle, etc. to isolate use
of indices.
+ * unit_tests/Test_Scheduler.cpp: Added arity-2 test aspect; updated
test to use markers.
+
+2007-06-27 Eric Hughes <address@hidden>
+ * Handle.[hc]pp: Finished implementation of Handle_Registry_Follower,
including its null aspect. Added new proxies for Vector_with_Handle_Index.
+ * unit_tests/Test_Scheduler.cpp: New unit test for
Handle_Registry_Follower, including a test aspect.
+
+2007-06-27 Eric Hughes <address@hidden>
+ * Handle.hpp: Beginning of an implementation of
Handle_Registry_Follower.
+ * test_support/Simple_Actions.hpp: Removed extraneous (and previous)
definition of class N_to_completion.
+ * Many small comment modification to doxygen comments.
+
+2007-06-27 Eric Hughes <address@hidden>
+ * Handle.[hc]pp, unit_tests/Test_Scheduler.cpp: Renamed Handle_Registry
to Handle_Registry_Leader.
+
+2007-06-26 Eric Hughes <address@hidden>
+ * ../Aspect.hpp: Added Aspect_Has_Access_To_Owner to make owner access
generic.
+ * Handle.hpp: Changed initialization of aspect owner pointer.
+ * unit_tests/Test_Scheduler.cpp: Reworked owner access with new classes.
+
+2007-06-26 Eric Hughes <address@hidden>
+ * Handle.hpp: Renamed Handled::at() to Handled::registry_at().
+
+2007-06-25 Eric Hughes <address@hidden>
+ * ../Aspect.cpp: Changed instantiation order for aspects for technical
reasons involving self-reference in template parameters.
+ * Handle.hpp: Added typedefs for aspect_type and friend declarations.
+ * Handle.cpp: Changed template declarations to match new aspect idiom.
+ * unit_tests/Test_Scheduler.cpp: Completed the white box test for
Handled. It passes.
+
+2007-06-23 Eric Hughes <address@hidden>
+ * Handle.hpp: Added Handle_Registry::remove() and Handle::~Handle().
+ * Handle.cpp: Implemented Handle_Registry::remove().
+ * unit_tests/Test_Scheduler.cpp: Added empty aspect methods for
verification under debugger.
+
+2007-06-23 Eric Hughes <address@hidden>
+ * ../Aspect.hpp: Base template classes to assist writing derivable
aspects.
+ * Handle.hpp: Added aspects to Handle_Registry and Handled.
+ * Handle.cpp: Use two hooks in Handle_Registry::add, which distinguish
between adding a new registry entry and reusing an existing one.
+ * unit_tests/Test_Scheduler.cpp: Added test aspects for Handled and
Handled_Registry. They compile buit don't yet do anything.
+
+2007-06-23 Eric Hughes <address@hidden>
+ * Handle.[hc]pp: New classes for handles, handle indices to vectors,
and handle-registered classes.
+ * unit_tests/Test_Scheduler.cpp: Unit test for handled class
+
+2007-06-22 Eric Hughes <address@hidden>
+ * Scheduler.hpp: Added second sequence number for round-robin
scheduling of background service.
+ * Scheduler.cpp: Changed add_service to use new sequence number and
activate_one_item to use it.
+ * Service.hpp: Renamed old Generator class; wrote new one. Added
shutdown method to Service.
+ * Service.cpp: Rewrote loop of Service::run to use new Generator.
+ * unit_tests/Test_Scheduler.cpp: Unit test for Service.
+ * test_support/Supplied_Service.[hc]pp: New service class with internal
vector of prebuilt actions.
+
2007-06-19 Eric Hughes <address@hidden>
Added a completion check for the test listening action.
All unit tests now fully pass.
Index: ACT/Cygnal_Instances.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Cygnal_Instances.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/Cygnal_Instances.cpp 1 Jul 2007 10:53:50 -0000 1.3
+++ ACT/Cygnal_Instances.cpp 10 Jul 2007 14:09:08 -0000 1.4
@@ -18,7 +18,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/** \file Cygnal_Instance.cpp
+/** \file Cygnal_Instances.cpp
* \brief Template instances of Scheduling_Queue etc. needed for Cygnal.
*
* Because we define the implementations of template functions outside of
its declaration in its header,
@@ -28,10 +28,13 @@
* Separating definition and instantiation alleviates problems with
multiply-defined symbols.
*/
+#include "Handle.cpp"
#include "Scheduling_Queue.cpp"
+#include "Scheduler.T.cpp"
namespace ACT {
- // Explicit template instantiation.
- template Basic_Scheduler::queue_type ;
+ // Explicit template instantiations.
+ template Basic_Scheduler< aspect::Null_Aspect_0 >::queue_type ;
+ template Basic_Scheduler< aspect::Null_Aspect_0 > ;
} // end namespace ACT
Index: ACT/Scheduler.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Scheduler.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/Scheduler.cpp 1 Jul 2007 10:53:51 -0000 1.3
+++ ACT/Scheduler.cpp 10 Jul 2007 14:09:08 -0000 1.4
@@ -37,7 +37,7 @@
case Task :
priority_category = Initial ;
break ;
- case Service :
+ case Demon :
priority_category = Background ;
break ;
default :
@@ -57,123 +57,4 @@
) ;
}
- //--------------------------------------------------
- // wakeup_listener_allocated
- //--------------------------------------------------
- wakeup_listener_allocated::
- wakeup_listener_allocated( size_t x, scheduler_pointer y )
- : the_wakeup_listener( new wakeup_listener( x, y ) ) {}
-
- //--------------------------------------------------
- // wakeup_listener
- //--------------------------------------------------
- void
- wakeup_listener::
- operator()()
- {
- queue_type & the_queue = the_scheduler -> queue() ;
- the_queue.item( permutation_index ).priority_category =
Ordinary ;
- the_queue.reorder( permutation_index ) ;
- }
-
- //--------------------------------------------------
- // Basic_Scheduler
- //--------------------------------------------------
- Basic_Scheduler::
- Basic_Scheduler()
- : operating( true ),
- next_sequence_number( 1 )
- {}
-
- //-------------------------
- void
- Basic_Scheduler::
- reset()
- {
- operating = true ;
- }
-
- //-------------------------
- void
- Basic_Scheduler::
- operator()()
- {
- while ( operating ) {
- activate_one_item() ;
- }
- }
-
- //-------------------------
- void
- Basic_Scheduler::
- operator()( unsigned int activation_bound )
- {
- while ( operating && activation_bound > 0 ) {
- -- activation_bound ;
- activate_one_item() ;
- }
- }
-
- //-------------------------
- void
- Basic_Scheduler::
- add_task( act x )
- {
- item_pointer item = the_queue.push( Basic_Scheduled_Item( x, ++
next_sequence_number ), this ) ;
- }
-
- void
- Basic_Scheduler::
- add_service( act x )
- {
- item_pointer item = the_queue.push( Basic_Scheduled_Item( x, ++
next_sequence_number, Service ), this ) ;
- }
-
- void
- Basic_Scheduler::
- add_critical_service( act )
- {
- }
-
- //-------------------------
- void
- Basic_Scheduler::
- activate_one_item()
- {
- // Note that this operation is not locked.
- // As of this version, this is a single-threaded server.
- if ( the_queue.empty() ) {
- // If the queue is finally empty, we're done.
- operating = false ;
- return ;
- // An alternate behavior would be to wait indefinitely
for another scheduled item.
- // This is an asynchronous scheduler; it doesn't wait.
- // To understand how this scheduler wakes up from
quiescence, look into service actions.
- }
- // Assert the_queue is not empty
-
- queue_type::pointer item = the_queue.top_ptr() ;
- act_state result = item -> the_action(
the_queue.auxiliary_top() -> get() ) ;
- if ( result == Working ) {
- if ( item -> action_type == Task ) {
- // Assert action is not a service
- item -> priority_category = Waiting ;
- the_queue.reorder( item ) ;
- }
- // Note service actions do not re-prioritize right now
- } else {
- the_queue.pop() ;
- // Perhaps we might want to log items gone bad here.
- }
- }
-
- //-------------------------
- bool
- Basic_Scheduler::
- ordinary_tasks_available()
- {
- if ( the_queue.empty() ) return false ;
- return the_queue.top().priority_category <= Ordinary ;
- }
-
} // end namespace ACT
Index: ACT/Scheduler.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Scheduler.hpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/Scheduler.hpp 1 Jul 2007 10:53:51 -0000 1.3
+++ ACT/Scheduler.hpp 10 Jul 2007 14:09:08 -0000 1.4
@@ -25,19 +25,57 @@
#define __Scheduler_hpp__
#include "ACT.hpp"
+#include "Handle.hpp"
#include "Scheduling_Queue.hpp"
#include <boost/optional/optional.hpp>
-
+#include "../Aspect.hpp"
//#include "boost/date_time/posix_time/posix_time.hpp"
+// Declarations within this namespace block intended for a new header file
defining only interfaces
namespace ACT {
+ //-------------------------
+ /** \class Scheduler
+ * \brief Abstract interface to scheduler.
+ */
+ class Scheduler
+ : public Handled< Scheduler >
+ {
+ public:
+ /// Add a task with bounded lifetime.
+ virtual void add_task( act ) =0 ;
+
+ /// Add a service with indefinite lifetime.
+ virtual void add_service( act ) =0 ;
+ ///
+ virtual bool ordinary_tasks_available() =0 ;
+
+ ///
+ Scheduler( Scheduler * that )
+ : Handled< Scheduler >( that )
+ {} ;
+ } ;
+
+ /** \class wakeup_listener
+ * \brief Abstract interface to a function object that wakes up a
listener task that's waiting.
+ */
+ class wakeup_listener
+ {
+ public:
+ /// The listener body.
+ virtual void operator()() =0 ;
+
+ /// Accessor for the scheduler
+ virtual Scheduler * scheduler() const =0 ;
+ } ;
+}
+
+namespace ACT {
//-------------------------
/* Forward declarations for wakeup_listener
*/
struct Basic_Scheduled_Item ;
- class Basic_Scheduler ;
- class wakeup_listener_allocated ;
+ template< template< class > class > class Basic_Scheduler ;
//-------------------------
/** \class wakeup_listener_allocated
@@ -51,11 +89,12 @@
* this allocation strategy has no performance penalty in
the steady state,
* except to the extent that excess memory usage causes
unnecessary swapping.
*/
+ template< class S >
class wakeup_listener_allocated
{
public:
///
- typedef Basic_Scheduler * scheduler_pointer ;
+ typedef S * scheduler_pointer ;
// typedef wakeup_listener::scheduler_pointer scheduler_pointer
;
///
@@ -80,7 +119,7 @@
} ;
//-------------------------
- /** \class wakeup_listener
+ /** \class Basic_Wakeup_Listener
* \brief The 'A' in ACT means 'asynchronous', so in general there
must be a way of notifying
* a scheduler that an inactive ACT, one that has a
pending sub-action, is ready to proceed.
* This class is the interface between a scheduler and such an ACT.
@@ -95,15 +134,17 @@
* The scheduler should encapsulate its own notification receiver,
however structured,
* into a function object of this class, say, by binding a
member function adapter.
*/
- class wakeup_listener
+ template< class S >
+ class Basic_Wakeup_Listener
+ : public wakeup_listener
{
public:
///
- typedef Basic_Scheduler * scheduler_pointer ;
+ typedef S * scheduler_pointer ;
private:
///
- typedef Scheduling_Queue< Basic_Scheduled_Item,
wakeup_listener_allocated > queue_type ;
+ typedef Scheduling_Queue< Basic_Scheduled_Item,
wakeup_listener_allocated< S > > queue_type ;
/// A pointer to the item to reschedule.
size_t permutation_index ;
@@ -119,7 +160,7 @@
inline scheduler_pointer scheduler() const { return
the_scheduler ; }
/// Ordinary constructor used after item is within a scheduling
queue and its storage location is known.
- wakeup_listener( size_t x, scheduler_pointer y )
+ Basic_Wakeup_Listener( size_t x, scheduler_pointer y )
: permutation_index( x ), the_scheduler( y ) {}
} ;
@@ -147,26 +188,35 @@
} ;
//-------------------------
- ///
+ /** \brief Category of actions within Basic_Scheduler.
+ * Distinguishes ordinary tasks from services, which have
different scheduling policies.
+ */
enum Action_Category
{
/// An ordinary task, executed until completed, then discarded.
Task = 0,
- /** A service task, reset if completed, discarded if reset
does not succeed.
+ /** A demon task, never expected to complete, but which may
complete.
*
- * A service executes with background priority in the
scheduling queue.
+ * A demon executes with background priority in the
scheduling queue.
* It may also have its own autonomous processing.
- * The select() call behind the wakeup listener for
network I/O, for example, is a service.
+ * The select() call behind the wakeup listener for
network I/O, for example, is somewhere within a certain demon.
*/
- Service,
+ Demon,
- /** A critical service is one that must be run in order for
the scheduler to run.
+ /** A critical demon is one that must be run in order for
the scheduler to run.
*/
- Critical_Service
+ Critical_Demon
} ;
//-------------------------
+ /** \class Basic_Scheduled_Item
+ * \brief Data within the priority queue proper.
+ * This data is swapped during priority queue operations,
so should remain as small as possible.
+ *
+ * \par Future
+ * It seems that \c the_action, which isn't needed for
ordering, might be able to move to the auxiliary vector.
+ */
struct Basic_Scheduled_Item
{
///
@@ -189,16 +239,28 @@
} ;
//-------------------------
+ /** \class Basic_Scheduler
+ * \brief A basic implementation of a scheduler.
+ *
+ * This may not be the final production version of a scheduler.
+ * Nevertheless, a scheduler which is as simple as possible, but
still works as a scheduler,
+ * should be retained for testing.
+ * In particular, this scheduler does not have a timeout mechanism
to detect stalled actions.
+ * This would be a defect in a production environment.
+ * Such an absence should be retained for the test environment, to
be able to isolate defective actions that stall.
+ */
+ template< template< class > class Aspect = aspect::Null_Aspect_0 >
class Basic_Scheduler
+ : public Scheduler
{
///
- friend wakeup_listener ;
+ friend Basic_Wakeup_Listener< Basic_Scheduler > ;
/// The type of our internal queue.
- typedef Scheduling_Queue< Basic_Scheduled_Item,
wakeup_listener_allocated > queue_type ;
+ typedef Scheduling_Queue< Basic_Scheduled_Item,
wakeup_listener_allocated< Basic_Scheduler > > queue_type ;
///
- typedef queue_type::pointer item_pointer ;
+ typedef typename queue_type::pointer item_pointer ;
/// Activate the next action once.
void activate_one_item() ;
@@ -213,11 +275,20 @@
inline queue_type & queue() { return the_queue ; }
/// Increasing sequence numbers upon scheduling implements a
kind of LRU activation policy.
- unsigned int next_sequence_number ;
+ unsigned int next_task_sequence_number ;
+
+ /// A separate sequence for services implements round-robin
activation.
+ unsigned int next_service_sequence_number ;
+
+ ///
+ typedef Aspect< Basic_Scheduler > aspect_type ;
+
+ ///
+ aspect_type aspect ;
public:
/// Default constructor is private to enforce singleton
- Basic_Scheduler() ;
+ Basic_Scheduler( aspect_type aspect = aspect_type() ) ;
/// Add an ordinary task into the scheduling queue.
void add_task( act ) ;
@@ -231,9 +302,6 @@
/// The main execution loop.
void operator()() ;
- /// The main execution loop with an activation bound.
- void operator()( unsigned int ) ;
-
///
bool ordinary_tasks_available() ;
@@ -244,6 +312,39 @@
void reset() ;
} ;
+ //-------------------------
+ /** \class Basic_Scheduler_Null_Aspect
+ * \brief Base class for aspects of \c Basic_Scheduler.
+ */
+ class Basic_Scheduler_Null_Aspect
+ {
+ public:
+ /// Guard must be true in order for execution loop to continue.
+ inline bool run_guard() { return true ; }
+
+ /// Called before any execution starts.
+ inline void run_begin() {}
+
+ /// Called after execution stops through internal means.
+ inline void run_end_ordinary() {}
+
+ /// Called if execution stop because of guard failure.
+ inline void run_end_guard_violation() {}
+ } ;
+
+ //-------------------------
} // end namespace ACT
+namespace aspect {
+ //-------------------------
+ /** \brief Default null aspect for Basic_Scheduler.
+ */
+ template<>
+ class Null_Aspect_0< ACT::Basic_Scheduler< Null_Aspect_0 > >
+ : public Null_Aspect_Base< ACT::Basic_Scheduler< Null_Aspect_0
> >,
+ public ACT::Basic_Scheduler_Null_Aspect
+ {} ;
+
+}
+
#endif
Index: ACT/Scheduling_Queue.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Scheduling_Queue.hpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/Scheduling_Queue.hpp 1 Jul 2007 10:53:51 -0000 1.3
+++ ACT/Scheduling_Queue.hpp 10 Jul 2007 14:09:08 -0000 1.4
@@ -76,7 +76,7 @@
//-------------------------
- /** \class Scheduled_Item
+ /** \class Auxiliary_Item
* \brief The full data that goes into the scheduling queue.
* It includes the underlying item plus extra housekeeping
information.
*/
@@ -99,6 +99,9 @@
//-------------------------
/** \class Scheduled_Item_Pointer
+ * \brief A pointer into an item within a scheduling queue.
+ * Since items within the underlying container of a queue move
around,
+ * a pointer is necessary to track such motion and provide
a stable reference for outsiders.
*/
template< class T, class Aux >
class Scheduled_Item_Pointer
@@ -149,7 +152,7 @@
{
// friends
template< class T, class Aux > friend class
Scheduled_Item_Pointer ;
- friend class wakeup_listener ;
+ template< class S > friend class Basic_Wakeup_Listener ;
/// The main queue for scheduled items.
std::vector< Scheduled_Item< T > > the_queue ;
Index: ACT/Service.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Service.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- ACT/Service.cpp 1 Jul 2007 10:53:51 -0000 1.2
+++ ACT/Service.cpp 10 Jul 2007 14:09:08 -0000 1.3
@@ -26,42 +26,53 @@
//-------------------------
/* \par Implementation
*/
- Service::
- Service( Generator & x, Basic_Scheduler & z )
+ template< template< class > class Aspect >
+ Service< Aspect >::
+ Service( Generator & x, Scheduler & z, aspect_type aspect )
: the_generator( x ),
- our_scheduler( z )
- {}
+ our_scheduler( z ),
+ aspect( aspect )
+ {
+ aspect.set_owner( this ) ;
+ }
//-------------------------
/* \par Implementation
*/
- act_state
- Service::
+ template< template< class > class Aspect >
+ ACT_State
+ Service< Aspect >::
run( wakeup_listener * w )
{
+ aspect.log_run_begin() ;
// We use a loop rather than a single pass because the
generator may have multiple pending actions ready for us.
// We'd get a similar result with just a single pass.
// The difference is that using a single pass here would cause
loop overhead in the scheduler.
// It's more efficient to do ordinary cycling here.
//
+ bool task_added( false ) ;
while ( true ) {
- the_generator( w ) ;
- if ( the_generator.working() ) return ACT::Working ;
- if ( the_generator.bad() ) return set_bad() ;
- // Assert the_generator.completed()
-
- act x( the_generator.result() ) ;
+ try {
+ shared_ptr< basic_act > x(
the_generator.next_action( w ) ) ;
+ if ( ! x ) {
+ if ( the_generator.completed() && !
task_added ) {
+ aspect.log_run_end() ;
+ return set_completed() ;
+ } else {
+ aspect.log_run_end() ;
+ return set_ready() ;
+ }
+ }
our_scheduler.add_task( x ) ;
-
+ task_added = true ;
+ } catch ( ... ) {
+ aspect.log_run_end() ;
+ return set_bad() ;
+ }
// If, in the future, ours scheduler might be
unavailable for adding something new to the queue.
// Such unavailability would (hopefully) be temporary.
// It might arise, for example, from a non-blocking
queue operation that just wasn't ready just yet.
- // What we would do in that case is simply to return,
avoiding the following reset.
- // Upon next invocation, the result won't have changed
and we can just try again.
-
- // Reset the generator and re-run the action.
- the_generator.reset() ;
+ // What we would do in that case is to save our
action-pending state and introduce at the next invocation.
}
}
-
}
Index: ACT/Service.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Service.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- ACT/Service.hpp 1 Jul 2007 10:53:51 -0000 1.2
+++ ACT/Service.hpp 10 Jul 2007 14:09:08 -0000 1.3
@@ -18,7 +18,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/// \file Server.hpp
+/// \file Service.hpp
#pragma once
#ifndef __Service_hpp__
@@ -26,9 +26,12 @@
#include "ACT.hpp"
#include "Scheduler.hpp"
+#include "Aspect.hpp"
namespace ACT {
- class Generator
+ //-------------------------
+ /// \brief still used in IO, for now.
+ class Obsolete_Generator
: public ACT::autonomous_act
{
public:
@@ -39,6 +42,59 @@
} ;
//-------------------------
+ /** \class Generator
+ * \brief A generator of actions, in bursts, used to feed a
Service.
+ * This class is a base for service implementations.
+ *
+ */
+ class Generator
+ {
+ public:
+ /** The parameter is necessary for when a Service must
suspend itself waiting for external events.
+ * The central example is a socket listener, which
generates new connections, each encapsulated in a protocol behavior.
+ *
+ * \post
+ * - return is zero implies no more action is available at
the present time. Ask again later.
+ */
+ virtual shared_ptr< basic_act > next_action( wakeup_listener *
) =0 ;
+
+ /**
+ * \post
+ * - return is true
+ * implies return value of next_action
will always be zero
+ * and implies return value of completed will
always be true
+ */
+ virtual bool completed() { return false ; }
+
+ /** The meaning of this shut-down routine are weak and lazy,
rather than strong and immediate.
+ * The only requirement is that the number of ready
actions monotonically decrease with each call to \c next_action.
+ * Conceptually, there must be a counter of ready actions.
+ * It must decrease this count by at least one with each
call to \c next_action.
+ *
+ * These ready actions may be implicit or explicit.
+ * Explicit action are those, say, waiting in a queue,
already constructed and ready to go.
+ * Generically, all generators will contain these kind of
explict actions.
+ *
+ * A central example of an implicit action is the set of
pending connections on a listening socket.
+ * The OS has established a connection, so there's some
potential action on that connection.
+ * Whatever that action is matter nothing to this base
class.
+ * What does matter is that after shutdown, that the
listening socket be closed,
+ * or at least put in a state to reject
connections, thereby not generating any new actions.
+ *
+ * The weak requirement of this shutdown does not preclude
immediate termination.
+ * The requirement is that the count of available actions
decrease by at least one, not by exactly one.
+ * A service that wishes to hang up immediately, simply
ending, may do so.
+ * Indeed, a particular implementation class might well
have configurable shutdown behavior,
+ * depending on whether the desired shutdown is
graceful or abrupt.
+ *
+ * Implementing classes should document their approach to
shutdown.
+ * This will avoid incorrect expectations about behavior,
+ * which expectations might develop out of habit
or idiom, rather than out of requirement.
+ */
+ virtual void shutdown() =0 ;
+ } ;
+
+ //-------------------------
/** \class Service
* \brief A service is a persistent action whose result to create
new actions and to schedule them for execution.
*
@@ -51,22 +107,61 @@
*
* A service, in addition, is "always working".
* It only completes when it needs to shut down, either from an
internal failure or by external command.
+ *
+ * WARNING: A service must not both schedule a new action and
return \c Completed in the same activation.
+ * This restriction simplifies implementation of the scheduler,
which then doesn't need to removed
+ * a completed service action from within the middle of
the scheduling queue.
+ * When a service schedules no new actions, it remains at the top
of the priority queue,
+ * from where it can be removed like any other task.
*/
+ template< template< class > class Aspect = aspect::Null_Aspect_0 >
class Service
: public autonomous_act
{
- Basic_Scheduler & our_scheduler ;
+ public:
+ typedef Aspect< Service > aspect_type ;
+
+ private:
+ /// Aspect instance.
+ aspect_type aspect ;
+
+ Scheduler & our_scheduler ;
Generator & the_generator ;
public:
///
- Service( Generator & x, Basic_Scheduler & z ) ;
+ Service( Generator & x, Scheduler & z, aspect_type aspect =
aspect_type() ) ;
+
+ ///
+ ACT_State run( wakeup_listener * ) ;
///
- act_state run( wakeup_listener * ) ;
+ inline void shutdown() { the_generator.shutdown() ; }
+ } ;
+
+ //-------------------------
+ /** \class Service_Null_Aspect
+ * \brief Null aspect for \c Service
+ */
+ class Service_Null_Aspect
+ {
+ public:
+ void log_run_begin() {} ;
+ void log_run_end() {} ;
} ;
//-------------------------
} // end namespace ACT
+namespace aspect {
+ //-------------------------
+ /** \brief Default null aspect for \c Service.
+ */
+ template<>
+ class Null_Aspect_0< ACT::Service< Null_Aspect_0 > >
+ : public ACT::Service_Null_Aspect,
+ public Null_Aspect_Base< ACT::Service< Null_Aspect_0 > >
+ {} ;
+}
+
#endif
\ No newline at end of file
Index: ACT/test_support/Action_Tracing.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/test_support/Action_Tracing.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- ACT/test_support/Action_Tracing.hpp 1 Jul 2007 10:53:51 -0000 1.2
+++ ACT/test_support/Action_Tracing.hpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -30,6 +30,7 @@
//-------------------------
/** \class execution_trace
+ * \brief A wrapper around a string to hold a logging trace of an
execution pathway.
*/
class execution_trace
{
Index: ACT/test_support/Listening_Actions.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/test_support/Listening_Actions.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/test_support/Listening_Actions.cpp 1 Jul 2007 10:53:51 -0000
1.3
+++ ACT/test_support/Listening_Actions.cpp 10 Jul 2007 14:09:09 -0000
1.4
@@ -24,53 +24,33 @@
#include "Listening_Actions.hpp"
#include "ACT/Scheduler.hpp"
+// Required to obtain instantiation of template base classes
+#include "ACT/Listen.T.cpp"
+
namespace ACT {
//--------------------------------------------------
// N_to_completion_Monitor
//--------------------------------------------------
- std::vector< wakeup_listener::scheduler_pointer >
N_to_completion_Monitor::schedulers ;
-
- N_to_completion_Monitor::
- N_to_completion_Monitor()
- : listeners( 0 )
- {}
-
void
N_to_completion_Monitor::
add_wakeup_item( N_to_completion *, wakeup_listener * w )
{
- // Assert this instance is registered in the scheduler and will
eventually run.
- // Note: as of this writing, there's no way for an object to
register itself with the scheduler.
- // Some other object must do so.
- // It's not yet clear whether this is good or not.
-
- // We ignore the N_to_completion pointer, since in this
test action,
+ // We ignore the N_to_completion pointer, since, for the
purposes of the present test action,
// we consider any background action always ready
for wakeup after one cycle of quiescence.
- listeners.push_back( w ) ;
+
+ Parent::add_ready_listener_task( w ) ;
}
- act_state
+ ACT_State
N_to_completion_Monitor::
run()
{
- if ( listeners.empty() ) {
- // This monitor is no longer necessary, since there's
nothing to wake up.
- // Therefore we return complete and let the scheduler
remove this instance.
- return Completed ;
- }
- while ( ! listeners.empty() ) {
- ( * listeners.back() )() ;
- listeners.pop_back() ;
- }
- return Working ;
+ return Parent::wake_up_ready_tasks() ;
}
//--------------------------------------------------
// N_to_completion
//--------------------------------------------------
- boost::shared_ptr< N_to_completion_Monitor >
N_to_completion::the_monitor ;
-
- //-------------------------
N_to_completion::
N_to_completion( unsigned int n, tracking_function * f )
: total_number_of_activations( n ),
@@ -79,7 +59,7 @@
{}
//-------------------------
- act_state
+ ACT_State
N_to_completion::
run( wakeup_listener * w )
{
@@ -88,8 +68,8 @@
if ( number_of_activations_left == 0 ) return set_completed() ;
// Assert we're not done yet.
// Register with our monitor before returning.
- register_for_wakeup( w ) ;
- return Working ;
+ register_for_wakeup( this, w ) ;
+ return set_would_block() ; ;
}
//-------------------------
@@ -98,22 +78,15 @@
reset()
{
number_of_activations_left = total_number_of_activations ;
- set_working() ;
- }
-
- //-------------------------
- void
- N_to_completion::
- register_for_wakeup( wakeup_listener * w )
- {
- if ( w == 0 ) return ;
- if ( the_monitor.get() == 0 ) {
- the_monitor = shared_ptr< monitor_type >( new
monitor_type() ) ;
- w -> scheduler() -> add_service( act( the_monitor ) ) ;
- }
- // Assert monitor exists
- the_monitor -> add_wakeup_item( this, w ) ;
+ set_ready() ;
}
//-------------------------
} // end namespace ACT
+
+//-------------------------
+// Instantiate an instance of Handle_Registry_Follower as needed for
N_to_Completion
+#include "ACT/Handle.cpp"
+namespace ACT {
+ template Handle_Registry_Follower< shared_ptr< N_to_completion_Monitor
>, Scheduler > ;
+}
\ No newline at end of file
Index: ACT/test_support/Listening_Actions.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/test_support/Listening_Actions.hpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/test_support/Listening_Actions.hpp 1 Jul 2007 10:53:51 -0000
1.3
+++ ACT/test_support/Listening_Actions.hpp 10 Jul 2007 14:09:09 -0000
1.4
@@ -24,36 +24,34 @@
#ifndef __Listening_Actions_hpp__
#define __Listening_Actions_hpp__
-#include "ACT/Scheduler.hpp"
+#include "ACT/Listen.hpp"
#include "Action_Tracing.hpp"
-#include <boost/optional.hpp>
-#include <vector>
namespace ACT {
- // Forward declaration
+ // Forward
class N_to_completion ;
//-------------------------
/** \class N_to_completion_Monitor
* \brief A monitor for N_to_completion.
+ *
+ * Note that this class derives from \c simple_act, rather than \c
autonomous_act.
+ * The monitor that wakes up other actions does not itself sleep.
*/
class N_to_completion_Monitor
- : public simple_act
+ : public Basic_Listen_Monitor< N_to_completion >
{
- /// A vector of schedulers
- static std::vector< wakeup_listener::scheduler_pointer >
schedulers ;
+ /// Type of parent monitor class, called often in implementation
+ typedef Basic_Listen_Monitor< N_to_completion > Parent ;
- std::vector< wakeup_listener * > listeners ;
-
- act_state run() ;
+ /// Action body
+ ACT_State run() ;
public:
/// Default constructor.
- N_to_completion_Monitor() ;
-
- /// Query whether there are any actions registered for wakeup.
- inline bool empty() { return listeners.empty() ; }
+ N_to_completion_Monitor() {} ;
+ /// Implementation of specific wake-up preparation
void add_wakeup_item( N_to_completion *, wakeup_listener * ) ;
} ;
@@ -62,14 +60,8 @@
* \brief Action that completes after N activations.
*/
class N_to_completion
- : public autonomous_act
+ : public Basic_Listening_Task< N_to_completion,
N_to_completion_Monitor >
{
- /// The monitor type for these actions to register with.
- typedef N_to_completion_Monitor monitor_type ;
-
- ///
- static shared_ptr< monitor_type > the_monitor ;
-
/// Tracking
std::auto_ptr< tracking_function > tracker ;
@@ -80,19 +72,16 @@
unsigned int total_number_of_activations ;
/// Action body, proxied by operator()
- act_state run( wakeup_listener * ) ;
-
- /// Register an action for wakeup
- void register_for_wakeup( wakeup_listener * ) ;
+ ACT_State run( wakeup_listener * ) ;
public:
///
N_to_completion( unsigned int n, tracking_function * = 0 ) ;
void reset() ;
-
} ;
+ //-------------------------
} // end namespace ACT
#endif
Index: ACT/test_support/Simple_Actions.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/test_support/Simple_Actions.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- ACT/test_support/Simple_Actions.cpp 1 Jul 2007 10:53:52 -0000 1.2
+++ ACT/test_support/Simple_Actions.cpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -27,7 +27,7 @@
//--------------------------------------------------
// simple_action
//--------------------------------------------------
- act_state
+ ACT_State
single_action::
run()
{
@@ -38,12 +38,12 @@
//--------------------------------------------------
// no_action
//--------------------------------------------------
- act_state
+ ACT_State
no_action::
run()
{
if ( tracker.get() != 0 ) ( * tracker )( "" ) ;
- return Completed ;
+ return set_completed() ;
}
} // end namespace ACT
Index: ACT/test_support/Simple_Actions.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/test_support/Simple_Actions.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- ACT/test_support/Simple_Actions.hpp 1 Jul 2007 10:53:52 -0000 1.2
+++ ACT/test_support/Simple_Actions.hpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -28,35 +28,10 @@
#include "Action_Tracing.hpp"
namespace ACT {
- //-------------------------
- /** \class N_to_completion
- * \brief Action that completes after N activations.
- */
- class N_to_completion
- : public autonomous_act
- {
- /// Tracking
- std::auto_ptr< tracking_function > tracker ;
-
- ///
- unsigned int number_of_activations_left ;
-
- ///
- unsigned int total_number_of_activations ;
-
- ///
- act_state run( wakeup_listener * ) ;
-
- public:
- ///
- N_to_completion( unsigned int n, tracking_function * = 0 ) ;
-
- void reset() ;
-
- } ;
//-------------------------
/** \class single_action
+ * \brief An action that always completes at its first activation.
*/
class single_action
: public simple_act
@@ -65,7 +40,7 @@
std::auto_ptr< tracking_function > tracker ;
/// Action body
- act_state run() ;
+ ACT_State run() ;
public:
///
single_action( tracking_function * x = 0 )
@@ -88,7 +63,7 @@
std::auto_ptr< tracking_function > tracker ;
/// Action body does very little.
- act_state run() ;
+ ACT_State run() ;
public:
/// Ordinary constructor.
Index: ACT/unit_tests/Test_ACT.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/unit_tests/Test_ACT.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- ACT/unit_tests/Test_ACT.cpp 1 Jul 2007 10:53:52 -0000 1.2
+++ ACT/unit_tests/Test_ACT.cpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -26,6 +26,7 @@
#include "../ACT.hpp"
#include "ACT/test_support/Simple_Actions.hpp"
+#include "ACT/test_support/Listening_Actions.hpp"
using namespace ACT ;
@@ -47,17 +48,17 @@
: number_of_calls( 0 )
{} ;
- act_state run( wakeup_listener * )
+ ACT_State run( wakeup_listener * )
{
switch ( number_of_calls ) {
case 0 :
number_of_calls = 1 ;
- return ACT::Working ;
+ return internal_state() ;
case 1 :
number_of_calls = 2 ;
return set_completed() ;
- case 2 :
- return ACT::Completed ;
+ // Note:
+ // case 2 should never be called, since the guard for
calling run requires that the action still be working
}
throw std::exception( "Not Reached" ) ;
}
Index: ACT/unit_tests/Test_Scheduler.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/unit_tests/Test_Scheduler.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/unit_tests/Test_Scheduler.cpp 1 Jul 2007 10:53:52 -0000 1.3
+++ ACT/unit_tests/Test_Scheduler.cpp 10 Jul 2007 14:09:09 -0000 1.4
@@ -24,14 +24,250 @@
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>
-#include "ACT/test_support/Simple_Actions.hpp"
#include "ACT/Scheduler.hpp"
+#include "ACT/test_support/Simple_Actions.hpp"
+#include "ACT/test_support/Listening_Actions.hpp"
+#include "ACT/test_support/Supplied_Service.hpp"
+#include "ACT/Pause_Demon.hpp"
+
+// Include implementations for explicit instantiation.
+#include "ACT/Handle.cpp"
+#include "ACT/Scheduler.T.cpp"
+#include "ACT/Scheduling_Queue.cpp"
+
+namespace ACT_Test {
+ //--------------------------------------------------
+ // White box test of Handle using aspects.
+ //--------------------------------------------------
+ using namespace ACT ;
+
+ //---------------
+ // This is the template definition of the base aspect class.
+ // Specializations of this class provide the actual aspect classes
compiled in to the classes under test.
+
+ /// \brief Generic template declaration to be specialized for
particular class aspects.
+ template< class, class > class test_aspect {} ;
+ /// \brief Generic template declaration to be specialized for
particular class aspects.
+ template< class, class, class > class test_aspect_2 {} ;
+
+ //---------------
+ /// \brief Test aspect for Handle_Registry_Leader
+ template< class T >
+ class test_aspect< T, Handle_Registry_Leader< T, test_aspect > >
+ : public aspect::Null_Aspect_1< T, Handle_Registry_Leader< T,
aspect::Null_Aspect_1 > >
+ {
+ // We need the execution trace in this class because it's
constructed statically.
+ // If we had two static classes that required a common trace,
we'd have to use a third class, a singleton, to put this in.
+ execution_trace tr ;
-using namespace ACT ;
+ public:
+ execution_trace & trace() { return tr ; }
+ std::string result() const { return tr.result() ; }
+
+ void add_in_new_place() { tr.add( "N" ) ; }
+ void add_in_old_place() { tr.add( "O" ) ; }
+ } ;
+
+ //---------------
+ /// \brief Test aspect for Handle_Registry_Follower.
+ template< class T, class Leader >
+ class test_aspect_2< T, Leader, Handle_Registry_Follower< T, Leader,
test_aspect_2 > >
+ : public aspect::Null_Aspect_2< T, Leader,
Handle_Registry_Follower< T, Leader, aspect::Null_Aspect_2 > >
+ {
+ // See reason above for why the execution trace is here
+ execution_trace tr ;
+ public:
+ execution_trace & trace() { return tr ; }
+ std::string result() const { return tr.result() ; }
+
+ void access_from_existing_slot() { tr.add( "A" ) ; }
+ void enlarge_size_of_vector() { tr.add( "X" ) ; }
+ } ;
+
+ //---------------
+ // Forward
+ class test ;
+ //---------------
+ /// \brief Test aspect for Handled.
+ template< class T >
+ class test_aspect< T, Handled< T, test_aspect > >
+ : public Null_Aspect_Handled< T >,
+ public aspect::Aspect_Has_Access_To_Owner< Handled< T,
test_aspect > >
+ {
+ // The explicit namespace qualification distinguishes the
generic declaration from this specialization.
+ typedef Handled< test, ACT_Test::test_aspect > owner_type ;
+
+ public:
+ std::string result() const { return owner() ->
our_registry.aspect.result() ; }
+ } ;
+
+ //---------------
+ /// \brief A test class for \c Handled, deriving from it in order to
exercise it.
+ class test
+ : public Handled< test, test_aspect >
+ {
+ typedef Handled< test, test_aspect > Handled_Base ;
+ public:
+ test() : Handled_Base( this ) {}
+
+ std::string result() const { return aspect.result() ; }
+ } ;
+
+ //---------------
+ BOOST_AUTO_UNIT_TEST( handle_one )
+ {
+ // We declare variables within blocks to invoke their
destructors.
+ {
+ test x ;
+ BOOST_CHECK( test::registry_at( x.handle() ) == & x ) ;
+ BOOST_CHECK( x.result() == "N" ) ;
+ }
+ // The second time, there should be an existing entry in the
free list to allocate from
+ {
+ test x ;
+ BOOST_CHECK( test::registry_at( x.handle() ) == & x ) ;
+ BOOST_CHECK( x.result() == "NO" ) ;
+ }
+ {
+ test x ;
+ BOOST_CHECK( test::registry_at( x.handle() ) == & x ) ;
+ BOOST_CHECK( x.result() == "NOO" ) ;
+ // Another object after the previous test.
+ test y ;
+ BOOST_CHECK( test::registry_at( y.handle() ) == & y ) ;
+ BOOST_CHECK( y.result() == "NOON" ) ;
+ // Since the execution trace should be in a common
class registry, results from both objects should match.
+ BOOST_CHECK( y.result() == x.result() ) ;
+ }
+ }
+
+ //---------------
+ BOOST_AUTO_UNIT_TEST( handle_two )
+ {
+ test x ;
+ Handle_Registry_Follower< int, test, test_aspect_2 > follower ;
+ std::string found( follower.aspect.result() ) ;
+ std::string expected( "" ) ;
+ BOOST_CHECK( found == "" ) ;
+
+ follower[ x.handle() ] = 1 ;
+ found = follower.aspect.result() ;
+ expected = "XA" ; // Expand follower registry,
then add
+ BOOST_CHECK_MESSAGE( found == expected,
+ "Found result " << found << ". Expected result " <<
expected << "." ) ;
+
+ test y ;
+ follower[ y.handle() ] = 2 ;
+ found = follower.aspect.result() ;
+ expected = "XAXA" ; // Expand again, then add
+ BOOST_CHECK_MESSAGE( found == expected,
+ "Found result " << found << ". Expected result " <<
expected << "." ) ;
+
+ x.~test() ; // invoke destructor to free up
existing handle
+ test z ; // should issue the handle that 'x' had.
+ follower[ z.handle() ] = 3 ;
+ found = follower.aspect.result() ;
+ expected = "XAXAA" ; // No expansion this time, just
add
+ BOOST_CHECK_MESSAGE( found == expected,
+ "Found result " << found << ". Expected result " <<
expected << "." ) ;
+ }
+
+ //--------------------------------------------------
+ // Basic exercises for the scheduler.
+ //--------------------------------------------------
+
+ /// \brief Body of test aspect for \c Basic_Scheduler; aspect itself is
a pointer to this class.
+ class scheduler_aspect_body
+ {
+ size_t execution_count ;
+ size_t execution_bound ;
+ public:
+ scheduler_aspect_body()
+ : execution_bound( 0 ) {}
+
+ void run_begin() { execution_count = 0 ; }
+
+ bool run_guard()
+ {
+ if ( execution_count >= execution_bound ) return false ;
+ ++ execution_count ;
+ return true ;
+ }
+
+ void set_execution_bound( size_t n ) { execution_bound = n ; }
+
+ bool finished_within_bound() { return execution_count <=
execution_bound ; }
+
+ bool finished_at_bound() { return execution_count ==
execution_bound ; }
+
+ } ;
+
+ template< class Owner > class scheduler_aspect ;
+
+ /// \brief test aspect for \c Basic_Scheduler
+ template<>
+ class scheduler_aspect< Basic_Scheduler< scheduler_aspect > >
+ : public Basic_Scheduler_Null_Aspect,
+ public aspect::Aspect_Has_Access_To_Owner< Basic_Scheduler<
scheduler_aspect > >
+ {
+ scheduler_aspect_body * body ;
+
+ public:
+ scheduler_aspect()
+ : body( 0 ) {}
+
+ scheduler_aspect( scheduler_aspect_body * b )
+ : body( b ) {}
+
+ void run_begin() { if ( body ) body -> run_begin() ; }
+
+ bool run_guard() { return ( body ) ? body -> run_guard() : true
; }
+
+ void set_execution_bound( size_t n ) { if ( body ) body ->
set_execution_bound( n ) ; }
+
+ bool finished_within_bound() { return ( body ) ? body ->
finished_within_bound() : false ; }
+
+ bool finished_at_bound() { return ( body ) ? body ->
finished_at_bound() : false ; }
+
+ } ;
+
+ typedef scheduler_aspect< Basic_Scheduler< scheduler_aspect > >
Test_Scheduler_Aspect ;
+ typedef Basic_Scheduler< scheduler_aspect > Test_Scheduler ;
+
+ // Explicit instantiation of our Test_Scheduler
+ template Test_Scheduler ;
+
+ //--------------------------------------------------
+ // This test checks that the execution guard functions correctly to
limit the total number of execution passes.
+ BOOST_AUTO_UNIT_TEST( guard_functions )
+ {
+ scheduler_aspect_body a ;
+ Test_Scheduler b = Test_Scheduler( Test_Scheduler_Aspect( & a )
) ;
+
+ /* N_to_completion( k ) causes the execution of '2k' actions:
+ * - 'k' actions of the N_to_completion task
+ * - 'k' actions of the listening monitor service.
+ * N_to_completion( 6 ) causes 12 action invocations.
+ * We run them 4 at a time.
+ * After the last one, the queue should be empty.
+ */
+ b.add_task( act( new N_to_completion( 6, 0 ) ) ) ;
+ a.set_execution_bound( 4 ) ;
+ b() ;
+ BOOST_CHECK( a.finished_within_bound() ) ;
+ BOOST_CHECK( ! b.empty() ) ;
+ b() ;
+ BOOST_CHECK( a.finished_within_bound() ) ;
+ BOOST_CHECK( ! b.empty() ) ;
+ b() ;
+ BOOST_CHECK( a.finished_at_bound() ) ;
+ BOOST_CHECK( b.empty() ) ;
+ }
-BOOST_AUTO_UNIT_TEST( null )
-{
- Basic_Scheduler b ;
+ BOOST_AUTO_UNIT_TEST( some_single_actions )
+ {
+ scheduler_aspect_body a ;
+ Test_Scheduler b = Test_Scheduler( Test_Scheduler_Aspect( & a )
) ;
execution_trace tr ;
b.add_task( act( new no_action( new simple_tracker( tr, "N" ) ) ) ) ;
@@ -39,40 +275,75 @@
b.add_task( act( new single_action( new simple_tracker( tr, "B" ) ) ) )
;
b.add_task( act( new single_action( new simple_tracker( tr, "C" ) ) ) )
;
- b( 100 ) ;
+ a.set_execution_bound( 100 ) ;
+ b() ;
std::string expected( "ABC" ) ;
BOOST_CHECK_MESSAGE( tr.result() == expected,
"Found result " << tr.result() << ". Expected result " <<
expected << "." ) ;
+ BOOST_CHECK( a.finished_within_bound() ) ;
BOOST_CHECK( b.empty() ) ;
-}
+ }
-BOOST_AUTO_UNIT_TEST( act_n_interleaved )
-{
- Basic_Scheduler b ;
- BOOST_REQUIRE( b.empty() ) ;
+ BOOST_AUTO_UNIT_TEST( act_n_interleaved )
+ {
+ scheduler_aspect_body a ;
+ Test_Scheduler b = Test_Scheduler( Test_Scheduler_Aspect( & a )
) ;
execution_trace tr ;
b.add_task( act( new N_to_completion( 2, new simple_tracker( tr, "A" )
) ) ) ;
b.add_task( act( new N_to_completion( 3, new simple_tracker( tr, "B" )
) ) ) ;
b.add_task( act( new N_to_completion( 5, new simple_tracker( tr, "C" )
) ) ) ;
- b( 100 ) ;
+ a.set_execution_bound( 100 ) ;
+ b() ;
std::string expected( "ABCABCBCCC" ) ;
BOOST_CHECK_MESSAGE( tr.result() == expected,
"Found result " << tr.result() << ". Expected result " <<
expected << "." ) ;
BOOST_CHECK( b.empty() ) ;
-}
+ }
-//--------------------------------------------------
-#include "ACT/Pause_Service.hpp"
+ //--------------------------------------------------
+ // Same as act_n_interleaved, but using a Supplied_Service
-BOOST_AUTO_UNIT_TEST( pause_action )
-{
- Basic_Scheduler b ;
+ BOOST_AUTO_UNIT_TEST( act_n_service )
+ {
+ scheduler_aspect_body a ;
+ Test_Scheduler b = Test_Scheduler( Test_Scheduler_Aspect( & a )
) ;
+
+ execution_trace tr ;
+ Supplied_Service * ss = new Supplied_Service( b, new
simple_tracker( tr, "S" ) ) ;
+ ss -> add_task( shared_ptr< basic_act >( new N_to_completion(
2, new simple_tracker( tr, "A" ) ) ) ) ;
+ ss -> add_task( shared_ptr< basic_act >( new N_to_completion(
3, new simple_tracker( tr, "B" ) ) ) ) ;
+ ss -> add_task( shared_ptr< basic_act >( new N_to_completion(
5, new simple_tracker( tr, "C" ) ) ) ) ;
+
+ b.add_service( act( ss ) ) ;
+ ss -> shutdown() ;
+ a.set_execution_bound( 100 ) ;
+ b() ;
+ // First "S" is to enter the new tasks into the queue.
+ // Second "S" is to allow the service to return Completed and
leave the scheduling queue.
+ std::string expected( "SABCSABCBCCC" ) ;
+ BOOST_CHECK_MESSAGE( tr.result() == expected,
+ "Found result " << tr.result() << ". Expected result "
<< expected << "." ) ;
+ }
+
+ //--------------------------------------------------
+ BOOST_AUTO_UNIT_TEST( pause_action )
+ {
+ scheduler_aspect_body a ;
+ Test_Scheduler b = Test_Scheduler( Test_Scheduler_Aspect( & a )
) ;
BOOST_REQUIRE( b.empty() ) ;
- Pause_Service x( & b ) ;
+ Pause_Demon * pause( new Pause_Demon( & b ) ) ;
b.add_task( act( new no_action( 0 ) ) ) ;
- x() ;
-}
+ // This pause action should immediately return, because there's
a pending action in the scheduler.
+ ( * pause )() ;
+
+ a.set_execution_bound( 2 ) ;
+ b.add_service( act( pause ) ) ;
+ b() ;
+ BOOST_CHECK( a.finished_at_bound() ) ; // Pause demon should
execute once, no_action once.
+ BOOST_CHECK( ! b.empty() ) ; // demon should
still be in queue.
+ }
+} // end namespace ACT_test
\ No newline at end of file
Index: ACT/unit_tests/Test_Scheduling_Queue.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/unit_tests/Test_Scheduling_Queue.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- ACT/unit_tests/Test_Scheduling_Queue.cpp 1 Jul 2007 10:53:52 -0000
1.3
+++ ACT/unit_tests/Test_Scheduling_Queue.cpp 10 Jul 2007 14:09:09 -0000
1.4
@@ -27,8 +27,6 @@
#include "unit_tests/Permutation.hpp"
#include "unit_tests/Random_Permutation.hpp"
-// Include this implementation file in order to instantiate template
-#include "ACT/Scheduling_Queue.cpp"
/** A test item to put into a scheduling queue.
*/
@@ -45,9 +43,12 @@
} ;
// Explicit instantiation
-template ACT::Scheduling_Queue< test_item, ACT::wakeup_listener_allocated > ;
+#include "ACT/Scheduling_Queue.cpp"
+#include "ACT/Scheduler.T.cpp"
+template ACT::wakeup_listener_allocated< ACT::Basic_Scheduler<> > ;
+template ACT::Scheduling_Queue< test_item, ACT::wakeup_listener_allocated<
ACT::Basic_Scheduler<> > > ;
-typedef ACT::Scheduling_Queue< test_item, ACT::wakeup_listener_allocated >
queue_type ;
+typedef ACT::Scheduling_Queue< test_item, ACT::wakeup_listener_allocated<
ACT::Basic_Scheduler<> > > queue_type ;
typedef queue_type::pointer pointer ;
using namespace ACT ;
Index: HTTP/HTTP_Behavior.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/HTTP/HTTP_Behavior.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- HTTP/HTTP_Behavior.cpp 1 Jul 2007 10:53:52 -0000 1.2
+++ HTTP/HTTP_Behavior.cpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -33,11 +33,11 @@
{}
//-------------------------
- act_state
+ ACT::ACT_State
HTTP_Behavior::
run( wakeup_listener * w )
{
- act_state x ;
+ ACT::ACT_State x( ACT::ACT_State::Ready ) ;
switch ( protocol_state ) {
case initial:
@@ -45,8 +45,8 @@
protocol_state = scanning_request ;
case scanning_request:
x = scan_request( w ) ;
- if ( x == Bad ) return set_bad() ;
- if ( x == Working ) return Working ;
+ if ( x.bad() ) return set_bad() ;
+ if ( x.working() ) return set_state( x ) ;
protocol_state = responding ;
case responding:
// We'll support HTTP/1.0 later.
@@ -71,11 +71,11 @@
protocol_state = sending_final_message ;
case sending_final_message:
x = the_device -> Sink::operator()( w ) ;
- if ( x == Bad ) return set_bad() ;
- if ( x == Working ) return Working ;
+ if ( x.bad() ) return set_bad() ;
+ if ( x.working() ) return set_state( x ) ;
return set_completed() ;
} ;
- return ACT::Working ;
+ return set_would_block() ;
}
} } // end namespace cygnal::HTTP
Index: HTTP/HTTP_Behavior.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/HTTP/HTTP_Behavior.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- HTTP/HTTP_Behavior.hpp 1 Jul 2007 10:53:52 -0000 1.2
+++ HTTP/HTTP_Behavior.hpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -57,7 +57,7 @@
HTTP_Behavior( IO::Device * ) ;
///
- ACT::act_state run( ACT::wakeup_listener * ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * ) ;
///
static shared_ptr< ACT::autonomous_act > new_HTTP_Behavior(
IO::Device * ) ;
Index: HTTP/HTTP_Parse.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/HTTP/HTTP_Parse.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- HTTP/HTTP_Parse.cpp 1 Jul 2007 10:53:52 -0000 1.2
+++ HTTP/HTTP_Parse.cpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -163,7 +163,7 @@
{}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
read_single_header::
scan( ACT::wakeup_listener * w )
{
@@ -289,7 +289,7 @@
// Assert n_left_to_process == 0
end_of_processing_loop:
- return ACT::Working ;
+ return source_state() ;
}
//-------------------------
@@ -312,7 +312,7 @@
message_header_size = 0 ;
r_field_name.set_begin( next_character ) ;
r_field_name.set_length( 0 ) ;
- set_working() ;
+ set_ready() ;
}
//--------------------------------------------------
@@ -327,7 +327,7 @@
{} ;
//-------------------------
- ACT::act_state
+ ACT::ACT_State
read_message_headers_action::
scan( ACT::wakeup_listener * waken )
{
@@ -342,7 +342,7 @@
// Our subroutine went bad. So do we.
return set_bad() ;
}
- return ACT::Working ;
+ return source_state() ;
}
// Assert (postcondition--read_single_header action
completed) input processed was "message-header? CR LF"
IO::buffer field_name(
read_single_header_action.result_field_name() ) ;
@@ -395,7 +395,7 @@
}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
Request_Method_Scanner::
scan( ACT::wakeup_listener * w )
{
@@ -451,34 +451,34 @@
/** \par Implementation Notes
* - The protocol designator "HTTP" is sensitive to case.
*/
- ACT::act_state
+ ACT::ACT_State
Request_Version_Scanner::
scan( ACT::wakeup_listener * w )
{
char ch ;
switch ( scan_state ) {
case initial:
- if ( n_left_to_process == 0 ) { scan_state =
initial ; return Working ; }
+ if ( n_left_to_process == 0 ) { scan_state =
initial ; return source_state() ; }
ch = * next_character ++ ; -- n_left_to_process
;
if ( ch != 'H' ) return syntax_error() ;
case seen_H:
- if ( n_left_to_process == 0 ) { scan_state =
seen_H ; return Working ; }
+ if ( n_left_to_process == 0 ) { scan_state =
seen_H ; return source_state() ; }
ch = * next_character ++ ; -- n_left_to_process
;
if ( ch != 'T' ) return syntax_error() ;
case seen_HT:
- if ( n_left_to_process == 0 ) { scan_state =
seen_HT ; return Working ; }
+ if ( n_left_to_process == 0 ) { scan_state =
seen_HT ; return source_state() ; }
ch = * next_character ++ ; -- n_left_to_process
;
if ( ch != 'T' ) return syntax_error() ;
case seen_HTT:
- if ( n_left_to_process == 0 ) { scan_state =
seen_HTT ; return Working ; }
+ if ( n_left_to_process == 0 ) { scan_state =
seen_HTT ; return source_state() ; }
ch = * next_character ++ ; -- n_left_to_process
;
if ( ch != 'P' ) return syntax_error() ;
case seen_HTTP:
- if ( n_left_to_process == 0 ) { scan_state =
seen_HTTP ; return Working ; }
+ if ( n_left_to_process == 0 ) { scan_state =
seen_HTTP ; return source_state() ; }
ch = * next_character ++ ; -- n_left_to_process
;
if ( ch != '/' ) return syntax_error() ;
case first_digits_0:
- if ( n_left_to_process == 0 ) { scan_state =
first_digits_0 ; return Working ; }
+ if ( n_left_to_process == 0 ) { scan_state =
first_digits_0 ; return source_state() ; }
ch = * next_character ++ ; -- n_left_to_process
;
if ( ! is_digit( ch ) ) return syntax_error() ;
the_result.major_number = ( ch - '0' ) ;
@@ -499,10 +499,10 @@
}
}
scan_state = first_digits_0 ;
- return Working ;
+ return source_state() ;
label_second_digits_0:
case second_digits_0:
- if ( n_left_to_process == 0 ) { scan_state =
second_digits_0 ; return Working ; }
+ if ( n_left_to_process == 0 ) { scan_state =
second_digits_0 ; return source_state() ; }
ch = * next_character ++ ; -- n_left_to_process
;
if ( ! is_digit( ch ) ) return syntax_error() ;
the_result.minor_number = ( ch - '0' ) ;
@@ -520,7 +520,7 @@
}
}
scan_state = first_digits_0 ;
- return Working ;
+ return source_state() ;
}
label_end_of_scan:
++ n_left_to_process ;
@@ -541,7 +541,7 @@
{}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
Request_Scanner::
scan( ACT::wakeup_listener * w )
{
@@ -555,31 +555,33 @@
switch ( current_state ) {
case in_method:
scan_method( w ) ;
- if ( scan_method.working() ) return
ACT::Working ;
+ if ( scan_method.working() ) { current_state =
in_method ; return source_state() ; }
if ( scan_method.bad() ) goto label_error ;
- current_state = in_request_URI ;
// fall through
case in_request_URI:
scan_URI( w ) ;
- if ( scan_URI.working() ) return ACT::Working ;
+ if ( scan_URI.working() ) { current_state =
in_request_URI ; return source_state() ; }
if ( scan_URI.bad() ) goto label_error ;
- current_state = in_HTTP_version ;
+ // fall through
+ case post_request_URI:
+ if ( n_left_to_process == 0 ) { current_state =
post_request_URI ; return source_state() ; }
+ -- n_left_to_process ;
+ ch = * next_character ++ ;
+ if ( ch != ' ' ) goto label_error ;
// fall through
case in_HTTP_version:
scan_version( w ) ;
- if ( scan_version.working() ) return
ACT::Working ;
+ if ( scan_version.working() ) { current_state =
in_HTTP_version ; return source_state() ; }
if ( scan_version.bad() ) goto label_error ;
- current_state = p_final_CR ;
// fall through
case p_final_CR:
- if ( n_left_to_process == 0 ) return
ACT::Working ;
+ if ( n_left_to_process == 0 ) { current_state =
p_final_CR ; return source_state() ; }
-- n_left_to_process ;
ch = * next_character ++ ;
if ( ch != '\r' ) goto label_error ;
- current_state = p_final_LF ;
// fall through
case p_final_LF:
- if ( n_left_to_process == 0 ) return
ACT::Working ;
+ if ( n_left_to_process == 0 ) { current_state =
p_final_LF ; return source_state() ; }
-- n_left_to_process ;
ch = * next_character ++ ;
if ( ch != '\n' ) goto label_error ;
Index: HTTP/HTTP_Parse.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/HTTP/HTTP_Parse.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- HTTP/HTTP_Parse.hpp 1 Jul 2007 10:53:52 -0000 1.2
+++ HTTP/HTTP_Parse.hpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -147,7 +147,7 @@
IO::result_buffer<> r_field_name ;
///
- ACT::act_state scan( ACT::wakeup_listener * ) ;
+ ACT::ACT_State scan( ACT::wakeup_listener * ) ;
public:
/// Ordinary constructor
@@ -196,7 +196,7 @@
read_single_header read_single_header_action ;
/// Body of action
- ACT::act_state scan( ACT::wakeup_listener * ) ;
+ ACT::ACT_State scan( ACT::wakeup_listener * ) ;
public:
/// Ordinary constructor takes a nonblocking device as its
source
@@ -250,7 +250,7 @@
IO::result_buffer<> r_method ;
///
- ACT::act_state scan( ACT::wakeup_listener * ) ;
+ ACT::ACT_State scan( ACT::wakeup_listener * ) ;
///
void init() ;
@@ -288,7 +288,7 @@
HTTP_Version the_result ;
///
- ACT::act_state scan( ACT::wakeup_listener * ) ;
+ ACT::ACT_State scan( ACT::wakeup_listener * ) ;
///
void init() ;
@@ -328,6 +328,7 @@
enum request_parse_state {
in_method,
in_request_URI,
+ post_request_URI,
in_HTTP_version,
p_final_CR,
p_final_LF,
@@ -347,7 +348,7 @@
Request_Version_Scanner scan_version ;
///
- ACT::act_state scan( ACT::wakeup_listener * ) ;
+ ACT::ACT_State scan( ACT::wakeup_listener * ) ;
public:
/// Ordinary constructor takes a nonblocking device as its
source
Index: HTTP/URI.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/HTTP/URI.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- HTTP/URI.cpp 1 Jul 2007 10:53:52 -0000 1.2
+++ HTTP/URI.cpp 10 Jul 2007 14:09:09 -0000 1.3
@@ -99,7 +99,7 @@
//--------------------------------------------------
// URI_Scanner
//--------------------------------------------------
- ACT::act_state
+ ACT::ACT_State
URI_Scanner::
scan( ACT::wakeup_listener * ) {
// If we are at EOF, some states may accept, some may reject.
@@ -165,7 +165,7 @@
}
}
current_state = scheme_0 ;
- return ACT::Working ;
+ return source_state() ;
label_scheme:
case scheme:
while ( n_left_to_process > 0 ) {
@@ -184,7 +184,7 @@
}
}
current_state = scheme ;
- return ACT::Working ;
+ return source_state() ;
//-------------------------
// hier-part
//-------------------------
@@ -208,7 +208,7 @@
}
}
current_state = hier_part_0 ;
- return ACT::Working ;
+ return source_state() ;
//----------
label_hier_part_slash:
case hier_part_slash:
@@ -237,7 +237,7 @@
}
}
current_state = hier_part_slash ;
- return ACT::Working ;
+ return source_state() ;
//-------------------------
// authority
//-------------------------
@@ -261,7 +261,7 @@
}
}
current_state = authority_0 ;
- return ACT::Working ;
+ return source_state() ;
//----------
label_auth_unknown:
case auth_unknown:
@@ -285,7 +285,7 @@
}
}
current_state = auth_unknown ;
- return ACT::Working ;
+ return source_state() ;
//-------------------------
// path
//-------------------------
@@ -315,7 +315,7 @@
}
}
current_state = path_absolute_0 ;
- return ACT::Working ;
+ return source_state() ;
//----------
label_path_absolute:
case path_absolute:
@@ -340,7 +340,7 @@
}
}
current_state = path_absolute ;
- return ACT::Working ;
+ return source_state() ;
//----------
label_path_abempty_0:
case path_abempty_0:
@@ -368,7 +368,7 @@
}
}
current_state = path_absolute_0 ;
- return ACT::Working ;
+ return source_state() ;
//-------------------------
// query
//-------------------------
@@ -390,7 +390,7 @@
}
}
current_state = query_0 ;
- return ACT::Working ;
+ return source_state() ;
//----------
label_query:
case query:
@@ -410,7 +410,7 @@
}
}
current_state = query_0 ;
- return ACT::Working ;
+ return source_state() ;
//-------------------------
// fragment
//-------------------------
@@ -430,7 +430,7 @@
}
}
current_state = fragment_0 ;
- return ACT::Working ;
+ return source_state() ;
//----------
label_fragment:
case fragment:
@@ -447,7 +447,7 @@
}
}
current_state = fragment ;
- return ACT::Working ;
+ return source_state() ;
//----------
label_done_unget_last_character:
uri.r_URI.set_length( next_character -
URI_begin - 1 ) ;
Index: HTTP/URI.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/HTTP/URI.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- HTTP/URI.hpp 1 Jul 2007 10:53:52 -0000 1.2
+++ HTTP/URI.hpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -70,6 +70,11 @@
} ;
//-------------------------
+ /** \class URI_Scanner
+ *
+ * \todo Fix the silent consumption of the next character after
the URI.
+ * It interferes with a caller's grammar.
+ */
class URI_Scanner
: public IO::Stream_Consumer
{
@@ -80,7 +85,7 @@
char * component_begin ;
///
- ACT::act_state scan( ACT::wakeup_listener * ) ;
+ ACT::ACT_State scan( ACT::wakeup_listener * ) ;
///
void init() ;
Index: HTTP/unit_tests/Test_HTTP.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/HTTP/unit_tests/Test_HTTP.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- HTTP/unit_tests/Test_HTTP.cpp 1 Jul 2007 10:53:53 -0000 1.2
+++ HTTP/unit_tests/Test_HTTP.cpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -454,7 +454,13 @@
}
//---------------------------------------------------------------------------
-BOOST_AUTO_TEST_CASE( Invalid_Version_Request )
+/* Scanning regular URI and "*"-URI are handled differently internally.
+ * This pair of tests once had different outcomes; the first failed and second
passed.
+ * URI scanning was consuming an extra character for ordinary URI but not "*".
+ * HTTP-Request scanning wasn't looking for the space after its URI.
+ * In the test that passed, one defect was masking the other.
+ */
+BOOST_AUTO_TEST_CASE( Invalid_Version_Request_1 )
{
char request[] = "GET * HTTP/1.0\r\n" ;
IO::String_Device device( request ) ;
@@ -464,6 +470,20 @@
cygnal::HTTP::HTTP_Behavior behavior( & device ) ;
behavior() ;
- BOOST_CHECK( behavior.completed() ) ;
+ BOOST_REQUIRE( behavior.completed() ) ;
+ BOOST_CHECK( device.string_written() == string( response ) ) ;
+}
+
+BOOST_AUTO_TEST_CASE( Invalid_Version_Request_2 )
+{
+ char request[] = "GET http://foo.com/ HTTP/1.0\r\n" ;
+ IO::String_Device device( request ) ;
+ char response[] =
+ "HTTP/1.1 505 HTTP Version Not Supported" "\r\n"
+ "Connection: close" "\r\n" ;
+
+ cygnal::HTTP::HTTP_Behavior behavior( & device ) ;
+ behavior() ;
+ BOOST_REQUIRE( behavior.completed() ) ;
BOOST_CHECK( device.string_written() == string( response ) ) ;
}
\ No newline at end of file
Index: IO/IO_Device.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/IO_Device.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/IO_Device.hpp 1 Jul 2007 10:53:53 -0000 1.2
+++ IO/IO_Device.hpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -125,8 +125,8 @@
: public Source
{
protected:
- virtual ACT::act_state source_run( ACT::wakeup_listener * ) =0 ;
- inline ACT::act_state run( ACT::wakeup_listener * w ) { return
source_run( w ) ; }
+ virtual ACT::ACT_State source_run( ACT::wakeup_listener * ) =0 ;
+ inline ACT::ACT_State run( ACT::wakeup_listener * w ) { return
source_run( w ) ; }
} ;
//-------------------------
@@ -140,7 +140,7 @@
: public SSource
{
S & the_source ;
- inline ACT::act_state source_run( ACT::wakeup_listener * w ) {
return the_source.run( w ) ; }
+ inline ACT::ACT_State source_run( ACT::wakeup_listener * w ) {
return the_source.run( w ) ; }
public:
Source_Adapter( S & source )
: the_source( source )
@@ -157,8 +157,8 @@
//-------------------------
class SSink : public Sink {
protected:
- virtual ACT::act_state sink_run( ACT::wakeup_listener * ) =0 ;
- inline ACT::act_state run( ACT::wakeup_listener * w ) { return
sink_run( w ) ; }
+ virtual ACT::ACT_State sink_run( ACT::wakeup_listener * ) =0 ;
+ inline ACT::ACT_State run( ACT::wakeup_listener * w ) { return
sink_run( w ) ; }
} ;
//-------------------------
@@ -172,7 +172,7 @@
: public SSink
{
S & the_sink ;
- inline ACT::act_state sink_run( ACT::wakeup_listener * w ) {
return the_sink.run( w ) ; }
+ inline ACT::ACT_State sink_run( ACT::wakeup_listener * w ) {
return the_sink.run( w ) ; }
public:
Sink_Adapter( S & sink )
: the_sink( sink )
@@ -206,8 +206,8 @@
{
In the_source ;
Out the_sink ;
- inline ACT::act_state sink_run( ACT::wakeup_listener * w ) {
return the_sink.run( w ) ; }
- inline ACT::act_state source_run( ACT::wakeup_listener * w ) {
return the_source.run( w ) ; }
+ inline ACT::ACT_State sink_run( ACT::wakeup_listener * w ) {
return the_sink.run( w ) ; }
+ inline ACT::ACT_State source_run( ACT::wakeup_listener * w ) {
return the_source.run( w ) ; }
public:
Split_Device( In in, Out out )
: the_source( in ), the_sink( out )
@@ -230,7 +230,7 @@
Oldsource & the_source ;
Action the_action ;
- inline ACT::act_state run( ACT::wakeup_listener * w ) { return
the_action.operator()( w ) ; }
+ inline ACT::ACT_State run( ACT::wakeup_listener * w ) { return
the_action.operator()( w ) ; }
template< class In, class Out > friend class Split_Device ;
public:
Index: IO/IO_Generator.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/IO_Generator.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/IO_Generator.cpp 1 Jul 2007 10:53:53 -0000 1.2
+++ IO/IO_Generator.cpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -15,7 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/// \file IO_Service.cpp
+/// \file IO_Generator.cpp
#include "IO_Generator.hpp"
@@ -28,13 +28,13 @@
{}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
Device_Adapter::
run( ACT::wakeup_listener * w )
{
the_generator( w ) ;
if ( the_generator.bad() ) return set_bad() ;
- if ( the_generator.working() ) return ACT::Working ;
+ if ( the_generator.working() ) return set_ready() ;
// Assert the_generator has a result ready for us.
the_result = the_behavior_factory( the_generator.result() ) ;
Index: IO/IO_Generator.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/IO_Generator.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/IO_Generator.hpp 1 Jul 2007 10:53:53 -0000 1.2
+++ IO/IO_Generator.hpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -74,7 +74,7 @@
/** \class Device_Adapter
*/
class Device_Adapter
- : public ACT::Generator
+ : public ACT::Obsolete_Generator // will rewrite
as deriving from ACT::Generator
{
/// We use shared_ptr here
Device_Generator & the_generator ;
@@ -89,7 +89,7 @@
Device_Adapter( Device_Generator & x, Behavior_Factory & y ) ;
///
- ACT::act_state run( ACT::wakeup_listener * w ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * w ) ;
///
ACT::act result() ;
Index: IO/Stream_Consumer.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/Stream_Consumer.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/Stream_Consumer.cpp 1 Jul 2007 10:53:53 -0000 1.2
+++ IO/Stream_Consumer.cpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -15,7 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/** \file Stream_Consumer.hpp
+/** \file Stream_Consumer.cpp
* \brief Assistance for treating ACT block readers as a stream.
*
* Implementing a stream model with ACT-based I/O requires resolving a
number of competing concerns.
@@ -60,7 +60,7 @@
{}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
Stream_Consumer::
run( ACT::wakeup_listener * w )
{
@@ -79,7 +79,7 @@
if ( source_still_working() ) {
// Assert our underlying source is
still working.
// Nothing left to do now.
- return ACT::Working ;
+ return the_source -> internal_state() ;
}
if ( source_went_bad() ) {
// Assert our underlying source went
bad.
@@ -105,7 +105,7 @@
if ( source_still_working() ) {
// Assert our underlying source is
still working.
// Nothing left to do now.
- return ACT::Working ;
+ return the_source -> internal_state() ;
}
if ( source_went_bad() ) {
// Assert our underlying source went
bad.
@@ -123,10 +123,9 @@
caller_next_character = next_character ;
caller_n_left_to_process =
n_left_to_process ;
}
- return ACT::Completed ;
- } else if ( bad() ) {
- return ACT::Completed ;
}
+ if ( ! working() ) return internal_state() ;
+ // Assert scanning remains incomplete
}
}
Index: IO/Stream_Consumer.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/Stream_Consumer.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/Stream_Consumer.hpp 1 Jul 2007 10:53:53 -0000 1.2
+++ IO/Stream_Consumer.hpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -63,7 +63,7 @@
unsigned int number_of_lookahead_characters_required ;
/// Polymorphic scanner.
- virtual ACT::act_state scan( ACT::wakeup_listener * ) =0 ;
+ virtual ACT::ACT_State scan( ACT::wakeup_listener * ) =0 ;
/// Initial action
virtual void init() {} ;
@@ -98,6 +98,9 @@
/// [replenish result]
inline bool source_went_bad() { return the_source -> bad() ; }
+ /// [replenish result]
+ inline ACT::ACT_State source_state() { return the_source ->
internal_state() ; }
+
///
inline void require_lookahead( unsigned int n ) {
number_of_lookahead_characters_required = n ; }
@@ -113,12 +116,12 @@
bool first_time ;
/// [error] Indicate a syntax error at the current location.
- ACT::act_state syntax_error() { return set_bad() ; }
+ ACT::ACT_State syntax_error() { return set_bad() ; }
public:
/// The class implements the ACT invocation.
/// This function wraps our own polymorphic \c run.
- ACT::act_state run( ACT::wakeup_listener * ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * ) ;
} ;
Index: IO/test_support/Null_Device.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/Null_Device.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/Null_Device.cpp 1 Jul 2007 10:53:54 -0000 1.2
+++ IO/test_support/Null_Device.cpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -15,7 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/** \file Null_Device.hpp
+/** \file Null_Device.cpp
* \brief
*/
@@ -31,7 +31,7 @@
set_completed() ;
}
- ACT::act_state
+ ACT::ACT_State
Null_Source::
run( ACT::wakeup_listener * )
{
Index: IO/test_support/Null_Device.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/Null_Device.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/Null_Device.hpp 1 Jul 2007 10:53:54 -0000 1.2
+++ IO/test_support/Null_Device.hpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -34,7 +34,7 @@
friend class Null_Device ;
template< class S > friend class Source_Adapter ;
- ACT::act_state run( ACT::wakeup_listener * ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * ) ;
public:
/// Only need a default constructor for a source that's always
the same.
@@ -57,7 +57,7 @@
template< class In, class Out > friend class Split_Device ;
/// The write action.
- ACT::act_state run( ACT::wakeup_listener * ) { return
set_completed() ; }
+ ACT::ACT_State run( ACT::wakeup_listener * ) { return
set_completed() ; }
/// [out parameter value]
size_t out_n_written ;
@@ -80,8 +80,8 @@
Null_Sink the_sink ;
Null_Source the_source ;
- inline ACT::act_state source_run( ACT::wakeup_listener * w ) {
return Device::SSource::set_state( the_source.run( w ) ) ; }
- inline ACT::act_state sink_run( ACT::wakeup_listener * w ) {
return Device::SSink::set_state( the_sink.run( w ) ) ; }
+ inline ACT::ACT_State source_run( ACT::wakeup_listener * w ) {
return Device::SSource::set_state( the_source.run( w ) ) ; }
+ inline ACT::ACT_State sink_run( ACT::wakeup_listener * w ) {
return Device::SSink::set_state( the_sink.run( w ) ) ; }
public:
///
Index: IO/test_support/Null_Filter.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/Null_Filter.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/Null_Filter.cpp 1 Jul 2007 10:53:54 -0000 1.2
+++ IO/test_support/Null_Filter.cpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -44,7 +44,7 @@
}
//---------------
- ACT::act_state
+ ACT::ACT_State
null_read_filter::
run( ACT::wakeup_listener * w )
{
Index: IO/test_support/Null_Filter.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/Null_Filter.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/Null_Filter.hpp 1 Jul 2007 10:53:54 -0000 1.2
+++ IO/test_support/Null_Filter.hpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -38,7 +38,7 @@
Source * the_source ;
///
- ACT::act_state run( ACT::wakeup_listener * ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * ) ;
public:
/// Ordinary constructor
Index: IO/test_support/String_Device.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/String_Device.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/String_Device.cpp 1 Jul 2007 10:53:54 -0000 1.2
+++ IO/test_support/String_Device.cpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -15,7 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/// \file String_Device.hpp
+/// \file String_Device.cpp
#include "String_Device.hpp"
#include <string>
@@ -81,7 +81,7 @@
}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
String_Device::
source_run( ACT::wakeup_listener * )
{
@@ -110,7 +110,7 @@
String_Device::
reset()
{
- SSource::set_working() ;
+ SSource::set_ready() ;
}
//-------------------------
@@ -137,7 +137,7 @@
}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
String_Device::
sink_run( ACT::wakeup_listener * )
{
Index: IO/test_support/String_Device.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/String_Device.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/String_Device.hpp 1 Jul 2007 10:53:54 -0000 1.2
+++ IO/test_support/String_Device.hpp 10 Jul 2007 14:09:10 -0000 1.3
@@ -49,7 +49,7 @@
contiguous_buffer<> the_next_segment ;
/// [source] read activation body
- ACT::act_state source_run( ACT::wakeup_listener * ) ;
+ ACT::ACT_State source_run( ACT::wakeup_listener * ) ;
/// [sink] This string receives the results of write operations.
std::string the_sink_string ;
@@ -61,7 +61,7 @@
buffer next_to_write ;
/// [sink] activation body
- ACT::act_state sink_run( ACT::wakeup_listener * ) ;
+ ACT::ACT_State sink_run( ACT::wakeup_listener * ) ;
public:
/// Ordinary constructor
Index: IO/test_support/String_Generator.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/String_Generator.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/String_Generator.cpp 1 Jul 2007 10:53:54 -0000
1.2
+++ IO/test_support/String_Generator.cpp 10 Jul 2007 14:09:10 -0000
1.3
@@ -36,11 +36,11 @@
}
///
- ACT::act_state
+ ACT::ACT_State
String_Generator::
run( ACT::wakeup_listener * )
{
- if ( the_queue.empty() ) return ACT::Working ;
+ if ( the_queue.empty() ) return ACT::ACT_State(
ACT::ACT_State::Ready ) ;
the_result = shared_ptr< IO::Device >( new String_Device(
the_queue.front() ) ) ;
the_queue.pop() ;
return set_completed() ;
@@ -65,7 +65,7 @@
reset()
{
if ( bad() ) return ;
- set_working() ;
+ set_ready() ;
}
} // end namespace IO
Index: IO/test_support/String_Generator.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/test_support/String_Generator.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/test_support/String_Generator.hpp 1 Jul 2007 10:53:54 -0000
1.2
+++ IO/test_support/String_Generator.hpp 10 Jul 2007 14:09:10 -0000
1.3
@@ -50,7 +50,7 @@
void add_source( std::string x ) ;
///
- ACT::act_state run( ACT::wakeup_listener * ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * ) ;
/// result accessor
shared_ptr< IO::Device > result() ;
Index: IO/unit_tests/Test_Service.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/IO/unit_tests/Test_Service.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- IO/unit_tests/Test_Service.cpp 1 Jul 2007 10:53:55 -0000 1.2
+++ IO/unit_tests/Test_Service.cpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -27,7 +27,7 @@
{
public:
Null_Behavior() { set_completed() ; }
- ACT::act_state run( ACT::wakeup_listener * ) { return ACT::Completed ; }
+ ACT::ACT_State run( ACT::wakeup_listener * ) { return set_completed() ;
}
} ;
//-------------------------
Index: Net/Net.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/Net/Net.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- Net/Net.hpp 1 Jul 2007 10:53:55 -0000 1.2
+++ Net/Net.hpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -189,7 +189,7 @@
* in order to support the RAII convention.
* The resource is the socket handle itself.
*
- * \inv Instance holds an allocated socket.
+ * \invariant Instance holds an allocated socket.
*
* \par Limitations
* - Class opens sockets in default streaming protocol (meaning
TCP) only.
Index: Net/Old_Device.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/Net/Old_Device.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- Net/Old_Device.hpp 1 Jul 2007 10:53:55 -0000 1.2
+++ Net/Old_Device.hpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -15,7 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/** \file IO_Device.hpp
+/** \file Old_Device.hpp
* \brief Basic abstractions for handling ACT-based I/O
*
* \par Design Notes
Index: Net/socket_device.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/Net/socket_device.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- Net/socket_device.cpp 1 Jul 2007 10:53:55 -0000 1.2
+++ Net/socket_device.cpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -188,7 +188,7 @@
{}
//-------------------------
- ACT::act_state
+ ACT::ACT_State
read_action::
run( ACT::wakeup_listener * waken )
{
@@ -218,9 +218,9 @@
} else if ( error == EINTR ) {
// Assert the read() call was interrupted.
// Rather than enter a loop here, we let the
scheduler retry.
- if ( waken != 0 ) {
- ( * waken )() ;
- }
+
+ /// \todo Implement a recovery tactic.
+ set_bad() ;
} else {
// Assert the socket had a non-recoverable error
set_bad() ;
@@ -253,7 +253,7 @@
} ;
//-------------------------
- ACT::act_state
+ ACT::ACT_State
write_action::
run( ACT::wakeup_listener * waken )
{
@@ -289,9 +289,9 @@
} else if ( errno == EINTR ) {
// Assert the read() call was interrupted.
// Rather than enter a loop here, we let the
scheduler retry.
- if ( waken != 0 ) {
- ( * waken )() ;
- }
+
+ /// \todo Implement a recovery tactic.
+ set_bad() ;
} else {
// Assert the socket had a non-recoverable error
set_bad() ;
Index: Net/socket_device.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/Net/socket_device.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- Net/socket_device.hpp 1 Jul 2007 10:53:55 -0000 1.2
+++ Net/socket_device.hpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -231,7 +231,7 @@
//---------------
/**
*/
- ACT::act_state run( ACT::wakeup_listener * waken ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * waken ) ;
//---------------
/** \brief Ordinary constructor
@@ -262,7 +262,7 @@
public:
/// Action operator actually does the write.
- ACT::act_state run( ACT::wakeup_listener * waken ) ;
+ ACT::ACT_State run( ACT::wakeup_listener * waken ) ;
/// Ordinary constructor
write_action(
Index: Net/unit_tests/Test_socket_device.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/Net/unit_tests/Test_socket_device.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- Net/unit_tests/Test_socket_device.cpp 1 Jul 2007 10:53:55 -0000
1.2
+++ Net/unit_tests/Test_socket_device.cpp 10 Jul 2007 14:09:11 -0000
1.3
@@ -15,7 +15,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/// \file Test_Service.cpp
+/// \file Test_socket_device.cpp
#include "config.h"
Index: unit_tests/Permutation.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/unit_tests/Permutation.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- unit_tests/Permutation.hpp 1 Jul 2007 10:53:56 -0000 1.2
+++ unit_tests/Permutation.hpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -107,6 +107,8 @@
throw std::exception( "Can only compare against end-iterators
in the present implementation." ) ;
}
+ /** \class test_function
+ */
boost::function< void( void ) > test_function() const
{
return boost::bind( f, the_vector.begin(), the_vector.end() ) ;
Index: unit_tests/Random_Permutation.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/unit_tests/Random_Permutation.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- unit_tests/Random_Permutation.cpp 1 Jul 2007 10:53:56 -0000 1.2
+++ unit_tests/Random_Permutation.cpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -18,7 +18,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/// \file Random_Permutation.hpp
+/// \file Random_Permutation.cpp
/// \brief A permutation generator for test cases.
#include "Random_Permutation.hpp"
Index: unit_tests/Test_Support.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/unit_tests/Test_Support.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- unit_tests/Test_Support.hpp 1 Jul 2007 10:53:56 -0000 1.2
+++ unit_tests/Test_Support.hpp 10 Jul 2007 14:09:11 -0000 1.3
@@ -133,7 +133,7 @@
} ;
//--------------------------------------------------
-/** \fn make_generator
+/** \fn make_generator template< class Gen > auto_generator make_generator(
Gen generator_instance, std::string name )
* \brief Adapter function allowing use of type inference to initialize
test generator.
*/
template< class Gen >
Index: ACT/ACT.doxygen.txt
===================================================================
RCS file: ACT/ACT.doxygen.txt
diff -N ACT/ACT.doxygen.txt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/ACT.doxygen.txt 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,174 @@
+/**
+
+\page ACT Module ACT: Asynchronous Computation Task
+
+ An ACT is the moral equivalent of a thread in an asynchronous,
cooperative, non-preemptive, multitasking environment.
+ The name "ACT" is itself an acronym for Asynchronous Computation Task.
+
+\section s_Speed Speed is the Reason
+
+ The whole point of the ACT environment is high performance.
+ In comes at a cost, certainly; the tradeoffs are not trivial.
+ Preemptive multitasking is easier to implement, but at the cost of the
overhead of context switches.
+ Each context switch must preserve the entire state of computation, both
internal CPU state as well as memory.
+ The operating system (or other control facility) is ignorant, perforce,
of the details of a computational unit, be it process or thread.
+ Thus it cannot optimize a context switch in any way,
+ either by picking a fortuitous point to interrupt (avoiding
saving CPU state)
+ or by saving less state on the stack than everything (incurring
cache and swapping penalties).
+ There are two primary benefits of the ACT model.
+ The first primary benefit, then, is the elimination of context switch
overhead.
+
+ The second benefit is its natural fit with asynchronous and
non-blocking I/O.
+ Technically, avoiding context switches mandates working within a single
thread and using cooperative scheduling.
+ Cooperative scheduling means that a task must manually yield its
control of the CPU back to its environment.
+ The natural time to do that is when receiving a "would block" return on
a non-blocking I/O call.
+ Every program that uses non-blocking I/O needs to be able to resume
itself at the effective point where the computation left off.
+ In the ACT system, this is simply a requirement for all tasks, so doing
it for non-blocking I/O adds no extra overhead.
+ The implementation pattern that comes to the fore is the "state of a
partial computation".
+ One element of a partial computation state is a record of what I/O
operation has been set to operate asynchronously.
+
+\section s_Elements An Oveview of the Elements of the ACT Environment
+ The main elements of the ACT environment the following:
+ - \b Actions.
+ These are ACT classes that do all the work; it's the equivalent
of a thread body.
+ The ultimate purpose of the ACT environment is to provide an
execution context for actions.
+ An action runs until it yields (typically because it would
block).
+ At such a time it enters a waiting state, waiting to be
awakened as a result of further activity.
+ - \b Scheduler.
+ In preemptive multitasking environments, the scheduling
function is provided transparently.
+ In the ACT environment, ordinary actions see scheduling as
transparent,
+ but the scheduler is visible to certain primitives,
particularly those involved with I/O.
+ A scheduler is single-threaded and is designed to be the body
of a thread.
+ The scheduler, however, is not a singleton, as the preferred
deployment configuration is one-scheduler-per-CPU.
+ - \b Demons.
+ Demons are a category of actions that run persistently in the
scheduler.
+ The scheduler views ordinary actions as tasks, which are
expected to eventually terminate.
+ The scheduler has different execution policies for demons and
tasks.
+ The two most significant kinds of demons are services and
monitors.
+ - \b Services.
+ A service is a demon that generates new tasks.
+ A service typically represents some kind of bound input device,
activity at which needs some response.
+ The response to such input activity is a new task.
+ For example, a socket listening at port 80 generates a new HTTP
protocol task for each incoming connection.
+ As a rule, services represent input response, but not as a
requirement.
+ A service may generate new tasks based on purely internal
considerations as well.
+ - \b Monitors.
+ A monitor is a demon that wakes up tasks from their waiting
state.
+ A task, once it yields to wait for new activity, won't be
scheduled until something else rouses it.
+ For each waiting task, there is some monitor demon that has
responsibility for waking it up.
+ Sensing the activity that triggers a wake-up is domain-specific,
+ so there's a separate monitor class for each kind of
waiting, in particular each kind of I/O.
+ - <b>Listener Actions</b>.
+ The code for actions is recursive, one action calling another
as needed.
+ This is as for ordinary code, with the distinction that the
action invariants must be preserved at each call.
+ A listener action is a primitive action that calls no other
action and cooperates with a monitor for wake-up.
+ As a result, each leaf in the call graph of an action is either
a listener action or one that spontaneously yields.
+
+\section s_Quiescence Quiescence
+
+ What does the scheduler do when it has no task work that needs to be
done?
+ If it also has no demons running, it simply exits.
+ If it does have demons running, it activates them round-robin until
they all terminate or generate new tasks.
+ In the first approximation, then, the scheduler will consume all
available CPU unless somehow throttled.
+ The basic tactic to throttle a quiescent scheduler is to have a demon
running that blocks.
+ This is the only place in the system where blocking is an ordinary part
of the architecture.
+
+ Now just to be contradictory, consider the following example.
+ The scheduler is running in a dedicated device where power consumption
due to CPU usage isn't an issue.
+ Using 100% CPU is no problem here.
+ So a blocking demon for quiescent operation isn't necessary in this
case.
+ The example shows that blocking is used during quiescent operation to
be kind to some larger execution environment.
+
+ So suppose that the scheduler is running some demon that can block.
+ How that demon unblocks is the real issue.
+ The easiest way to unblock generates a polling algorithm: it simply
waits some amount of time, then unblocks.
+ An implementation of this idea is the class ACT::Pause_Demon.
+ Without the motivation to properly handle quiescent operation, it's a
bit of a mystery why there should be a task that just eats time.
+
+ \b Note: Interrupt I/O is not yet implemented.
+ It's on the timeline.
+
+ The other way of unblocking is by interrupt.
+ With this method, actions waiting for asynchronous I/O receive
notifications on another thread.
+ This notification triggers unblocking in the demon that's blocked in
the same same thread as the waiting action.
+ It's desirable that all interruptions from any source converge upon a
single demon that aggregates them.
+ The alternatives require a hybrid algorithm with polling that doesn't
perform well.
+
+ These two strategies each have advantageous niches.
+ The downside to a polling strategy is that under quiescence it consumes
some constant fraction of CPU
+ and has a certain average latency in its responses,
proportional to that responsiveness.
+ Its upside is that under load it does no work over and above what it
would have do anyway.
+ The downside of an interrupt stategy is that there's task-switching
overhead in the interrupt process.
+ Its upside is that under quiescence it has zero CPU overhead and good
latency response.
+ The hybrid strategy is to switch between these two depending on load.
+
+ From a development sequence point of view, however, polling is easy and
interrupt is hard.
+ Thus, polling was done at the outset.
+ As of this writing, interrupting is not implemented.
+ Since the first use case of the scheduler is for deployment on
dedicated server hardware,
+ this absence has not become problematic.
+ Once the ACT environment is used on client software, however, this will
have to change.
+
+ The ACT architecture enables the separation of polling-vs.-interrupt
strategy by using listener actions and monitors.
+ While the underlying I/O calls may be identical, there are different
control structures around them for the two strategies.
+ Once both are implemented, however, swapping between them is a matter
of link-time configuration.
+ Implementing a hybrid strategy requires writing more effort, but it too
is simply linked in.
+ As a result, there's little project risk to delaying the interrupt and
hybrid strategies.
+
+\section s_Shutdown Shutdown
+
+ \b Note: The facilities in this section are not yet implemented for the
most part.
+
+ Shutting down a server is an important use case for system
administrators.
+ They have different reasons for shutting down a process, ranging from
emergency ("Process is a security breach!") to the languid ("Regular version
upgrade.").
+ The ACT environment takes the basic stance that shutdown is
application-specific.
+ The application defines a class representing a shutdown order,
+ and it's a parameter to both the scheduler and to actions.
+ The author of an action class is responsible for shutting them down in
whatever way they may find appropriate
+ and documenting that behavior.
+ There remains the issue of what the scheduler does.
+
+ To start with, there's always the option of killing it pre-emptively.
+ It's not graceful, but it's available.
+ So let's assume that the application wishes to cooperate with the
scheduler.
+
+ A scheduler must determine what to do with the actions in its
scheduling queue when it receives a shutdown order.
+ The simplest, though rarely the best, thing to do is nothing.
+ It is able to simply cease processing altogether and return from its
main loop with all its items left intact.
+ Up to this stage, this is an order to suspend.
+ Now, if the thread main function were a scheduler's execution loop (as
it supports),
+ to continue to do nothing means that the thread terminates and
presumably then the scheduler goes out of scope.
+
+ There's also a slightly more aggressive version of nothing,
+ which is to remove all references to a scheduled item from the
scheduling queue.
+ In the typical case, the only reference to an item is within the queue
(think tasks generated by a service)
+ and so this causes such an object to go out of scope
immediately.
+ Removing such a reference is the regular policy if an action completes
itself normally.
+ This removal is unusual because it happens when an action is still in
an incomplete state.
+
+ If shutdown is not required immediately, then the scheduler may
continue to execute actions
+ in anticipating of termination, presumably in the near future.
+ The next question is how many times to perform such execution.
+ As the proverbial angel-on-pinheads, the choice is between a definite
and an indefinite bound.
+ If a definite execution bound is desired, it might be by execution
count or by a time limit (or both).
+
+ summarizing, we have the following shutdown algorithm, with its main
points of configuration:
+ - Decide upon a cooperative shutdown.
+ - Construct a shutdown parameter and invoke the scheduler's shutdown
function with it.
+ - If the scheduler is immediately suspending, do so now, deleting
references if requested.
+ - Call the shutdown interface on each action in the scheduling queue.
+ - If the scheduler has a zero execution bound (either by count or in
time), return now, deleting references if requested.
+ - If execution bounds are not in place, resume ordinary operations.
The actions will shut themselves down.
+ - If execution bound are in place, continue with bounded operation.
When an action overreaches a bound, delete it if requested.
+
+\section s_Implementation_Tactics Implementation Tactics
+
+ - <b>Scheduler-specific Storage</b>.
+ It is permitted to have one monitor scheduled for each waiting
task.
+ In an I/O-bound environment, most tasks at any given time are
waiting for I/O,
+ so a one-monitor-per-waiting-task policy almost doubles
the size of the scheduling queue.
+ To alleviate this issue, scheduler-specific storage enables a
single monitor for all waiting tasks of the same category.
+ This works by allowing a listener action to navigate to the
correct monitor for its scheduler.
+ Using one monitor per scheduler rather than one monitor per
system eliminates
+ what would otherwise be a large number of cross-thread
messages, requiring relatively expensive mutex protection.
+ */
Index: ACT/Handle.cpp
===================================================================
RCS file: ACT/Handle.cpp
diff -N ACT/Handle.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/Handle.cpp 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,91 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/** \file Handle.cpp
+ */
+
+#include "Handle.hpp"
+
+namespace ACT {
+ //---------------
+ template< class T, template< class, class > class Aspect >
+ typename Handled< T, Aspect >::registry_type
+ Handled< T, Aspect >::our_registry ;
+
+ //---------------
+ template< class T, template< class, class > class Aspect >
+ typename Handle_Registry_Leader< T, Aspect >::handle_type
+ Handle_Registry_Leader< T, Aspect >::
+ add( T * that )
+ {
+ handle_type x( 0 ) ;
+ if ( free_handles.empty() ) {
+ // Assert no existing space in registry vector
+ x = handle_type( the_registry.size() ) ;
+ the_registry.push_back( that ) ;
+ aspect.add_in_new_place() ;
+ } else {
+ // Assert there's an existing slot in the registry
vector
+ x = free_handles.back() ;
+ free_handles.pop_back() ;
+ the_registry[ x ] = that ;
+ aspect.add_in_old_place() ;
+ }
+ return x ;
+ }
+
+ template< class T, template< class, class > class Aspect >
+ void
+ Handle_Registry_Leader< T, Aspect >::
+ remove( handle_type x )
+ {
+ try {
+ // Zero out the entry so that a bad index (however that
might happen) doesn't get reused.
+ the_registry.at( x ) = 0 ;
+ free_handles.push_back( x ) ;
+ } catch ( ... ) {
+ }
+ }
+
+ //---------------
+ template< class T, class Leader, template< class, class, class > class
Aspect >
+ typename Handle_Registry_Follower< T, Leader, Aspect >::reference
+ Handle_Registry_Follower< T, Leader, Aspect >::
+ operator[]( handle_type x )
+ {
+ if ( x >= the_registry.size() ) {
+ if ( x >= the_registry.capacity() ) {
+ // Assert the handle is outside of the
allocated bounds of the registry vector.
+ // Force a reservation, not knowing how
resize() works.
+ the_registry.reserve( x + 1 ) ;
+ aspect.expand_capacity_of_vector() ;
+ }
+ // Assert the handle is within the allocated size of
the registry vector.
+ the_registry.resize( x + 1 ) ;
+ aspect.enlarge_size_of_vector() ;
+ } else {
+ // Assert the handle is already within the bounds of
the present vector.
+ }
+ // Assert handle is within range of
+ aspect.access_from_existing_slot() ;
+ return the_registry[ x ] ;
+ }
+
+} // end of namespace ACT
Index: ACT/Handle.hpp
===================================================================
RCS file: ACT/Handle.hpp
diff -N ACT/Handle.hpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/Handle.hpp 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,332 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/** \file Handle.hpp
+ * \brief A handle is a type-safe, encapsulated integer that's opaque to
its ordinary users.
+ * A handled class is one whose constructor adds it to a singleton
registry,
+ * allowing handles rather than pointers where appropriate.
+ */
+
+#pragma once
+#ifndef __Handle_hpp___
+#define __Handle_hpp___
+
+#include "Aspect.hpp"
+#include <vector>
+
+namespace ACT {
+ //-------------------------
+ /** \class Handle
+ * \brief A marked, encapsulate ordinal, used as an index in
offset operations.
+ *
+ * - template parameter \c T: parametric so it can match both
<tt>std::vector< X >::size_type</tt> and others
+ * - template parameter \c Marker: creates type-distinction to
prevent intermixing of indices
+ *
+ * \pre
+ * - class T is an integral type
+ */
+ template< class T, class Marker >
+ class Handle
+ {
+ // friend classes
+ template< class T, class Marker > friend class
Vector_with_Handle_Index ;
+
+ /// A handle is an encapsulated integral type
+ T the_index ;
+
+ /// Unwrapper is friends-only
+ inline T get() { return the_index ; }
+ public:
+ /// Expose Marker so that multiple vectors can share a common
handle type
+ typedef Marker marker_type ;
+
+ /// Explicit constructor is required to avoid accidental
indexing into non-compatible objects.
+ explicit Handle( T x )
+ : the_index( x ) {}
+
+ inline bool operator<( Handle & x ) { return the_index <
x.the_index ; }
+ inline bool operator<=( Handle & x ) { return the_index <=
x.the_index ; }
+ inline bool operator==( Handle & x ) { return the_index ==
x.the_index ; }
+ inline bool operator>=( Handle & x ) { return the_index >=
x.the_index ; }
+ inline bool operator>( Handle & x ) { return the_index >
x.the_index ; }
+ inline bool operator!=( Handle & x ) { return the_index !=
x.the_index ; }
+
+ /// Addition is not Handle-to-Handle, but Handle-to-integer,
because Handle is ordinal.
+ inline Handle operator+( unsigned int n ) { return Handle(
the_index + n ) ; }
+ } ;
+
+ //-------------------------
+ /** \class Vector_with_Handle_Index
+ * \brief A wrapper around std::vector, with its integral index
replaced by a handle.
+ */
+ template< class T, class Marker >
+ class Vector_with_Handle_Index
+ : public std::vector< T >
+ {
+ typedef std::vector< T > Base ; /// Our base class,
defined for legibility.
+ inline reference operator[]( size_type n ) { throw
std::exception() ; } /// Prohibit offset operation with
unwrapped index
+ inline const_reference operator[]( size_type n ) const { throw
std::exception() ; } /// Prohibit offset operation with unwrapped index
+ inline reference at( size_type n ) { throw std::exception() ; }
/// Prohibit offset operation with
unwrapped index
+ inline const_reference at( size_type n ) const { throw
std::exception() ; } /// Prohibit offset operation with
unwrapped index
+ inline void resize( size_type, T ) { throw std::exception() ; }
/// Prohibit resize operation with unwrapped index
+ inline void reserve( size_type ) { throw std::exception() ; }
/// Prohibit reserve operation with unwrapped index
+
+ public:
+ /// Declaration of index type
+ typedef Handle< size_type, Marker > handle_type ;
+
+ inline reference operator[]( handle_type n ) { return
Base::operator[]( n.get() ) ; } /// Replacement
unchecked offset operator
+ inline const_reference operator[]( handle_type n ) const {
return Base::operator[]( n.get() ) ; } /// Replacement unchecked offset
operator
+ inline reference at( handle_type n ) { return Base::at( n.get()
) ; } /// Replacement
checked offset operator
+ inline const_reference at( handle_type n ) const { return
Base::at( n.get() ) ; } /// Replacement
checked offset operator
+
+ inline handle_type size() const { return handle_type(
Base::size() ) ; } ///
Replacement size returning handle
+ inline void resize( handle_type n, T val = T() ) { return
Base::resize( n.get(), val ) ; } /// Replacement resize
with handle
+ inline void reserve( handle_type n ) { return Base::reserve(
n.get() ) ; } ///
Replacement reserve with handle
+ inline handle_type capacity() const { return handle_type(
Base::capacity() ) ; } /// Replacement
capacity returning handle
+ } ;
+
+ //-------------------------
+ template< class T, template< class, class > class > class Handled ;
+ //-------------------------
+ /** \class Handle_Registry_Leader
+ * \brief A registry that maps handles to instances of a handled
class.
+ *
+ * This registry is the normative one.
+ * Each instance of a class with a handle (that is, deriving from
\c Handled) appears within this registry.
+ * In other words, this registry provides a mechanism for
operationalizing the referent of a handle.
+ */
+ template< class T, template< class, class > class Aspect =
Null_Aspect_1 >
+ class Handle_Registry_Leader
+ {
+ /// The aspect type as actually used.
+ typedef Aspect< T, Handle_Registry_Leader > aspect_type ;
+
+ /// The aspect class is a friend
+ friend class aspect_type ;
+
+ /// The cooperative Handled aspect is also a friend.
+ friend typename Handled< T, Aspect >::aspect_type ;
+
+ /// Type declaration of the class registry
+ typedef Vector_with_Handle_Index< T *, Handle_Registry_Leader >
vector_type ;
+
+ public:
+ /// Proxy the declaration of handle type.
+ typedef typename vector_type::handle_type handle_type ;
+
+ private:
+ /// Vector holding pointers to constructed items.
+ vector_type the_registry ;
+
+ /// Stack of free indices
+ std::vector< handle_type > free_handles ;
+
+ /// Aspect instance
+ aspect_type aspect ;
+
+ public:
+ /// Default constructor
+ Handle_Registry_Leader( aspect_type aspect = aspect_type() )
+ : aspect( aspect )
+ {}
+
+ /// Add an object to the registry, returning its handle.
+ handle_type add( T * ) ;
+
+ /// Remove a handle from the registry.
+ void remove( handle_type ) ;
+
+ /// Offset access is simple because this class issues all its
own indices.
+ inline T * operator[]( handle_type x ) { return the_registry[ x
] ; }
+ } ;
+}
+
+namespace aspect {
+ //-------------------------
+ /** Null_Aspect_1
+ * \brief Partial specialization of generic aspect holds the hooks
for derived aspects
+ */
+ template< class T >
+ class Null_Aspect_1< T, ACT::Handle_Registry_Leader< T, Null_Aspect_1 >
>
+ {
+ public:
+ /// Called in \c Handle_Registry_Leader::add upon successful
addition that expands the internal size of the registry
+ void add_in_new_place() {}
+
+ /// Called in \c Handle_Registry_Leader::add upon successful
addition that reuses an existing entry within the registry
+ void add_in_old_place() {}
+ } ;
+}
+
+namespace ACT {
+ //-------------------------
+ /** \class Handle_Registry_Follower
+ * \brief A registry indexed by handles issued by a
Handle_Registry_Leader
+ */
+ template< class T, class Leader, template< class, class, class > class
Aspect = aspect::Null_Aspect_2 >
+ class Handle_Registry_Follower
+ {
+ /// The aspect type as actually used.
+ typedef Aspect< T, Leader, Handle_Registry_Follower >
aspect_type ;
+
+ /// The aspect class is a friend
+ friend class aspect_type ;
+
+ /// Marker class derived from Leader
+ typedef typename Leader::handle_type::marker_type marker_type ;
+
+ /// Type declaration of the class registry
+ typedef Vector_with_Handle_Index< T, marker_type > vector_type ;
+
+ /// Vector holding pointers to constructed items.
+ vector_type the_registry ;
+
+ public:
+ /// Proxy the declaration of handle type.
+ typedef typename vector_type::handle_type handle_type ;
+
+ /// Aspect instance
+ aspect_type aspect ;
+
+ public:
+ /// Default constructor
+ Handle_Registry_Follower( aspect_type aspect = aspect_type() )
+ : aspect( aspect )
+ {}
+
+ /// Reference to content item of this registry
+ typedef typename vector_type::reference reference ;
+
+ /// Offset access for follower requires a possible expansion of
the internal registry for an as-yet-unseen index.
+ reference operator[]( handle_type x ) ;
+ } ;
+}
+namespace aspect {
+ //-------------------------
+ /** Null_Aspect_2
+ * \brief Partial specialization of generic aspect holds the hooks
for derived aspects
+ */
+ template< class T, class Leader >
+ class Null_Aspect_2< T, Leader, ACT::Handle_Registry_Follower< T,
Leader, Null_Aspect_2 > >
+ {
+ public:
+ inline void access_from_existing_slot() {} ;
+ inline void expand_capacity_of_vector() {} ;
+ inline void enlarge_size_of_vector() {} ;
+ } ;
+}
+namespace ACT {
+ //-------------------------
+ /** \class Handled
+ * \brief A base class for handled classes.
+ * To use, use the derived class as the template
parameter, as follows:
+ * class X : public class Handled< X > { ... } ;
+ *
+ * This class has the responsibility of defining a class registry
for each class T.
+ */
+ template< class T, template< class, class > class Aspect =
aspect::Null_Aspect_1 >
+ class Handled
+ {
+ public:
+ /// The aspect type as actually used.
+ typedef Aspect< T, Handled > aspect_type ;
+
+ /// The aspect class is a friend
+ friend class aspect_type ;
+
+ private:
+ /// Type declaration of the class registry
+ typedef Handle_Registry_Leader< T, Aspect > registry_type ;
+
+ /// Per-class registry.
+ ///
+ /// [EH 2007-06-25]
+ /// In MSVC8, this declaration must appear after that for
\c aspect_type,
+ /// otherwise the compiler says it's not defined in
this class.
+ /// This is a compiler defect.
+ /// The point of instantiation is supposed to be immediately
before the declaration containing the first instance,
+ /// but at a namespace or global level, not within
a class declaration.
+ /// That means that \c registry_type is supposed to be
instantiated before this class is.
+ /// Since visibility has an ordering dependence, I conclude the
class is not instantiated then,
+ /// immediately before this class, but rather
within the class.
+ /// In other words, MSVC8 has their point of instantiation
wrong.
+ static registry_type our_registry ;
+
+ public:
+ /// Proxy the declaration of handle type from registry type.
+ typedef typename registry_type::handle_type handle_type ;
+
+ private:
+ /// Enclosed handle
+ handle_type the_handle ;
+
+ protected:
+ /// Aspect helper instance.
+ ///
+ /// It's protected so that derived classes may access the
aspect.
+ /// This class is designed to be a base class, so this is a
generic need.
+ /// If a read-only version of the aspect is desired,
+ /// change the access control of this item to
private
+ /// and add a \c const accessor function returning
a reference.
+ aspect_type aspect ;
+
+ public:
+ /// Default constructor takes as parameter the \c this pointer
of a derived object.
+ Handled( T * that, aspect_type aspect = aspect_type() )
+ : the_handle( our_registry.add( that ) ),
+ aspect( aspect )
+ {
+ aspect.set_owner( this ) ;
+ }
+
+ /// Destructor
+ ~Handled() { our_registry.remove( the_handle ) ; }
+
+ /// Class method to access registry
+ static T * registry_at( handle_type x ) { return our_registry[
x ] ; }
+
+ /// Handle accessor
+ inline handle_type handle() const { return the_handle ; }
+ } ;
+
+ //-------------------------
+ /** \class Null_Aspect_Handled
+ * \brief Base for aspect classes of \c Handled
+ */
+ template< class T >
+ class Null_Aspect_Handled
+ {} ;
+
+} // end of namespace ACT
+
+namespace aspect {
+ //-------------------------
+ /** Null_Aspect_1
+ * \brief Default null aspect class, bound through default aspect
parameter
+ */
+ template< class T >
+ class Null_Aspect_1< T, ACT::Handled< T, Null_Aspect_1 > >
+ : public ACT::Null_Aspect_Handled< T >,
+ public Null_Aspect_Base< ACT::Handled< T, Null_Aspect_1 > >
+ {} ;
+}
+
+#endif // end of inclusion protection
Index: ACT/Listen.T.cpp
===================================================================
RCS file: ACT/Listen.T.cpp
diff -N ACT/Listen.T.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/Listen.T.cpp 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,99 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/// \file Listen.T.cpp
+/// \brief Implementations of a set of simple actions with which to test the
scheduler
+
+#include "Listen.hpp"
+
+namespace ACT {
+ //--------------------------------------------------
+ // Basic_Listen_Monitor
+ //--------------------------------------------------
+ template< class Listener >
+ void
+ Basic_Listen_Monitor< Listener >::
+ add_ready_listener_task( wakeup_listener * w )
+ {
+ ready_list.push_back( w ) ;
+ }
+
+ template< class Listener >
+ ACT_State
+ Basic_Listen_Monitor< Listener >::
+ wake_up_ready_tasks()
+ {
+ if ( ready_list.empty() ) {
+ // This monitor is no longer necessary, since there's
nothing to wake up.
+ // Therefore we return complete and let the scheduler
remove this instance.
+ // We first have to remove ourselves from the follower
registry, in order to be re-created when needed.
+
+ // Note that we only return Completed when the ready
list is empty at the start of execution.
+ // This satisfies the service requirement
+ // that a service action may not both
reschedule a task and complete itself in the same invocation.
+ return set_completed() ;
+ }
+ do {
+ ( * ready_list.back() )() ;
+ ready_list.pop_back() ;
+ } while ( ! ready_list.empty() ) ;
+ return set_ready() ;
+ }
+
+ //--------------------------------------------------
+ // Basic_Listening_Task
+ //--------------------------------------------------
+ // Class registry definition
+ template< class Listener, class Monitor >
+ typename Basic_Listening_Task< Listener, Monitor
>::follower_registry_type
+ Basic_Listening_Task< Listener, Monitor >::schedulers ;
+
+ //-------------------------
+ template< class Listener, class Monitor >
+ void
+ Basic_Listening_Task< Listener, Monitor >::
+ register_for_wakeup( Listener * that, wakeup_listener * w )
+ {
+ if ( w == 0 ) return ;
+ // Assert wakeup listener is non-trivial.
+
+ handle_type k = w -> scheduler() -> handle() ;
+ // Assert k is the handle to the scheduler of origin for our
wakeup_listener
+ shared_ptr< monitor_type > p = schedulers[ k ].lock() ;
+ // Assert p is the monitor associated with our scheduler, if
one exists.
+
+ // Ensure monitor exists
+ if ( ! p ) {
+ // Assert monitor does not yet exist
+ p = shared_ptr< monitor_type >( new monitor_type() ) ;
+ schedulers[ k ] = boost::weak_ptr< monitor_type >( p ) ;
+ // Monitor exists but it's not yet scheduled (invariant
violation)
+ w -> scheduler() -> add_service( act( p ) ) ;
+ // Assert monitor exists in registry and it's scheduled
(invariant satisfied)
+ }
+ // Assert listening monitor for this class exists
+ // Assert p == schedulers[ k ].lock() && p != 0
+
+ // Add the current instance to the monitor associated with our
wakeup listener
+ p -> add_wakeup_item( that, w ) ;
+ }
+
+ //-------------------------
+} // end namespace ACT
\ No newline at end of file
Index: ACT/Listen.hpp
===================================================================
RCS file: ACT/Listen.hpp
diff -N ACT/Listen.hpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/Listen.hpp 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,138 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/// \file Listen.hpp
+
+#pragma once
+#ifndef __Listen_hpp__
+#define __Listen_hpp__
+
+#include "ACT/Scheduler.hpp"
+#include "ACT/Handle.hpp"
+
+#include <boost/weak_ptr.hpp>
+#include <vector>
+
+namespace ACT {
+ //-------------------------
+ /** \class Basic_Listen_Monitor
+ * \brief Base class for monitor service actions.
+ *
+ * Collaborators:
+ * - Basic_Listening_Task. Tasks register themselves here
when they need to wake up.
+ * - Scheduler. This action runs as a service within the
scheduler.
+ * While this class uses no specific knowledge of
its scheduler, it satisfies the requirements for a service action.
+ * - wakeup_listener. Calls this is a function object to
effect a wake-up.
+ * Responsibilities:
+ * - Hold a record of each task that is waiting and won't
again run until this class wakes it up.
+ * - Run as a service in the same scheduler that each task
is also in.
+ * - When activated, wake up waiting tasks that have
become ready.
+ * Note: this is not a postcondition for monitors
generally.
+ * A monitor might only wake up a subset of its
ready tasks at each activation.
+ */
+ template< class Listener >
+ class Basic_Listen_Monitor
+ : public simple_act
+ {
+ /// Container for actions ready to run.
+ ///
+ /// \par Future
+ /// The vector used currently will be replaced by
one provided by the scheduling queue.
+ /// Since each task is present in at most one
monitor list,
+ /// we may eliminate an entire dynamic
allocation issue by allocating them within the scheduling queue.
+ std::vector< wakeup_listener * > ready_list ;
+
+ protected:
+ /// Run through the ready list and wake up all the tasks on it,
removing them from the ready list.
+ ///
+ /// This is typically the last statement in the action body of
a derived monitor.
+ /// \post
+ /// - return value is either Completed or Working
+ ACT_State wake_up_ready_tasks() ;
+
+ /// Add an item directly to the ready list, skipping readiness
checking
+ ///
+ /// Since the item is known to be ready, it needs no further
examination.
+ /// It need not appear in the parameter list, in
contradistinction to \c add_waiting_listener_task.
+ void add_ready_listener_task( wakeup_listener * ) ;
+
+ /// Add an item to the waiting list
+ void add_waiting_listener_task( Listener *, wakeup_listener * )
;
+ } ;
+
+ //-------------------------
+ /** \class Basic_Listening_Task
+ * \brief Base class for tasks that may suspend themselves and
listen for wakeup.
+ *
+ * Collaborators:
+ * - Basic_Listen_Monitor. An instance registers itself
with its monitor, upon which it relies for wake-up.
+ * - Scheduler. This action runs as a task within the
scheduler.
+ * Responsibilities.
+ * - Register self for later wake-up if it suspends
computation.
+ */
+ template< class Listener, class Monitor >
+ class Basic_Listening_Task
+ : public autonomous_act
+ {
+ /// The monitor type for these actions to register with.
+ typedef Monitor monitor_type ;
+
+ /// Type of handles to Scheduler
+ typedef Scheduler::handle_type handle_type ;
+
+ /// Type of the class registry of monitors
+ typedef typename Handle_Registry_Follower< boost::weak_ptr<
Monitor >, Scheduler > follower_registry_type ;
+
+ /** A vector of monitors, indexed by Scheduler handles.
+ *
+ * The cardinality relationship is either zero-or-one
monitor instance for each scheduler.
+ *
+ * \invariant
+ * - Each monitor within this registry is present in the
queue of its corresponding scheduler.
+ *
+ * Occurrences when this invariant might be violated:
+ * - When adding a monitor as a service, the add_service
call in the registry doesn't know about the registry.
+ * Therefore, we add it to the registry when
adding a listening monitor service.
+ * - When a monitor completes (say, having nothing left to
listen for), the scheduler remove it from the queue.
+ * Therefore, when a monitor completes, it's
shared_ptr in the Scheduler goes away,
+ * so the weak_ptr in the follower
registry expires.
+ * - When a registry terminates, it might do so with
pending actions in its queue.
+ * While this is abnormal, it may also be
recoverable with a single execution context.
+ * The entire scheduling queue in terminated
scheduler goes out of scope,
+ * so, as with ordinary monitor
completion, the weak_ptr expires.
+ * Unlike the case of ordinary monitor completion,
the destructor for the scheduler
+ * runs before that of the monitor.
+ * Since the monitor is ignorant of its scheduler,
this makes no difference.
+ */
+ static follower_registry_type schedulers ;
+
+ protected:
+ /** \brief Register an action for wakeup
+ * \post
+ * - Monitor is registered in the scheduler and will
eventually run.
+ */
+ void register_for_wakeup( Listener * that, wakeup_listener * w
) ;
+
+ } ;
+
+ //-------------------------
+} // end namespace ACT
+
+#endif
Index: ACT/Pause_Demon.cpp
===================================================================
RCS file: ACT/Pause_Demon.cpp
diff -N ACT/Pause_Demon.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/Pause_Demon.cpp 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/// \file Pause_Demon.cpp
+/// \brief The Pause service suspends itself (and its thread) for a number
of milliseconds
+/// if the scheduling queue has no high-priority items.
+
+#include "Pause_Demon.hpp"
+#include <boost/thread/thread.hpp>
+#include <boost/thread/xtime.hpp>
+
+namespace ACT {
+ //-------------------------
+ ACT_State
+ Pause_Demon::
+ run()
+ {
+ if ( the_scheduler -> ordinary_tasks_available() )
+ return ACT_State::Ready ;
+
+ boost::xtime t ;
+ if ( 0 == xtime_get( & t, boost::TIME_UTC ) ) {
+ return set_bad() ;
+ }
+ t.nsec += ms_to_pause * 1000 * 1000 ;
+ boost::thread().sleep( t ) ;
+ return ACT_State::Ready ;
+ }
+
+ //-------------------------
+} // end namespace ACT
Index: ACT/Pause_Demon.hpp
===================================================================
RCS file: ACT/Pause_Demon.hpp
diff -N ACT/Pause_Demon.hpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/Pause_Demon.hpp 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,77 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/// \file Pause_Demon.hpp
+/// \brief The Pause service suspends itself (and its thread) for a number
of milliseconds
+/// if the scheduling queue has no high-priority items.
+
+#pragma once
+#ifndef __Pause_Demon_hpp__
+#define __Pause_Demon_hpp__
+
+#include "ACT.hpp"
+#include "Scheduler.hpp"
+
+namespace ACT {
+ //-------------------------
+ /** \class Pause_Demon
+ * \brief A service that does nothing for some number of
milliseconds if the scheduler has no tasks pending.
+ *
+ * This service is only pauses during quiet or quiescent operation
of a scheduler.
+ * The point is to reduce CPU load when nothing is happening.
+ * This class is not the most efficient for a low-load service,
+ * since it consumes some constant fraction of CPU
regardless of other load.
+ * At high load, this service consumes neglible CPU.
+ *
+ * \par Future
+ * For low-load and/or utility server applications, this service
should be replaced with one that simply blocks.
+ * Such a service would have to cooperate with all other listening
facilities, any of which could unblock it.
+ *
+ * \par Defects
+ * - The present implementation is immortal, preventing graceful
cooperative shutdown.
+ * It should be able to terminate itself under at least
one condition.
+ * For example, if no other tasks or services are present,
then this one too can end.
+ */
+ class Pause_Demon
+ : public simple_act
+ {
+ /// Configuration parameter.
+ ///
+ /// Should eventually transition to a template parameter.
+ static const unsigned int ms_to_pause = 20 ;
+
+ /// Action body.
+ ACT_State run() ;
+
+ /// Scheduler determines whether pause is necessary or not.
+ Scheduler * the_scheduler ;
+
+ public:
+ ///
+ Pause_Demon( Scheduler * sc )
+ : the_scheduler( sc )
+ {}
+
+ } ;
+
+ //-------------------------
+} // end namespace ACT
+
+#endif
\ No newline at end of file
Index: ACT/Scheduler.T.cpp
===================================================================
RCS file: ACT/Scheduler.T.cpp
diff -N ACT/Scheduler.T.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/Scheduler.T.cpp 10 Jul 2007 14:09:08 -0000 1.1
@@ -0,0 +1,163 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/// \file Scheduler.T.cpp
+
+#include "Scheduler.hpp"
+
+namespace ACT {
+ //--------------------------------------------------
+ // wakeup_listener_allocated
+ //--------------------------------------------------
+ template< class S >
+ wakeup_listener_allocated< S >::
+ wakeup_listener_allocated( size_t x, scheduler_pointer y )
+ : the_wakeup_listener( new Basic_Wakeup_Listener< S >( x, y ) )
{}
+
+ //--------------------------------------------------
+ // Basic_Wakeup_Listener
+ //--------------------------------------------------
+ template< class S >
+ void
+ Basic_Wakeup_Listener< S >::
+ operator()()
+ {
+ queue_type & the_queue = the_scheduler -> queue() ;
+ the_queue.item( permutation_index ).priority_category =
Ordinary ;
+ the_queue.reorder( permutation_index ) ;
+ }
+
+ //--------------------------------------------------
+ // Basic_Scheduler
+ //--------------------------------------------------
+ template< template< class > class Aspect >
+ Basic_Scheduler< Aspect >::
+ Basic_Scheduler( aspect_type aspect )
+ : Scheduler( this ),
+ operating( true ),
+ next_task_sequence_number( 1 ),
+ next_service_sequence_number( 1 ),
+ aspect( aspect )
+ {
+ aspect.set_owner( this ) ;
+ }
+
+ //-------------------------
+ template< template< class > class Aspect >
+ void
+ Basic_Scheduler< Aspect >::
+ reset()
+ {
+ operating = true ;
+ }
+
+ //-------------------------
+ template< template< class > class Aspect >
+ void
+ Basic_Scheduler< Aspect >::
+ operator()()
+ {
+ aspect.run_begin() ;
+ while ( operating ) {
+ if ( ! aspect.run_guard() ) {
+ aspect.run_end_guard_violation() ;
+ return ;
+ }
+ activate_one_item() ;
+ }
+ aspect.run_end_ordinary() ;
+ }
+
+ //-------------------------
+ template< template< class > class Aspect >
+ void
+ Basic_Scheduler< Aspect >::
+ add_task( act x )
+ {
+ item_pointer item = the_queue.push( Basic_Scheduled_Item( x, ++
next_task_sequence_number ), this ) ;
+ }
+
+ template< template< class > class Aspect >
+ void
+ Basic_Scheduler< Aspect >::
+ add_service( act x )
+ {
+ item_pointer item = the_queue.push( Basic_Scheduled_Item( x, ++
next_service_sequence_number, Demon ), this ) ;
+ }
+
+ template< template< class > class Aspect >
+ void
+ Basic_Scheduler< Aspect >::
+ add_critical_service( act )
+ {
+ }
+
+ //-------------------------
+ template< template< class > class Aspect >
+ void
+ Basic_Scheduler< Aspect >::
+ activate_one_item()
+ {
+ // Note that this operation is not locked.
+ // As of this version, this is a single-threaded server.
+ if ( the_queue.empty() ) {
+ // If the queue is finally empty, we're done.
+ operating = false ;
+ return ;
+ // An alternate behavior would be to wait indefinitely
for another scheduled item.
+ // This is an asynchronous scheduler; it doesn't wait.
+ // To understand how this scheduler wakes up from
quiescence, look into service actions.
+ }
+ // Assert the_queue is not empty
+
+ queue_type::pointer item = the_queue.top_ptr() ;
+ ACT_State result = item -> the_action(
the_queue.auxiliary_top() -> get() ) ;
+ if ( result.working() ) {
+ switch ( item -> action_type )
+ {
+ case Task :
+ // Assert action is not a service
+ item -> priority_category = Waiting ;
+ the_queue.reorder( item ) ;
+ break ;
+ case Demon :
+ // Always reset the sequence number for
a demon.
+ // The resulting behavior is to cycle
through all available demons.
+ item -> sequence_number =
next_service_sequence_number ++ ;
+ the_queue.reorder( item ) ;
+ break ;
+ }
+ } else {
+ the_queue.pop() ;
+ // Perhaps we might want to log items gone bad here.
+ }
+ }
+
+ //-------------------------
+ template< template< class > class Aspect >
+ bool
+ Basic_Scheduler< Aspect >::
+ ordinary_tasks_available()
+ {
+ if ( the_queue.empty() ) return false ;
+ return the_queue.top().priority_category <= Ordinary ;
+ }
+
+} // end namespace ACT
Index: ACT/test_support/Supplied_Service.cpp
===================================================================
RCS file: ACT/test_support/Supplied_Service.cpp
diff -N ACT/test_support/Supplied_Service.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/test_support/Supplied_Service.cpp 10 Jul 2007 14:09:09 -0000
1.1
@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/// \file Supplied_Service.cpp
+/// \brief A service that takes an outside supply of actions and supplies them
as a service.
+
+#include "Supplied_Service.hpp"
+
+namespace ACT {
+ shared_ptr< basic_act >
+ Supplied_Generator::
+ next_action( wakeup_listener * )
+ {
+ if ( ! complete ) {
+ if ( ! the_tasks.empty() ) {
+ shared_ptr< basic_act > x = the_tasks.front() ;
+ the_tasks.pop_front() ;
+ return x ;
+ } else {
+ if ( ! active ) complete = true ;
+ }
+ /// Assert no more tasks left to return
+ }
+ return shared_ptr< basic_act >() ;
+ }
+
+ void
+ Supplied_Generator::
+ add_task( shared_ptr< basic_act > x )
+ {
+ if ( ! active ) throw std::exception( "Not accepting new
actions after shutdown" ) ;
+ the_tasks.push_back( x ) ;
+ }
+
+} // end namespace ACT
+
+#include "ACT/Service.cpp"
+namespace ACT {
+ template Service< Supplied_Service_Aspect > ;
+}
Index: ACT/test_support/Supplied_Service.hpp
===================================================================
RCS file: ACT/test_support/Supplied_Service.hpp
diff -N ACT/test_support/Supplied_Service.hpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ACT/test_support/Supplied_Service.hpp 10 Jul 2007 14:09:09 -0000
1.1
@@ -0,0 +1,121 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/// \file Supplied_Service.hpp
+/// \brief A service that takes an outside supply of actions and supplies them
as a service.
+
+#pragma once
+#ifndef __Supplied_Service_hpp__
+#define __Supplied_Service_hpp__
+
+#include "ACT/Service.hpp"
+#include "Action_Tracing.hpp"
+#include <list>
+
+namespace ACT {
+ //-------------------------
+ /** \class Supplied_Generator
+ * \brief A generator whose entries are added manually one by one.
+ */
+ class Supplied_Generator
+ : public Generator
+ {
+ /// List of pending actions.
+ std::list< shared_ptr< basic_act > > the_tasks ;
+
+ /// Remove the first pending action in our internal list and
return it.
+ shared_ptr< basic_act > next_action( wakeup_listener * ) ;
+
+ /// The active-vs.-shutdown state of this generator.
+ bool active ;
+
+ ///
+ bool complete ;
+
+ public:
+ /// Default constructor starts off in active state.
+ Supplied_Generator()
+ : active( true ), complete( false ) {}
+
+ /// This \c shutdown routine pushes out all pending actions,
accepting no new ones.
+ void shutdown() { active = false ; }
+
+ ///
+ void add_task( shared_ptr< basic_act > ) ;
+
+ ///
+ bool completed() { return complete ; }
+ } ;
+
+ //-------------------------
+ // Aspect for Service base class
+ template< class > class Supplied_Service_Aspect ;
+
+ //-------------------------
+ // Supplied_Service_Aspect
+ /**
+ * \brief Aspect for class \c Service that tracks the run function
+ */
+ template<>
+ class Supplied_Service_Aspect< Service< Supplied_Service_Aspect > >
+ : public Service_Null_Aspect,
+ public aspect::Aspect_Has_Access_To_Owner< Service<
Supplied_Service_Aspect > >
+ {
+ /// Tracking
+ std::auto_ptr< tracking_function > tracker ;
+
+ public:
+ Supplied_Service_Aspect( tracking_function * t )
+ : tracker( t )
+ {}
+
+ void log_run_begin() { if ( tracker.get() != 0 ) ( * tracker )(
"" ) ; }
+ } ;
+
+ //-------------------------
+ /** \class Supplied_Service
+ * \brief A service whose tasks are manually added one by one.
+ */
+ class Supplied_Service
+ : public Service< Supplied_Service_Aspect >
+ {
+ /// Aspect type for \c Service base class
+ typedef Supplied_Service_Aspect< Service<
Supplied_Service_Aspect > > service_base_aspect_type ;
+
+ /// Member allocation for our generator
+ Supplied_Generator the_generator ;
+
+ public:
+ /// Default constructor
+ Supplied_Service( Scheduler & z, tracking_function * t = 0 )
+ : Service( the_generator, z, service_base_aspect_type(
t ) )
+ {}
+
+ ///
+ inline void shutdown() { the_generator.shutdown() ; }
+
+ ///
+ inline void add_task( shared_ptr< basic_act > x ) {
the_generator.add_task( x ) ; }
+ } ;
+
+ //-------------------------
+} // end namespace ACT
+
+#endif
Index: HTTP/Change_Log.txt
===================================================================
RCS file: HTTP/Change_Log.txt
diff -N HTTP/Change_Log.txt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ HTTP/Change_Log.txt 10 Jul 2007 14:09:10 -0000 1.1
@@ -0,0 +1,6 @@
+Change Log for GNU Cygnal, Module HTTP
+======================================
+
+2007-07-09 Eric Hughes <address@hidden>
+ * unit_tests/Test_HTTP.cpp: Duplicated Invalid_Version_Request test
into ordinary URI and *-URI forms.
+ * HTTP_Parse.[hc]pp: Fixed defect in Request_Scanner, which wasn't
looking explicitly for a space after the URI. It was relying on the URI
scanner to consume the next character, but since the URI scanner is used
elsewhere, it should not silently consume anything other than the URI itself.
Fixing this defect allowed the Invalid_Version_Request, *-version, to pass, but
unmasked the defect in URI scanning.
Index: Net/Change_Log.txt
===================================================================
RCS file: Net/Change_Log.txt
diff -N Net/Change_Log.txt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Net/Change_Log.txt 10 Jul 2007 14:09:11 -0000 1.1
@@ -0,0 +1,5 @@
+Change Log for GNU Cygnal, Module Net
+=====================================
+
+2007-07-06 Eric Hughes <address@hidden>
+ * socket_device.cpp: Stubbed out obsolete reaction to EINTR.
Index: Aspect.hpp
===================================================================
RCS file: Aspect.hpp
diff -N Aspect.hpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Aspect.hpp 10 Jul 2007 14:09:11 -0000 1.1
@@ -0,0 +1,135 @@
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of GNU Cygnal.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+/** \file Aspect.hpp
+ * \brief An aspect is a hook for augmenting the behavior of a class at
compile time.
+ */
+
+#pragma once
+#ifndef __Aspect_hpp___
+#define __Aspect_hpp___
+
+namespace aspect {
+
+ //--------------------------------------------------
+ // Base null aspect classes for specialization
+
+ /// Base Null_Aspect class for class that would otherwise be ordinary
classes (no template)
+ template< class Owner >
+ class Null_Aspect_0
+ {} ;
+
+ /// Base Null_Aspect class for class that would otherwise have a single
template parameter
+ template< class T, class Owner >
+ class Null_Aspect_1
+ {} ;
+
+ /// Base Null_Aspect class for class that would otherwise have two
template parameters
+ template< class T1, class T2, class Owner >
+ class Null_Aspect_2
+ {} ;
+
+ //--------------------------------------------------
+ /** \class Null_Aspect_Base
+ *
+ * Specializations of null aspect templates, required to create
hook points, do not inherit from their generic template.
+ * This class provides such a base.
+ * In order that null templates may derive from it, it does not
define any data.
+ *
+ * This base is needed to provide a null definition of the hooks
provided by other add-in classes within this module.
+ * The first one of these is \c set_owner(), needed for an aspect
to gain access its owner's internal data.
+ * When other add-ins are defined, put a null function definition
here for each function in the add-in.
+ */
+ template< class Owner >
+ class Null_Aspect_Base
+ {
+ public:
+ /// The owner type is the class of which this class is an
aspect.
+ typedef Owner owner_type ;
+
+ /// For the null aspect set_owner does nothing.
+ inline void set_owner( Owner * x ) {}
+ } ;
+
+ //--------------------------------------------------
+ /** \class Aspect_Has_Access_To_Owner
+ * \brief Base class for aspects that require access to their
owner.
+ *
+ * Not all aspects require access to their owner class.
+ * Universally, null aspects don't, because the operations they
define don't do anything.
+ * Access to an owner requires storing a pointer, so a null aspect
couldn't have one anyway,
+ * since a null aspect must not define storage (otherwise
it's not null).
+ */
+ template< class Owner >
+ class Aspect_Has_Access_To_Owner
+ {
+ /// This class is a wrapper around a pointer to its owner.
+ Owner * the_owner ;
+
+ public:
+ /// Default constructor
+ Aspect_Has_Access_To_Owner()
+ : the_owner( 0 ) {}
+
+ /// Accessor to owner
+ inline Owner * owner() const { return the_owner ; }
+
+ /// Owner must be set after construction, because 'this' isn't
known before the aspect instance is constructed.
+ inline void set_owner( Owner * x ) { the_owner = x ; }
+ } ;
+
+ //--------------------------------------------------
+ /** \class Aspect_Has_Const_Access_To_Owner
+ * \brief Base class for aspects that require read access to their
owner, but not write access.
+ *
+ * Not all aspects require access to their owner class.
+ * Universally, null aspects don't, because the operations they
define don't do anything.
+ * Access to an owner requires storing a pointer, so a null aspect
couldn't have one anyway,
+ * since a null aspect must not define storage (otherwise
it's not null).
+ */
+ template< class Owner >
+ class Aspect_Has_Const_Access_To_Owner
+ {
+ /// This class is a wrapper around a pointer to its owner.
+ const Owner * the_owner ;
+
+ public:
+ /// Default constructor
+ Aspect_Has_Const_Access_To_Owner( const Owner * x )
+ : the_owner( x ) {}
+
+ /// Accessor to owner
+ inline const Owner * owner() const { return the_owner ; }
+ } ;
+
+ //--------------------------------------------------
+ /**
+ */
+} // end namespace aspect
+
+
+// This should move to config.h, perhaps
+#ifdef _MSC_VER
+// Disable the warning about "'this' uses in base member initializer list
+# pragma warning(disable:4355)
+#else
+#endif
+
+#endif // end of inclusion protection
Index: Change_Log.txt
===================================================================
RCS file: Change_Log.txt
diff -N Change_Log.txt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Change_Log.txt 10 Jul 2007 14:09:11 -0000 1.1
@@ -0,0 +1,24 @@
+Change Log for GNU Cygnal
+=========================
+
+2007-07-09 Eric Hughes <address@hidden>
+ * ACT/ACT.hpp: Changed ACT_State::Waiting to Would_Block. Modified
convenience methods accordingly.
+ * ACT/Pause_Service.cpp, ACT/test_support/Listening_Actions.cpp,
HTTP/HTTP_Behavior.cpp: followed ACT.hpp changes.
+ * ACT/unit_tests/Test_ACT.cpp: Improved act_twice to ensure guard on
run() is in effect.
+ * IO/Stream_Consumer.cpp: Removed defect that was masking failures in
scanning. Change causes an HTTP unit test to fail.
+
+2007-07-06 Eric Hughes <address@hidden>
+ * ACT/ACT.hpp: Converted ACT_State from an enumeration to a class.
Removed convenience typedef.
+ * IO/Stream_Consumer.hpp: Added source_state() to assist in writing
parsing filters.
+ * Lots and lots of files: Renamed act_state to ACT_State everywhere.
Changed constant references to Working to either Waiting or Ready, as
appropriate. Changed set_working() to set_ready(), set_waiting(), or
source_state(), as appropriate.
+
+2007-07-06 Eric Hughes <address@hidden>
+ * doc/Doxyfile: Converted all paths to relative form.
+ * doc/mainpage.doxygen.txt: Wrote new main page.
+ * ACT/ACT.doxygen.txt: Wrote new page with overview of ACT.
+
+2007-06-28 Eric Hughes <address@hidden>
+ * doc/Doxyfile: New file.
+
+2007-06-17 Eric Hughes <address@hidden>
+ * ACT/*: Got listener wakeup working correctly in scheduler.
Index: mainpage.doxygen.txt
===================================================================
RCS file: mainpage.doxygen.txt
diff -N mainpage.doxygen.txt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ mainpage.doxygen.txt 10 Jul 2007 14:09:12 -0000 1.1
@@ -0,0 +1,36 @@
+/**
+
+\mainpage GNU Cygnal
+
+\section s_Introduction Introduction
+
+ Documentation for the source code of GNU Cygnal.
+
+\section s_Code_Organization Code Organization
+
+ The code is organized into a set of modules:
+ - \ref ACT.
+ Asynchronous Computation Task.
+ The multitasking foundation of the system.
+ - IO.
+ Input/Output.
+ ACT-enabled I/O infrastructure.
+ Provides scattered buffering and the conversion of asynchronous
block I/O into an asynchronous stream abstraction.
+ - Net.
+ Network I/O.
+ ACT-enabled network primitives.
+ - HTTP.
+ HTTP syntax and protocol behavior.
+
+\section s_Running_Doxygen Running Doxygen [EH as of 2007-07-05]
+
+ Doxygen doesn't deal so well with code that makes heavy use of
templates.
+ Here's a <a
href="http://bugzilla.gnome.org/buglist.cgi?query_format=advanced&short_desc_type=allwordssubstr&short_desc=template&product=doxygen&long_desc_type=substring&long_desc=&status_whiteboard_type=allwordssubstr&status_whiteboard=&keywords_type=allwords&keywords=&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=NEEDINFO&emailassigned_to1=1&emailtype1=substring&email1=&emailassigned_to2=1&emailreporter2=1&emailqa_contact2=1&emailcc2=1&emailtype2=substring&email2=&bugidtype=include&bug_id=&chfieldfrom=&chfieldto=Now&chfieldvalue=&cmdtype=doit&order=Bug+Number&field0-0-0=noop&type0-0-0=noop&value0-0-0=">search
for doxygen template defects</a>.
+ While it would be a good thing for doxygen to run without errors,
that's not happening now.
+ The two most common defects seem to be these:
+ - No recognition of explicit template instantiation:
http://bugzilla.gnome.org/show_bug.cgi?id=331519.
+ - Conflation of members in template specifications:
http://bugzilla.gnome.org/show_bug.cgi?id=406027.
+ There are a couple of other errors doxygen spits out.
+ I haven't located them in the doxygen issue tracker.
+
+ */
\ No newline at end of file
Index: doc/Doxyfile
===================================================================
RCS file: doc/Doxyfile
diff -N doc/Doxyfile
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ doc/Doxyfile 10 Jul 2007 14:09:12 -0000 1.1
@@ -0,0 +1,264 @@
+# Doxyfile 1.5.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "GNU Cygnal"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = doc
+CREATE_SUBDIRS = YES
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = YES
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file( $line) : $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = .
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.dox \
+ *.py \
+ *.doxygen.txt
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS = BOOST_AUTO_UNIT_TEST
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = YES
+TREEVIEW_WIDTH = 350
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH = .
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
Index: ACT/Pause_Service.cpp
===================================================================
RCS file: ACT/Pause_Service.cpp
diff -N ACT/Pause_Service.cpp
--- ACT/Pause_Service.cpp 1 Jul 2007 10:53:50 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,48 +0,0 @@
-//
-// Copyright (C) 2007 Free Software Foundation, Inc.
-//
-// This file is part of GNU Cygnal.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-/// \file Pause_Service.hpp
-/// \brief The Pause service suspends itself (and its thread) for a number
of milliseconds
-/// if the scheduling queue has no high-priority items.
-
-#include "Pause_Service.hpp"
-#include <boost/thread/thread.hpp>
-#include <boost/thread/xtime.hpp>
-
-namespace ACT {
- //-------------------------
- act_state
- Pause_Service::
- run()
- {
- if ( the_scheduler -> ordinary_tasks_available() )
- return Working ;
-
- boost::xtime t ;
- if ( 0 == xtime_get( & t, boost::TIME_UTC ) ) {
- return set_bad() ;
- }
- t.nsec += ms_to_pause * 1000 * 1000 ;
- boost::thread().sleep( t ) ;
- return Working ;
- }
-
- //-------------------------
-} // end namespace ACT
Index: ACT/Pause_Service.hpp
===================================================================
RCS file: ACT/Pause_Service.hpp
diff -N ACT/Pause_Service.hpp
--- ACT/Pause_Service.hpp 1 Jul 2007 10:53:51 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,61 +0,0 @@
-//
-// Copyright (C) 2007 Free Software Foundation, Inc.
-//
-// This file is part of GNU Cygnal.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-/// \file Pause_Service.hpp
-/// \brief The Pause service suspends itself (and its thread) for a number
of milliseconds
-/// if the scheduling queue has no high-priority items.
-
-#pragma once
-#ifndef __Pause_Service_hpp__
-#define __Pause_Service_hpp__
-
-#include "ACT.hpp"
-#include "Scheduler.hpp"
-
-namespace ACT {
- //-------------------------
- /** \class Pause_Service
- */
- class Pause_Service
- : public simple_act
- {
- /// Configuration parameter.
- ///
- /// Should eventually transition to a template parameter.
- static const unsigned int ms_to_pause = 20 ;
-
- /// Action body.
- act_state run() ;
-
- /// Scheduler determines whether pause is necessary or not.
- Basic_Scheduler * the_scheduler ;
-
- public:
- ///
- Pause_Service( Basic_Scheduler * sc )
- : the_scheduler( sc )
- {}
-
- } ;
-
- //-------------------------
-} // end namespace ACT
-
-#endif
\ No newline at end of file
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash/cygnal ACT/ACT.hpp ACT/Change_Log.txt ACT...,
Eric Hughes <=