/** \file
 *
 *  Contains the ControlThread class declaration.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef CONTROLTHREAD_H_
#define CONTROLTHREAD_H_

#include "component/AsyncComponent.h"
#include "component/SyncComponent.h"
#include "process/SyncHandler.h"

static const double DEFAULT_CONTROL_THREAD_PERIOD = 0.4;

class ControlThread;

/**
 *  The periodic "control thread"
 *
 *  The basic idea is that the ControlThread has a specialized
 *  form of Handler which holds a list of Components that will
 *  be running each control cycle
 *
 *  The ControlThread is run in a PeriodicThreadHandler by Supervisor.
 *  It calculates an order of operations in advance, but is able to
 *  determine when "things have changed" and recalculate that order as
 *  needed.
 *
 *  On each execution (every 5Hz or whatever) it will work its way through
 *  the order of operations, calling components, starting with CycleStarter and
 *  ending with LogEngine.
 *
 *  \ingroup supervisor
 */
class ControlThread : public AsyncComponent
{
public:
    /// Constructor
    ControlThread();

    /// Destructor
    virtual ~ControlThread();

    /// Initialize the component
    virtual void initialize( void );

    /// Run the thread
    virtual void run( void );

    /// Uninitialize the component
    virtual void uninitialize( void );

    //== Functions for dealing with the list of components ==
    /// Put a component in the control thread's control.
    /// Does not insert duplicates.
    ///
    /// \param component The SyncComponent to be added
    void addComponent( SyncComponent *component );

    /// Remove a component from the control thread's control.
    /// (technically only removes the first instance but
    /// list should not allow duplicates.
    ///
    /// \param component The SyncComponent to remove (uses == to compares pointers)
    void removeComponent( SyncComponent *component );

    /// Returns the Handler associated with this component
    virtual Handler *getSyncHandler()
    {
        return & syncHandler_;
    }

private:

    SyncHandler syncHandler_;

    // Hm, ok, what if there were three lists, an "add me" list,
    // a "delete me" list and an actual "working" list.  Then
    // the thread could decide when to take action...
    //
    // It's possible that some of these lists will actually be of
    // intermediate "holder" objects to hold counts, metainfo, etc...
    ListOfSyncComponents componentsToAdd_;
    ListOfSyncComponents componentsToRemove_;
    Mutex addComponentsMutex_, removeComponentsMutex_;

    /// Takes any new components in the componentsToAdd_ queue,initializes them,
    /// and adds them to the control thread.
    ///
    /// \return Number of new components added
    int addComponentsFromQueue( void );

    /// Takes any components in the componentsToRemove_ queue, uninitializes them
    /// and removes them from the control thread
    ///
    /// \return Number of new components removed
    int removeComponentsFromQueue( void );
};


#endif /*CONTROLTHREAD_H_*/
