/* -*- mode: c++; c-basic-offset: 4; -*-
 *
 * MICO --- a CORBA implementation
 * Copyright (C) 1997-98 Kay Roemer & Arno Puder
 * 
 * message handling
 * Copyright (C) 1999 Andreas Schultz                                 
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Send comments and/or bug reports to:
 *                mico@informatik.uni-frankfurt.de
 * 
 */


#ifndef __mico_message_h__
#define __mico_message_h__

class Operation;
class ThreadPool;
class WorkerThread;

class msg_type {
public:
    typedef enum { Terminate, Process } MsgType;
    
protected:
    MsgType type;
    void *ptr;
    
public:
    msg_type( void *_ptr, MsgType _t = Process ): type( _t ), ptr(_ptr)
    {
#ifdef MTDEBUG
	create_time = OSMisc::timestamp();
#endif
    };
    ~msg_type()
    { 
#ifdef MTDEBUG
	MT_PROFILE( {
		       MICODebug::instance()->printer() << "  time from create to delete:  " 
		            << OSMisc::timestamp() - create_time << " ms" << endl;
		       MICODebug::instance()->printer() << "  time from pop to delete:     " 
			    << OSMisc::timestamp() - pop_time << " ms" << endl;
	} );
#endif
    };
    MsgType get_type() { return type; };
    void set_type( MsgType _t) { type = _t; };

    void *data() { return ptr; };

#ifdef MTDEBUG
    MICO_Long create_time;
    MICO_Long push_time;
    MICO_Long pop_time;
#endif
    int value;
};

typedef int OP_id_type;

class MsgChannel {
public:
    typedef enum { active, passive, direct } Types;
 
protected:
    ThreadPool             *tp;
public:
    void setThreadPool( ThreadPool *_tp ) { tp = _tp; };
    ThreadPool *getThreadPool() { return tp; };

    virtual MICO_Boolean check_msg( MICO::WorkerThread * );
    virtual msg_type *get_msg( OP_id_type );
    virtual void put_msg( OP_id_type, msg_type *) = 0;
};

class activeMsgQueue: public MsgChannel
#ifdef DEBUG_NAMES
                ,public _namedObject 
#endif
{
protected:
    queue<msg_type*>       Q;
    MICOMT::Mutex  Qaccess;

public:
#ifdef DEBUG_NAMES
    activeMsgQueue();
    const char *name (const char *new_name = NULL);
#endif
    MICO_Boolean check_msg( MICO::WorkerThread * );
    void put_msg( OP_id_type nextOP_id, msg_type *);

    virtual ~activeMsgQueue();
};


class passiveMsgQueue: public MsgChannel
#ifdef DEBUG_NAMES
                ,public _namedObject 
#endif
{
protected:
    queue<msg_type*>          Q;
    MICOMT::Mutex     Qaccess;
    MICOMT::Semaphore msg_cnt;

public:
#ifdef DEBUG_NAMES
    passiveMsgQueue();
    const char *name (const char *new_name = NULL);
#endif

    msg_type *get_msg( OP_id_type nextOP_id );
    void put_msg( OP_id_type nextOP_id, msg_type *msg);

    virtual ~passiveMsgQueue();
};

class directMsgConnector: public MsgChannel
#ifdef DEBUG_NAMES
                         ,public _namedObject 
#endif
{
protected:
    Operation *op;
    
public:
#ifdef DEBUG_NAMES
    directMsgConnector();
    const char *name (const char *new_name = NULL);
#endif
    
    void setOperation( Operation *_op ) {
	op = _op;
    };
    void put_msg( OP_id_type nextOP_id, msg_type *msg);
    
    virtual ~directMsgConnector();
};

#endif // __mico_message_h__
