gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash/cygnal/ACT ACT.hpp Cygnal_Instances.cpp S...


From: Eric Hughes
Subject: [Gnash-commit] gnash/cygnal/ACT ACT.hpp Cygnal_Instances.cpp S...
Date: Tue, 19 Jun 2007 18:52:26 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Eric Hughes <eh9>       07/06/19 18:52:26

Modified files:
        cygnal/ACT     : ACT.hpp Cygnal_Instances.cpp Scheduler.cpp 
                         Scheduler.hpp Scheduling_Queue.cpp 
                         Scheduling_Queue.hpp 
        cygnal/ACT/test_support: Listening_Actions.cpp 
                                 Listening_Actions.hpp 
        cygnal/ACT/unit_tests: Test_Scheduler.cpp 
                               Test_Scheduling_Queue.cpp 
Added files:
        cygnal/ACT     : Change_Log.txt 

Log message:
        Scheduler to stable status.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/ACT.hpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Cygnal_Instances.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduler.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduler.hpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduling_Queue.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Scheduling_Queue.hpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/Change_Log.txt?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Listening_Actions.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/test_support/Listening_Actions.hpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/unit_tests/Test_Scheduler.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/cygnal/ACT/unit_tests/Test_Scheduling_Queue.cpp?cvsroot=gnash&r1=1.1&r2=1.2

Patches:
Index: ACT.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/ACT.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- ACT.hpp     13 Jun 2007 19:29:10 -0000      1.1
+++ ACT.hpp     19 Jun 2007 18:52:25 -0000      1.2
@@ -32,34 +32,7 @@
 
 namespace ACT {
 
-       //-------------------------
-       /** \class 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.
-        *
-        *      The archetype of a notification is that from an asynchronous 
system I/O call.
-        *      These notifications arrive various by event, queue item, 
callback, signal, and others.
-        *      Notification is a mechanism crying out for implementation 
hiding by means of an abstraction.
-        *      This type provides a standard way to do so.
-        *
-        *      The implementation pattern is an ACT call a wakeup_listener and 
that a scheduler
-        *              provide the function so called.
-        *      The scheduler should encapsulate its own notification receiver, 
however structured,
-        *              into a function object of this class, say, by binding a 
member function adapter.
-        *
-        *      Such a function object should be parameter of the ACT 
constructor, if required.
-        *
-        *      An alternate design would have to pass a wakeup_listener with 
each call.
-        *      This would be useful if a single ACT were variously handled by 
different scheduler objects.
-        *      This may, perhaps, be an opportunity for greater efficiency.
-        *      It's not clear as of this writing that such an interface is 
necessary.
-        */
-       class wakeup_listener
-       {
-       public:
-               virtual void operator()() =0 ;
-       } ;
+       class wakeup_listener ;
 
        //-------------------------
        /** \enum act_state

Index: Cygnal_Instances.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Cygnal_Instances.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- Cygnal_Instances.cpp        13 Jun 2007 19:29:11 -0000      1.1
+++ Cygnal_Instances.cpp        19 Jun 2007 18:52:25 -0000      1.2
@@ -32,6 +32,6 @@
 
 namespace ACT {
        // Explicit template instantiation.
-       template Scheduling_Queue< Basic_Scheduled_Item > ;
+       template Basic_Scheduler::queue_type ;
 
 } // end namespace ACT

Index: Scheduler.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Scheduler.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- Scheduler.cpp       13 Jun 2007 19:29:11 -0000      1.1
+++ Scheduler.cpp       19 Jun 2007 18:52:25 -0000      1.2
@@ -28,39 +28,61 @@
        // Basic_Scheduled_Item
        //--------------------------------------------------
        Basic_Scheduled_Item::
-       Basic_Scheduled_Item( act x, unsigned int n, Basic_Priority p )
+       Basic_Scheduled_Item( act x, unsigned int n, Action_Category 
action_type )
                : the_action( x ),
                sequence_number( n ),
-               priority_category( p )
-       {}
+               action_type( action_type )
+       {
+               switch ( action_type ) {
+                       case Task :
+                               priority_category = Initial ;
+                               break ;
+                       case Service :
+                               priority_category = Background ;
+                               break ;
+                       default :
+                               priority_category = Background ;
+                               break ;
+               }
+       }
 
        //-------------------------
        bool
        Basic_Scheduled_Item::
        operator<( const Basic_Scheduled_Item & x ) const
        {
-               return  priority_category < x.priority_category
-                       ||      sequence_number > x.sequence_number ;
+               return  priority_category > x.priority_category
+                       ||      (               priority_category == 
x.priority_category 
+                                       &&      sequence_number > 
x.sequence_number 
+                               ) ;
        }
 
        //--------------------------------------------------
-       // Basic_Scheduler
+       // wakeup_listener_allocated
        //--------------------------------------------------
-       // Class member initialization
-       Basic_Scheduler Basic_Scheduler::the_instance ;
+       wakeup_listener_allocated::
+       wakeup_listener_allocated( size_t x, scheduler_pointer y )
+               : the_wakeup_listener( new wakeup_listener( x, y ) ) {}
 
-       //-------------------------
-       // Class factory function member
-       Basic_Scheduler & 
-       Basic_Scheduler::obtain_scheduler()
+       //--------------------------------------------------
+       // wakeup_listener
+       //--------------------------------------------------
+       void
+       wakeup_listener::
+       operator()()
        {
-               return the_instance ;
+               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 )
+               : operating( true ),
+               next_sequence_number( 1 )
        {}
 
        //-------------------------
@@ -97,14 +119,14 @@
        Basic_Scheduler::
        add_task( act x )
        {
-               item_pointer item = the_queue.push( Basic_Scheduled_Item( x, ++ 
next_sequence_number ) ) ;
-               item -> listener = Basic_Wakeup_Listener( item, & the_queue ) ;
+               item_pointer item = the_queue.push( Basic_Scheduled_Item( x, ++ 
next_sequence_number ), this ) ;
        }
 
        void
        Basic_Scheduler::
-       add_service( act )
+       add_service( act x )
        {
+               item_pointer item = the_queue.push( Basic_Scheduled_Item( x, ++ 
next_sequence_number, Service ), this ) ;
        }
 
        void
@@ -130,11 +152,15 @@
                }
                // Assert the_queue is not empty
 
-               Scheduling_Queue< Basic_Scheduled_Item >::reference item = 
the_queue.top() ;
-               act_state result = item.the_action( & item.listener.get() ) ;   
        //.get() because .listener is optional<>
+               queue_type::pointer item = the_queue.top_ptr() ;
+               act_state result = item -> the_action( 
the_queue.auxiliary_top() -> get() ) ;
                if ( result == Working ) {
-                       item.priority_category = Waiting ;
-                       the_queue.reorder( the_queue.top_ptr() ) ;
+                       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.
@@ -150,16 +176,4 @@
                return the_queue.top().priority_category <= Ordinary ;
        }
 
-       //--------------------------------------------------
-       // Basic_Wakeup_Listener
-       //--------------------------------------------------
-       void
-       Basic_Wakeup_Listener::
-       operator()()
-       {
-               the_item -> priority_category = Ordinary ;
-               the_scheduler -> reorder( the_item ) ;
-       }
-
-
 } // end namespace ACT

Index: Scheduler.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Scheduler.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- Scheduler.hpp       13 Jun 2007 19:29:11 -0000      1.1
+++ Scheduler.hpp       19 Jun 2007 18:52:25 -0000      1.2
@@ -32,27 +32,81 @@
 
 namespace ACT {
 
-       //using boost::posix_time::ptime ;
-
        //-------------------------
-       /* Forward declarations for Basic_Wakeup_Listener
+       /* Forward declarations for wakeup_listener
         */
        struct Basic_Scheduled_Item ;
+       class Basic_Scheduler ;
+       class wakeup_listener_allocated ;
 
        //-------------------------
-       class Basic_Wakeup_Listener
-               : public wakeup_listener
+       /**     \class wakeup_listener_allocated
+        *      \brief A managed-storage wrapper for wakeup listener as it's 
used with the Scheduling_Queue
+        *
+        *      \par Plans
+        *      This class uses the ordinary heap for allocation on an 
item-by-item basis.
+        *      Since we know that we must have one object of this class 
allocated for each task,
+        *              we can optimize this memory use by allocating in bulk 
and providing a custom allocator.
+        *      On the other hand, since these objects are allocated only 
during the growth phase,
+        *              this allocation strategy has no performance penalty in 
the steady state,
+        *              except to the extent that excess memory usage causes 
unnecessary swapping.
+        */
+       class wakeup_listener_allocated
        {
        public:
                ///
-               typedef Scheduling_Queue< Basic_Scheduled_Item >::pointer 
item_pointer ;
+               typedef Basic_Scheduler * scheduler_pointer ;
+               // typedef wakeup_listener::scheduler_pointer scheduler_pointer 
;
+
+               ///
+               typedef scheduler_pointer constructor_parameter ;
 
+       private:
+               /// The wrapped pointer
+               ///
+               /// I'm using a shared_ptr here because this class must have a 
copy constructor for std::vector resizing.
+               /// An auto_ptr won't work with the default copy constructor.
+               boost::shared_ptr< wakeup_listener > the_wakeup_listener ;
+
+       public:
+               /// Ordinary constructor used after item is within a scheduling 
queue and its storage location is known.
+               wakeup_listener_allocated( size_t x, scheduler_pointer y ) ;
+
+               ///
+               wakeup_listener * get() const { return 
the_wakeup_listener.get() ; }
+
+               ///
+               inline void reconstruct( scheduler_pointer ) {} ;
+       } ;
+
+       //-------------------------
+       /** \class 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.
+        *
+        *      The archetype of a notification is that from an asynchronous 
system I/O call.
+        *      These notifications arrive various by event, queue item, 
callback, signal, and others.
+        *      Notification is a mechanism crying out for implementation 
hiding by means of an abstraction.
+        *      This type provides a standard way to do so.
+        *
+        *      The implementation pattern is an ACT call a wakeup_listener and 
that a scheduler
+        *              provide the function so called.
+        *      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
+       {
+       public:
                ///
-               typedef Scheduling_Queue< Basic_Scheduled_Item > * 
scheduler_pointer ;
+               typedef Basic_Scheduler * scheduler_pointer ;
 
        private:
+               ///
+               typedef Scheduling_Queue< Basic_Scheduled_Item, 
wakeup_listener_allocated > queue_type ;
+
                /// A pointer to the item to reschedule.
-               item_pointer the_item ;
+               size_t permutation_index ;
 
                /// We use the scheduler to reorder an item after we change its 
priority.
                scheduler_pointer the_scheduler ;
@@ -61,9 +115,12 @@
                /// The listener body.
                void operator()() ;
 
+               /// Accessor for the scheduler
+               inline scheduler_pointer scheduler() const { return 
the_scheduler ; }
+
                /// Ordinary constructor used after item is within a scheduling 
queue and its storage location is known.
-               Basic_Wakeup_Listener( item_pointer x, scheduler_pointer y )
-                       : the_item( x ), the_scheduler( y ) {}
+               wakeup_listener( size_t x, scheduler_pointer y )
+                       : permutation_index( x ), the_scheduler( y ) {}
        } ;
 
        //-------------------------
@@ -113,6 +170,9 @@
        struct Basic_Scheduled_Item
        {
                /// 
+               Action_Category action_type ;
+
+               /// 
                Basic_Priority priority_category ;
 
                ///
@@ -122,10 +182,7 @@
                act the_action ;
 
                ///
-               Basic_Scheduled_Item( act, unsigned int, Basic_Priority = 
Initial ) ;
-
-               ///
-               boost::optional< Basic_Wakeup_Listener > listener ;
+               Basic_Scheduled_Item( act x, unsigned int n, Action_Category 
action_type = Task ) ;
 
                /// Comparison operator for the priority queue
                bool operator<( const Basic_Scheduled_Item & ) const ;
@@ -135,7 +192,13 @@
        class Basic_Scheduler
        {
                ///
-               typedef Scheduling_Queue< Basic_Scheduled_Item >::pointer 
item_pointer ;
+               friend wakeup_listener ;
+
+               /// The type of our internal queue.
+               typedef Scheduling_Queue< Basic_Scheduled_Item, 
wakeup_listener_allocated > queue_type ;
+
+               ///
+               typedef queue_type::pointer item_pointer ;
 
                /// Activate the next action once.
                void activate_one_item() ;
@@ -144,18 +207,18 @@
                bool operating ;
 
                /// The live activation queue.
-               Scheduling_Queue< Basic_Scheduled_Item > the_queue ;
+               queue_type the_queue ;
+
+               /// Getter method for wakeup_listener
+               inline queue_type & queue() { return the_queue ; }
 
                /// Increasing sequence numbers upon scheduling implements a 
kind of LRU activation policy.
                unsigned int next_sequence_number ;
 
+       public:
                /// Default constructor is private to enforce singleton
                Basic_Scheduler() ;
 
-               ///
-               static Basic_Scheduler the_instance ;
-
-       public:
                /// Add an ordinary task into the scheduling queue.
                void add_task( act ) ;
 
@@ -179,9 +242,6 @@
 
                ///
                void reset() ;
-
-               /// Factory method for singleton pattern
-               static Basic_Scheduler & obtain_scheduler() ;
        } ;
 
 } // end namespace ACT

Index: Scheduling_Queue.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Scheduling_Queue.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- Scheduling_Queue.cpp        13 Jun 2007 19:29:11 -0000      1.1
+++ Scheduling_Queue.cpp        19 Jun 2007 18:52:25 -0000      1.2
@@ -28,22 +28,17 @@
 
 namespace ACT {
        //-------------------------
-       template< class T >
-       Scheduling_Queue< T >::
+       template< class T, class Aux >
+       Scheduling_Queue< T, Aux >::
        Scheduling_Queue()
                : n_queue_items( 0 )
        {}
 
        //-------------------------
-       /*
-The problem here is that the free list isn't ordered as it should be.
-Or else the problem here is that something.
-Blargh.
-        */
-       template< class T >
-       typename Scheduling_Queue< T >::pointer
-       Scheduling_Queue< T >::
-       push( const_reference item )
+       template< class T, class Aux >
+       typename Scheduling_Queue< T, Aux >::pointer
+       Scheduling_Queue< T, Aux >::
+       push( const_reference item, const typename Aux::constructor_parameter 
auxiliary )
        {
                size_t permutation_index ;
                // The new queue-index in both cases is n_queue_items, which is 
incremented afterwards.
@@ -52,25 +47,26 @@
                        // In this case the permutation index is the mutual 
size of the queue and the permutation.
                        permutation_index = n_queue_items ;
                        the_queue.push_back( Scheduled_Item< T >( item, 
permutation_index ) ) ; // operator[] would throw here
-                       permutation.push_back( n_queue_items ) ;                
                                                // ditto
+                       permutation.push_back( Auxiliary_Item< Aux >( 
n_queue_items, permutation_index, auxiliary ) ) ;         // ditto
                } else {
                        // Assert n_queue_items < the_queue.size()
                        // Assert the_queue has at least one deleted element
                        // In this case the permutation index to use it that of 
the first deleted element
                        permutation_index = the_queue[ n_queue_items 
].permutation_index ;
                        the_queue[ n_queue_items ] = Scheduled_Item< T >( item, 
permutation_index ) ;   // note that the Scheduled_Item is the same as above
-                       permutation[ permutation_index ] = n_queue_items ;
+                       // The reconstruct() call is ordinarily a no-op, since 
a wakeup_listener can be reused.
+                       // This call is present to support a possible aspect in 
the Auxiliary.
+                       permutation[ permutation_index 
].the_auxiliary.reconstruct( auxiliary ) ;
                }
                ++ n_queue_items ;
-
                size_t n = up_heap( n_queue_items - 1 ) ;
-               return pointer( n, this ) ;
+               return pointer( permutation_index, this ) ;
        }
 
        //-------------------------
-       template< class T >
+       template< class T, class Aux >
        void
-       Scheduling_Queue< T >::
+       Scheduling_Queue< T, Aux >::
        pop()
        {
                -- n_queue_items ;
@@ -79,21 +75,33 @@
        }
 
        //-------------------------
-       template< class T >
+       template< class T, class Aux >
        void
-       Scheduling_Queue< T >::
+       Scheduling_Queue< T, Aux >::
        reorder( pointer p )
        {
-               size_t z = permutation[ p.index ] ;
+               size_t z = permutation[ p.index ].priority_queue_index ;
                size_t x = down_heap( z ) ;
                if ( z != x ) return ;
                (void) up_heap( z ) ;
        }
 
        //-------------------------
-       template< class T >
+       template< class T, class Aux >
+       void
+       Scheduling_Queue< T, Aux >::
+       reorder( size_t permutation_index )
+       {
+               size_t z( permutation[ permutation_index ].priority_queue_index 
) ;
+               size_t x( down_heap( z ) ) ;
+               if ( z != x ) return ;
+               (void) up_heap( z ) ;
+       }
+
+       //-------------------------
+       template< class T, class Aux >
        void
-       Scheduling_Queue< T >::
+       Scheduling_Queue< T, Aux >::
        swap( size_t x, size_t y )
        {
                // Swap the items
@@ -102,17 +110,17 @@
                the_queue[ y ] = tmp ;
 
                // Update the permutation
-               permutation[ the_queue[ x ].permutation_index ] = x ;
-               permutation[ the_queue[ y ].permutation_index ] = y ;
+               permutation[ the_queue[ x ].permutation_index 
].priority_queue_index = x ;
+               permutation[ the_queue[ y ].permutation_index 
].priority_queue_index = y ;
        }
 
        //-------------------------
        /** \par Implementation
         *      This algorithm treat the_queue as an implicit binary heap.
         */
-       template< class T >
+       template< class T, class Aux >
        size_t
-       Scheduling_Queue< T >::
+       Scheduling_Queue< T, Aux >::
        up_heap( size_t item )
        {
                //      Guards:
@@ -135,9 +143,9 @@
        /** \par Implementation
         *      This algorithm treat the_queue as an implicit binary heap.
         */
-       template< class T >
+       template< class T, class Aux >
        size_t
-       Scheduling_Queue< T >::
+       Scheduling_Queue< T, Aux >::
        down_heap( size_t item )
        {
                //

Index: Scheduling_Queue.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/Scheduling_Queue.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- Scheduling_Queue.hpp        13 Jun 2007 19:29:11 -0000      1.1
+++ Scheduling_Queue.hpp        19 Jun 2007 18:52:25 -0000      1.2
@@ -74,19 +74,42 @@
                }
        } ;
 
+
+       //-------------------------
+       /** \class Scheduled_Item
+        *      \brief The full data that goes into the scheduling queue.
+        *              It includes the underlying item plus extra housekeeping 
information.
+        */
+       template< class Aux >
+       struct Auxiliary_Item
+       {
+               /// Index into the priority queue.
+               size_t priority_queue_index ;
+
+               /// The auxiliary item held at fixed location.
+               /// Designed for wakeup_listener.
+               Aux the_auxiliary ;
+
+               /// Ordinary constructor
+               Auxiliary_Item( size_t x, size_t permutation_index, typename 
Aux::constructor_parameter z )
+                       : priority_queue_index( x ), 
+                       the_auxiliary( permutation_index, z ) 
+               {} ;
+       } ;
+
        //-------------------------
        /** \class Scheduled_Item_Pointer
         */
-       template< class T >
+       template< class T, class Aux >
        class Scheduled_Item_Pointer
        {
-               template< class T > friend class Scheduling_Queue ;
+               template< class T, class Aux > friend class Scheduling_Queue ;
 
                size_t index ;
 
-               Scheduling_Queue< T > * the_scheduling_queue ;
+               Scheduling_Queue< T, Aux > * the_scheduling_queue ;
 
-               Scheduled_Item_Pointer( size_t x, Scheduling_Queue< T > * y )
+               Scheduled_Item_Pointer( size_t x, Scheduling_Queue< T, Aux > * 
y )
                        : index( x ), the_scheduling_queue( y ) {}
        public:
                inline T & operator*() {
@@ -110,8 +133,8 @@
         *      These extra permutation indices constitute a "free list" of 
available permutation slots for the creation of pointers.
         *
         *      \invariant
-        *      - (bijective permutation) permutation[ the_queue[ x 
].permutation_index ] == x
-        *      - (bijective permutation) the_queue[ permutation[ y ] 
].permutation_index == y
+        *      - (bijective permutation) permutation[ the_queue[ x 
].permutation_index ].priority_queue_index == x
+        *      - (bijective permutation) the_queue[ permutation[ y 
].priority_queue_index ].permutation_index == y
         *      - n_queue_items <= the_queue.size
         *      - permutation.size() == the_queue.size()
         *
@@ -121,10 +144,12 @@
         *      It might be more efficient later to put them in the same 
container 
         *              and provide adapters to simulate separate arrays.
         */
-       template< class T >
+       template< class T, class Aux >
        class Scheduling_Queue
        {
-               template< class T > friend class Scheduled_Item_Pointer ;
+               // friends
+               template< class T, class Aux > friend class 
Scheduled_Item_Pointer ;
+               friend class wakeup_listener ;
 
                /// The main queue for scheduled items.
                std::vector< Scheduled_Item< T > > the_queue ;
@@ -134,7 +159,7 @@
                size_t n_queue_items ;
 
                /// The heap functions maintain a permutation that provide a 
constant pointer into the item queue.
-               std::vector< size_t > permutation ;
+               std::vector< Auxiliary_Item< Aux > > permutation ;
 
                /// Swap two elements within the queue.
                /// Adjust the permutation accordingly.
@@ -155,12 +180,12 @@
 
                /// Item accessor for implementation of indirection in 
Scheduled_Item_Pointer
                T & item( size_t x ) {
-                       return the_queue[ permutation[ x ] 
].the_underlying_item ;
+                       return the_queue[ permutation[ x ].priority_queue_index 
].the_underlying_item ;
                }
 
                /// Item accessor for implementation of indirection in 
Scheduled_Item_Pointer
                T * item_ptr( size_t x ) {
-                       return & the_queue[ permutation[ x ] 
].the_underlying_item ;
+                       return & the_queue[ permutation[ x 
].priority_queue_index ].the_underlying_item ;
                }
 
        public:
@@ -168,7 +193,7 @@
                typedef T value_type ;
 
                /// We have a pointer type rather than an iterator type, since 
we cannot increment through the queue.
-               typedef Scheduled_Item_Pointer< T > pointer ;
+               typedef Scheduled_Item_Pointer< T, Aux > pointer ;
 
                /// A reference to a member of the queue
                typedef value_type & reference ;
@@ -183,7 +208,7 @@
                ///
                /// Note that the signature of this function differs from that 
of std::priority_queue, which returns void.
                /// We require a reference to be able to asynchronously wake up 
an action.
-               pointer push( const_reference ) ;
+               pointer push( const_reference, const typename 
Aux::constructor_parameter auxiliary ) ;
 
                /// Constant access to the top-priority item in the queue.
                reference top() { return the_queue[ 0 ].the_underlying_item ; }
@@ -194,11 +219,20 @@
                /// Remove the top item from the queue
                void pop() ;
 
+               /// Reorder the position of the indexed item.  Use this after 
its priority changes.
+               void reorder( size_t ) ;
+
                /// Reorder the position of the pointed-to item.  Use this 
after its priority changes.
                void reorder( pointer ) ;
 
                /// Return is true if queue has no items of any kind in it, 
waiting or not.
                bool empty() { return n_queue_items == 0 ; }
+
+               ///
+               inline Aux & auxiliary( size_t x ) { return permutation[ x 
].the_auxiliary ; }
+
+               ///
+               inline Aux * auxiliary_top() { return & permutation[ the_queue[ 
0 ].permutation_index ].the_auxiliary ; }
        } ;
 
 } // end namespace ACT

Index: test_support/Listening_Actions.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/test_support/Listening_Actions.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test_support/Listening_Actions.cpp  13 Jun 2007 19:29:12 -0000      1.1
+++ test_support/Listening_Actions.cpp  19 Jun 2007 18:52:26 -0000      1.2
@@ -28,6 +28,8 @@
        //--------------------------------------------------
        // 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 )
@@ -35,7 +37,7 @@
 
        void
        N_to_completion_Monitor::
-       add( N_to_completion *, wakeup_listener * w )
+       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.
@@ -51,6 +53,11 @@
        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() ;
@@ -99,12 +106,13 @@
        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() ) ;
-                       Basic_Scheduler::obtain_scheduler().add_service( act( 
the_monitor ) ) ;
+                       w -> scheduler() -> add_service( act( the_monitor ) ) ;
                }
                // Assert monitor exists
-               the_monitor -> add( this, w ) ;
+               the_monitor -> add_wakeup_item( this, w ) ;
        }
 
        //-------------------------

Index: test_support/Listening_Actions.hpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/test_support/Listening_Actions.hpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test_support/Listening_Actions.hpp  13 Jun 2007 19:29:12 -0000      1.1
+++ test_support/Listening_Actions.hpp  19 Jun 2007 18:52:26 -0000      1.2
@@ -24,7 +24,7 @@
 #ifndef __Listening_Actions_hpp__
 #define __Listening_Actions_hpp__
 
-#include "ACT/ACT.hpp"
+#include "ACT/Scheduler.hpp"
 #include "Action_Tracing.hpp"
 #include <boost/optional.hpp>
 #include <vector>
@@ -40,6 +40,9 @@
        class N_to_completion_Monitor
                : public simple_act
        {
+               /// A vector of schedulers
+               static std::vector< wakeup_listener::scheduler_pointer > 
schedulers ;
+
                std::vector< wakeup_listener * > listeners ;
 
                act_state run() ;
@@ -51,7 +54,7 @@
                /// Query whether there are any actions registered for wakeup.
                inline bool empty() { return listeners.empty() ; }
 
-               void add( N_to_completion *, wakeup_listener * ) ;
+               void add_wakeup_item( N_to_completion *, wakeup_listener * ) ;
        } ;
 
        //-------------------------

Index: unit_tests/Test_Scheduler.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/unit_tests/Test_Scheduler.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- unit_tests/Test_Scheduler.cpp       13 Jun 2007 19:29:12 -0000      1.1
+++ unit_tests/Test_Scheduler.cpp       19 Jun 2007 18:52:26 -0000      1.2
@@ -31,8 +31,7 @@
 
 BOOST_AUTO_UNIT_TEST( null )
 {
-       Basic_Scheduler & b = Basic_Scheduler::obtain_scheduler() ;
-       BOOST_REQUIRE( b.empty() ) ;
+       Basic_Scheduler b ;
 
        execution_trace tr ;
        b.add_task( act( new no_action( new simple_tracker( tr, "N" ) ) ) ) ;
@@ -44,12 +43,12 @@
        std::string expected( "ABC" ) ;
        BOOST_CHECK_MESSAGE( tr.result() == expected,
                "Found result " << tr.result() << ". Expected result " << 
expected << "." ) ;
+       BOOST_CHECK( b.empty() ) ;
 }
 
 BOOST_AUTO_UNIT_TEST( act_n_interleaved )
 {
-       Basic_Scheduler & b = Basic_Scheduler::obtain_scheduler() ;
-       b.reset() ;
+       Basic_Scheduler b ;
        BOOST_REQUIRE( b.empty() ) ;
 
        execution_trace tr ;
@@ -61,6 +60,7 @@
        std::string expected( "ABCABCBCCC" ) ;
        BOOST_CHECK_MESSAGE( tr.result() == expected,
                "Found result " << tr.result() << ". Expected result " << 
expected << "." ) ;
+       BOOST_CHECK( b.empty() ) ;
 }
 
 //--------------------------------------------------
@@ -68,7 +68,7 @@
 
 BOOST_AUTO_UNIT_TEST( pause_action )
 {
-       Basic_Scheduler & b = Basic_Scheduler::obtain_scheduler() ;
+       Basic_Scheduler b ;
        BOOST_REQUIRE( b.empty() ) ;
 
        Pause_Service x( & b ) ;

Index: unit_tests/Test_Scheduling_Queue.cpp
===================================================================
RCS file: /sources/gnash/gnash/cygnal/ACT/unit_tests/Test_Scheduling_Queue.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- unit_tests/Test_Scheduling_Queue.cpp        13 Jun 2007 19:29:12 -0000      
1.1
+++ unit_tests/Test_Scheduling_Queue.cpp        19 Jun 2007 18:52:26 -0000      
1.2
@@ -29,12 +29,12 @@
 
 // Include this implementation file in order to instantiate template
 #include "ACT/Scheduling_Queue.cpp"
-namespace ACT {
-       /** A test item to put into a scheduling queue.
+
+/** A test item to put into a scheduling queue.
         */
-       class test_item {
+class test_item {
                size_t it ;
-       public:
+public:
                explicit test_item( size_t x )
                        : it( x ) {}
 
@@ -42,27 +42,28 @@
                inline bool operator==( unsigned int x ) const { return it == x 
; }
                size_t get() { return it ; }
                void set( size_t n ) { it = n ; }
-       } ;
+} ;
 
-       // Explicit instantiation
-       template Scheduling_Queue< test_item > ;
-}
+// Explicit instantiation
+template ACT::Scheduling_Queue< test_item, ACT::wakeup_listener_allocated > ;
+
+typedef ACT::Scheduling_Queue< test_item, ACT::wakeup_listener_allocated > 
queue_type ;
+typedef queue_type::pointer pointer ;
 
 using namespace ACT ;
-typedef Scheduling_Queue< test_item >::pointer pointer ;
 
 //--------------------------------------------------
 BOOST_AUTO_UNIT_TEST( simple_queue_exercise )
 {
-       Scheduling_Queue< test_item > q ;
+       queue_type q ;
 
        test_item a( 1 ) ;
        test_item b( 2 ) ;
        test_item c( 3 ) ;
 
-       q.push( a ) ;
-       q.push( b ) ;
-       q.push( c ) ;
+       q.push( a, 0 ) ;
+       q.push( b, 0 ) ;
+       q.push( c, 0 ) ;
 
        pointer x( q.top_ptr() ) ;
        test_item it = * x ;
@@ -80,12 +81,12 @@
 void
 add_then_test_order( permutation_iterator::const_iterator begin, 
permutation_iterator::const_iterator end )
 {
-       Scheduling_Queue< test_item > q ;
+       queue_type q ;
        size_t permutation_size = end - begin ;
 
        size_t j ;
        for ( j = 0 ; j < permutation_size ; ++ j ) {
-               q.push( test_item( * begin ++ ) ) ;
+               q.push( test_item( * begin ++ ), 0 ) ;
        }
        for ( j = 0 ; j < permutation_size ; ++ j ) {
                pointer p( q.top_ptr() ) ;
@@ -114,15 +115,15 @@
 //--------------------------------------------------
 BOOST_AUTO_UNIT_TEST( another_simple_queue_exercise )
 {
-       Scheduling_Queue< test_item > q ;
+       queue_type q ;
 
        test_item a( 4 ) ;
        test_item b( 5 ) ;
        test_item c( 6 ) ;
 
-       q.push( a ) ;
-       q.push( b ) ;
-       q.push( c ) ;
+       q.push( a, 0 ) ;
+       q.push( b, 0 ) ;
+       q.push( c, 0 ) ;
 
        pointer x( q.top_ptr() ) ;
        test_item it = * x ;
@@ -172,7 +173,7 @@
 void
 add_then_reorder( const iterator begin, iterator middle, iterator end )
 {
-       Scheduling_Queue< test_item > q ;
+       queue_type q ;
 
        size_t n = middle - begin ;
        size_t n2 = end - middle ;
@@ -183,7 +184,7 @@
        /* Add elements to the queue from middle to end
         */
        for ( j = 0 ; j < n2 ; ++ j ) {
-               q.push( test_item( * i ++ ) ) ;
+               q.push( test_item( * i ++ ), 0 ) ;
        }
        i = begin ;
        for ( j = 0 ; j < n ; ++ j ) {
@@ -231,14 +232,14 @@
 void
 add_then_wakeup( const iterator begin, const iterator middle, const iterator 
end )
 {
-       Scheduling_Queue< test_item > q ;
+       queue_type q ;
        const size_t number_of_elements = middle - begin ;
        size_t j ;
        iterator i( begin ) ;
        std::vector< pointer > pp ;
 
        while ( i != middle ) {
-               pp.push_back( q.push( test_item( * i ++ ) ) ) ;
+               pp.push_back( q.push( test_item( * i ++ ), 0 ) ) ;
        }
        BOOST_REQUIRE( i - begin == number_of_elements ) ;
 

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      19 Jun 2007 18:52:25 -0000      1.1
@@ -0,0 +1,32 @@
+2007-06-19 Eric Hughes <address@hidden>
+       Added a completion check for the test listening action.
+       All unit tests now fully pass.
+
+2007-06-19 Eric Hughes <address@hidden>
+       Added wakeup_listener_allocated to be the auxiliary object in the 
scheduling queue.
+       Changed constructor for old auxiliary items into a call to reconstruct 
on the old object.
+       Eliminated identifier Basic_Wakeup_Listener.
+
+2007-06-18 Eric Hughes <address@hidden>
+       Removed singleton construction for Scheduler.
+       
+2007-06-17 Eric Hughes <address@hidden>
+       Changed activate_one_item to use a queue pointer rather than a 
reference.  A reference points to a single location in the priority queue 
(which reorders itself), whereas a pointer points to the same entry as it moves 
around.
+       Changed index version of reorder to use a permutation_index.
+
+2007-06-17 Eric Hughes <address@hidden>
+       Changed wakeup_listener to store a permutation_index rather than a 
pointer.  This eliminates an essential duplication, having stored both the 
scheduler and its queue addresses both.
+       Expanded permutation vector to incorporate an auxiliary object, used to 
hold wakeup_listener.   
+       Changed interface to push to take this auxiliary object.
+       Added a reorder( size_t ) call that directly takes the 
permutation_index in wakeup_listener.
+
+2007-06-17 Eric Hughes <address@hidden>
+       Found defect with wakeup_listener allocated with queue_item, so 
pointers to such aren't stable.
+       Added another class parameter to Scheduling_Queue etc. in preparation 
for storing wakeup_listener stably.
+
+2007-06-16 Eric Hughes <address@hidden>
+       Added guard for wakeup to require a listener present.
+       Moved wakeup_listener from ACT.hpp to Scheduler.hpp
+       Added scheduler accessor to wakeup_listener.  Will allow removal of 
singleton.
+       Added action type to scheduled item.  Fixed comparison function.
+       Implemented add_service.
\ No newline at end of file




reply via email to

[Prev in Thread] Current Thread [Next in Thread]