/*!
  @file           Converter_WaitQueue.hpp
  @author         TorstenS
  @author         AlexanderK
  @author         UweH
  @ingroup        Converter
  @brief          wait queue class used in the converter
*/

/*
    ========== licence begin  GPL
    Copyright (c) 2001-2005 SAP AG

    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 2
    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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

*/


#ifndef CONVERTER_WAITQUEUE_HPP
#define CONVERTER_WAITQUEUE_HPP

#include "gsp00.h"
#include "KernelCommon/Kernel_TaskWaitList.hpp"


/* -----------------------------------------------------------------------*/
/*!
   @class   Converter_WaitQueue
   @brief   wait queue class used in the converter
 */
/* -----------------------------------------------------------------------*/

class Converter_WaitQueue
{
public:

    /// only for convenience
    typedef Kernel_TaskWaitList::WaitContext WaitContext;

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   constructor for a converter wait queue, which is used if a
                task should be suspended if onw of the converter resources
                is not available.
       @param   suspendReason  [in] reason used if a task should be suspended
       @param   queueUsageName [in] name of the wait queue used for
                                    RTE spinlock monitoring
       @return  none
     */
    /* -----------------------------------------------------------------------*/

    Converter_WaitQueue( const SAPDB_Int2    suspendReason );

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method is used to resume all task stored within the
                wait queue. Note that a spinlock is used to protect the
                internal structure of the wait queue.
       @return  none
     */
    /* -----------------------------------------------------------------------*/

    void ResumeAllWaitingTasks( const tsp00_TaskId taskId );

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method is used to insert a task into the wait queue and
                to suspend the task. The task will leave the method after it
                is resume by another task. Note that a spinlock is used to
                protect the internal structure of the wait queue.
       @param   taskId [in] calling task identification
       @return  none
     */
    /* -----------------------------------------------------------------------*/

    void InsertTaskAndWait( const tsp00_TaskId taskId )
    {
        WaitContext waitContext;

        InsertTask( taskId, waitContext );

        Wait( taskId );
    }

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method is used to insert a task into the wait queue.
                Note that the task is not suspended by this method!
                It will return immediately. Note that a spinlock is used to
                protect the internal structure of the wait queue.
       @param   taskId      [in] calling task identification
       @param   waitContext [in] task specific wait context used to manage
                                 the wait situation
       @return  none
     */
    /* -----------------------------------------------------------------------*/

    void InsertTask( const tsp00_TaskId     taskId,
                     WaitContext            &waitContext );

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method is used to suspend the calling task. Note
                that the task won't be inserted into a wait queue. This
                has to be done before with InsertTask.
       @param   taskId [in] calling task identification
       @return  none
     */
    /* -----------------------------------------------------------------------*/

    void Wait( const tsp00_TaskId taskId ) const;

    /* -----------------------------------------------------------------------*/
    /*!
       @brief   This method is used to provide the filling state of the
                wait queue. Note that NO spinlock is used to protect the
                internal structure of the wait queue.
       @return  (SAPDB_Bool) true if the wait queue is empty else false.
     */
    /* -----------------------------------------------------------------------*/

    bool IsEmpty() const
    {
       return( m_WaitList.IsEmpty() );
    }

private:

    /// suspend reason
    const SAPDB_Int2 m_SuspendReason;

    /// identifier for the latch
    const  tsp00_RegionId  m_RegionId;

    /// the list of waiting tasks
    Kernel_TaskWaitList m_WaitList;
};

#endif  /* CONVERTER_WAITQUEUE_HPP */
