// $Id: JGTask.cpp,v 1.8 2003/03/16 14:51:00 fukasawa Exp $

//=============================================================================
/**
 *  @file    JGTask.cpp
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2001-2003 BEE Co.,Ltd. All rights reserved.
 *
 * 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.
 */
//=============================================================================

#define BEE_BUILD_DLL

#include "JGTask.h"
#include "JGDevType.h"
#include "JGDevObject.h"

//-----------------------------------------------------------------------------
// Constructor/Destructor
//-----------------------------------------------------------------------------
JGTask::JGTask(const string& progName) : m_program(progName)
{
}

//-----------------------------------------------------------------------------
// Spawn off a new thread.
//-----------------------------------------------------------------------------
int JGTask::open(void *)
{
    if (this->activate(THR_NEW_LWP | THR_DETACHED) == -1)
    {
        ACE_ERROR((LM_ERROR, ACE_TEXT("%p :%s \n"), ACE_TEXT("spawn"),
                                                    this->charName()));
        return -1;
    }
    return 0;
}

//-----------------------------------------------------------------------------
int JGTask::close(u_long exit_status)
{
    // ACE_DEBUG((LM_DEBUG,
    //          ACE_TEXT("(%t) thread is exiting with status %d in module :%s\n"),
    //          exit_status, this->charName()));
    ACE_UNUSED_ARG(exit_status);
    return 0;
}

//-----------------------------------------------------------------------------
// Request to stop thread.
//-----------------------------------------------------------------------------
int JGTask::end()
{
    return this->m_activation_queue.enqueue(new TaskEndRequest(this));
}

//-----------------------------------------------------------------------------
// Schedule a new timer.
//-----------------------------------------------------------------------------
int JGTask::addTimer(const ACE_Time_Value& term, TaskTimerHandler * tmh)
{
    TRACE_FUNCTION(TRL_LOW, "JGTask::addTimer");

    int tmid = ACE_Proactor::instance()->schedule_timer(*tmh, NULL, term);
    if (tmid == -1)
    {
        TRACE_ERROR((_TX("[%s] Timer schedule failed"), this->charName()));
        return -1;
    }
    // We store the id into the handler, this is only used to produce
    // nicer messages.
    tmh->set_id(tmid);
    tmh->set_task(this);

    // TRACE_DEBUG((_TX("[%s] Start timer(%d) : scheduling timer id = %d\n"),
    //             this->charName(), term.sec(), tmid));

    return tmid;
}


//-----------------------------------------------------------------------------
// Cancel a timer.
//-----------------------------------------------------------------------------
int JGTask::cancelTimer(int timer_id)
{
    TRACE_FUNCTION(TRL_LOW, "JGTask::cancelTimer");

    if (timer_id < 0)
    {
        return -1;
    }

    ACE_Proactor::instance()->cancel_timer(timer_id);

    // TRACE_DEBUG((_TX("[%s] scheduled timer id = %d\n"), this->charName(),
    //             timer_id));

    return 0;
}


//-----------------------------------------------------------------------------
// Notify trigger to self
//-----------------------------------------------------------------------------
int JGTask::notify(JGTrigger * trigger)
{
    return m_activation_queue.enqueue(new JGTriggerRequest(trigger, this));
}

//-----------------------------------------------------------------------------
int JGTask::put(JGTriggerRequest * req)
{
    return m_activation_queue.enqueue(req);
}

//-----------------------------------------------------------------------------
// Attach / Detach
//-----------------------------------------------------------------------------
int JGTask::attach(JGObserver * observer)
{
    m_observer = observer;
    return 0;
}

//-----------------------------------------------------------------------------
int JGTask::detach(JGObserver * task)
{
    ACE_UNUSED_ARG(task);
    m_observer = NULL;
    return 0;
}

//-----------------------------------------------------------------------------
// Thread service
//-----------------------------------------------------------------------------
int JGTask::svc()
{
    // ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%s) JGTask::svc start.\n"), this->charName()));

    int  result = 0;

    // Receive trigger request.
    for (;;)
    {
        auto_ptr<ACE_Method_Request> mo(this->m_activation_queue.dequeue());

        // Call it.
        if ((result = mo->call()) == -1)
        {
            break;
        }

        // Destructor automatically deletes it.
    }

    if (result == -1 && errno == EWOULDBLOCK)
    {
        ACE_ERROR((LM_ERROR, ACE_TEXT("(%s) %p\n"), this->charName(),
                             ACE_TEXT("timed out waiting for message")));
    }

    ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%s) JGTask::svc end.\n"), this->charName()));
    return 0;
}
