/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_THREADED_NODE_HPP
#define NMM_THREADED_NODE_HPP NMM_THREADED_NODE_HPP

#include "nmm/nmm_prefix.hpp"

#include "Node.hpp"
#include "IThreadedNodeImpl.hpp"
#include "nmm/utils/thread/Thread.hpp"

#include "visibility.hpp"

namespace NMM {

  /** A node in an NMM flow graph.
   * This class extends the Node class by threading functionality.
   * Every node has its own internal thread for processing instream messages and signals.
   * This class provides functionality for managing and controlling this thread.
   *
   * The node thread is running in the state OUTPUT_INITIALIZED, ACTIVATED and STARTED.
   */
  class DLLEXPORT ThreadedNode
    : public Node,
      public IThreadedNodeImpl
  {
  private:
    bool activated_before;      ///< Flag which indicates that the node thread is running
    bool thread_owner;          ///< Flag which indicates that this node owns its thread (always true)

    Thread thread;              ///< The node thread

    /** Static thread main method.
     * This method is invoked directly by the node thread.
     * It invokes the main processing method of the node and handles any exception before returning.
     *
     * @param me The thread argument, a pointer to the ThreadedNode which owns the thread
     * @return The thread exit status (always 0)
     */
    static void* run_static(void *me);

    pid_t thread_pid;           ///< Thread ID of the node thread
    int thread_priority;        ///< Priority of the node thread

    /** Set the thread ID of the node thread.
     *
     * @param new_pid The thread ID
     */
    void setPID(pid_t new_pid);

  protected:
    /** Main processing method.
     * This method is running in the node thread and performs all instream processing and signal handling
     * of the node. It is an abstract method and implemented in generic subclasses.
     * Plug-ins should not reimplement this method directly.
     *
     * @param num_times Deprecated, must be zero
     */
    virtual void run(int num_times = 0) = 0;

    /** Lower thread priority.
     * This method lowers the priority of the node thread.
     *
     * This method is only implemented on linux and does nothing on other platforms.
     *
     * @param value Priority value, must be between 1-20
     */
    void lowerPriority(const nmm_uint32& value);


  public:
    /** Create a new node.
     *
     * @param name Node name
     */
    ThreadedNode(const char* name);

    /** Virtual destructor.
     */
    virtual ~ThreadedNode();

    /** Perform state transition from INITIALIZED to OUTPUT_INITIALIZED.
     * This method changes the state and invokes the doInitOutput method of the node.
     * The state transition fails if doInitOutput fails or a required interface method for this
     * state transition has not been called successfully.
     *
     * This implementation invokes the base class implementation and additionally starts
     * the node thread.
     *
     * @exception StateTransitionFailedException if doInitOutput has failed
     * @exception UnsuccessfulRequiredCallException if a required interface method was not called successfully
     */
    virtual void initOutput()
      throw (const StateTransitionFailedException&, const UnsuccessfulRequiredCallException&);

    /** Perform state transition from OUTPUT_INITIALIZED to INITIALIZED.
     * This method changes the state and invokes the doDeinitOutput method of the node.
     * The state transition fails if doDeinitOutput fails or a required interface method for this
     * state transition has not been called successfully.
     *
     * This implementation invokes the base class implementation and additionally stops
     * the node thread.
     *
     * @exception StateTransitionFailedException if doDeinitOutput has failed
     * @exception UnsuccessfulRequiredCallException if a required interface method was not called successfully
     */
    virtual void deinitOutput()
      throw (const StateTransitionFailedException&, const UnsuccessfulRequiredCallException&);

    /** Set whether this node is the owner of its thread.
     *
     * @param owner Flag which indicates that this node owns its thread
     *
     * @deprecated This method is deprecated and might have undefined behaviour and results
     */
    virtual void setThreadOwner(bool owner)  {  thread_owner = owner;  }

    /** Get the thread ID of the node thread of this node.
     *
     * @return The thread ID of the node thread
     *
     * @deprecated This method is deprecated and might have undefined behaviour and results
     */
    pid_t getPID();

    /** Set thread priority.
     *
     * @param level The thread priority
     *
     * @deprecated This method is deprecated and might have undefined behaviour and results
     */
    Result setPriority(unsigned int level);

    /** Set the scheduling priority of the node thread.
     *
     * @param scheduling_policy A scheduling policy
     *
     * @deprecated This method is deprecated and might have undefined behaviour and results
     */
    void enableCustomScheduling(Thread::Scheduling_Policy scheduling_policy);

    /** Set the priority of the node thread to the minimum.
     *
     * @deprecated This method is deprecated and might have undefined behaviour and results
     */
    void setMinPriority();

    /** Set the priority of the node thread to the average.
     *
     * @deprecated This method is deprecated and might have undefined behaviour and results
     */
    void setMidPriority();

    /** Set the priority of the node thread to the maximum.
     *
     * @deprecated This method is deprecated and might have undefined behaviour and results
     */
    void setMaxPriority();

  };

}

#include "nmm/nmm_suffix.hpp"

#endif
