// $Id: MELDeviceServer.h,v 1.1.1.1 2002/08/31 04:47:25 fukasawa Exp $

//=============================================================================
/**
 *  @file    MELDeviceServer.h
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2001-2002 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.
 */
//=============================================================================

#ifndef MELDEVICESERVER_H
#define MELDEVICESERVER_H

#ifdef _MSC_VER
#pragma warning(disable: 4786)  // too long identifier
#endif

#include <vector>
using namespace std;
#include "ace/Reactor.h"
#include "ace/Task.h"
#include "ace/Timer_Heap_T.h"
#include "ace/Timer_Queue_Adapters.h"
#include "MELDeviceManager.h"
#include "MELXmlParser.h"

typedef ACE_Module<ACE_MT_SYNCH>        MT_Module;
typedef ACE_Task<ACE_MT_SYNCH>          MT_Task;

// These typedefs ensure that we use the minimal amount of locking
// necessary.
typedef ACE_Event_Handler_Handle_Timeout_Upcall<ACE_Null_Mutex> Upcall;
typedef ACE_Timer_Heap_T<ACE_Event_Handler *, Upcall,
                                              ACE_Null_Mutex> Timer_Heap;
typedef ACE_Timer_Heap_Iterator_T<ACE_Event_Handler *,
                                  Upcall, ACE_Null_Mutex> Timer_Heap_Iterator;
typedef ACE_Thread_Timer_Queue_Adapter<Timer_Heap> PLCTimerQueue;


class PLCTimerHandler;

//------------------------------------------------------------------------------
// Parameter of melsec use for random read.
//------------------------------------------------------------------------------
#if _MSC_VER >= 1100
#pragma pack(push)
#endif

struct ReadParam                  // mdRandR/W parameter
{
    unsigned short m_devid;
    unsigned short m_top;
    unsigned short m_dataq;
#ifdef __GNUC__
} __attribute__((packed));
#else
};
#endif

struct RandomReadParam
{
    MelReadBlocks *  m_blocks;
    unsigned short * m_bufp;
    size_t         m_bufsize;
    unsigned short m_devq;          // As use parameter for mdRandR function,
    ReadParam      m_params[1];     // don't change item sequence.
#ifdef __GNUC__
} __attribute__((packed));
#else
};
#endif

#if _MSC_VER >= 1100
#pragma pack(pop)
#endif

//------------------------------------------------------------------------------
//
// MELSEC Device Server
//
//------------------------------------------------------------------------------
class BEE_Export MELDeviceServer : public MELDeviceManager, MT_Task
{
public:
    MELDeviceServer(char * filename = NULL) : MELDeviceManager(filename) {
            m_randq = 0; m_randptr = NULL; m_period.set(0, 1000);
            m_timer = NULL;
        }
    virtual ~MELDeviceServer();

    virtual int init(const char * pname = NULL, const char * xmlname = NULL,
                     int chan = 12, int stnum = 1, int unit = 0xFF);
    virtual int open(void * args = 0);
    virtual int close(u_long flags = 0);
    virtual int svc(void);
    virtual int put(ACE_Message_Block * mb, ACE_Time_Value * tv = NULL);

    int  end();                      // request to stop thread
    int  project();                  // Device to shared memosry.
    void stopSemaphore()  { sema_onoff(false); }
    void startSemaphore() { sema_onoff(true); }

    static MELDeviceServer * instance();
//
private:
    int addTimer(const ACE_Time_Value& interval, PLCTimerHandler * tmh);
    int cancelTimer(int timer_id);  // Cancel timer <id>.
    int makeVirtualMemory();
    int initRandomReadInfo(MELXmlParser * xmlParser);
    void sema_onoff(bool tf);

// member's variables
private:
    int                m_randq;
    RandomReadParam ** m_randptr;

    ACE_Time_Value   m_period;
    ACE_Thread_Mutex m_lock;          // lock for message list
    PLCTimerHandler  * m_timer;

};


#endif
