// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_GIOP_SERVER_STARTER_H
#define OB_GIOP_SERVER_STARTER_H

//
// Declare OBGIOPServerWorker as a class
//
class OBGIOPServerWorker;
typedef OBGIOPServerWorker* OBGIOPServerWorker_ptr;
void OBDuplicate(OBGIOPServerWorker_ptr);
void OBRelease(OBGIOPServerWorker_ptr);
typedef OBObjVar< OBGIOPServerWorker > OBGIOPServerWorker_var;
typedef OBObjSeq< OBGIOPServerWorker > OBGIOPServerWorkerSeq;

//
// The OBGIOPServerStarter class
//
class OBGIOPServerStarter;
typedef OBGIOPServerStarter* OBGIOPServerStarter_ptr;
void OBDuplicate(OBGIOPServerStarter_ptr);
void OBRelease(OBGIOPServerStarter_ptr);
typedef OBObjVar< OBGIOPServerStarter > OBGIOPServerStarter_var;

class OBGIOPServerStarter : public OBRefCount
{
    //
    // Hide copy-constructor and asignment operator
    //
    OBGIOPServerStarter(const OBGIOPServerStarter&);
    void operator=(const OBGIOPServerStarter&);

protected:

    //
    // The acceptor
    //
    OCI_Acceptor_var acceptor_;

    //
    // The workers
    //
    OBGIOPServerWorkerSeq workers_;
#ifdef HAVE_JTC
    JTCMutex workersMutex_;
#endif

    //
    // Destroy all workers
    //
    void destroyAllWorkers();

public:
    
    OBGIOPServerStarter(OCI_Acceptor_ptr, bool);
    virtual ~OBGIOPServerStarter();

    static inline OBGIOPServerStarter_ptr _duplicate(OBGIOPServerStarter_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline OBGIOPServerStarter_ptr _nil()
    { return 0; }

    //
    // Destroy the server starter
    //
    virtual void destroy() = 0;

    //
    // Destroy a worker
    //
    virtual void destroyWorker(OBGIOPServerWorker_ptr);

    //
    // Start the worker
    //
    virtual bool startWorker();
};

inline void
CORBA_release(OBGIOPServerStarter_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(OBGIOPServerStarter_ptr p)
{
    return p == 0;
}

//
// The OBGIOPServerStarterBlocking class
//
class OBGIOPServerStarterBlocking;
typedef OBGIOPServerStarterBlocking* OBGIOPServerStarterBlocking_ptr;
void OBDuplicate(OBGIOPServerStarterBlocking_ptr);
void OBRelease(OBGIOPServerStarterBlocking_ptr);
typedef OBObjVar< OBGIOPServerStarterBlocking >
OBGIOPServerStarterBlocking_var;

class OBGIOPServerStarterBlocking : public OBGIOPServerStarter
{
    //
    // Hide copy-constructor and asignment operator
    //
    OBGIOPServerStarterBlocking(const OBGIOPServerStarterBlocking&);
    void operator=(const OBGIOPServerStarterBlocking&);

public:
    
    OBGIOPServerStarterBlocking(OCI_Acceptor_ptr, bool);
    virtual ~OBGIOPServerStarterBlocking();

    static inline OBGIOPServerStarterBlocking_ptr
    _duplicate(OBGIOPServerStarterBlocking_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline OBGIOPServerStarterBlocking_ptr _nil()
    { return 0; }

    //
    // Destroy the server starter
    //
    virtual void destroy();

    //
    // Start the worker
    //
    virtual bool startWorker();
};

inline void
CORBA_release(OBGIOPServerStarterBlocking_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(OBGIOPServerStarterBlocking_ptr p)
{
    return p == 0;
}

//
// The OBGIOPServerStarterReactive class
//
class OBGIOPServerStarterReactive;
typedef OBGIOPServerStarterReactive* OBGIOPServerStarterReactive_ptr;
void OBDuplicate(OBGIOPServerStarterReactive_ptr);
void OBRelease(OBGIOPServerStarterReactive_ptr);
typedef OBObjVar< OBGIOPServerStarterReactive >
OBGIOPServerStarterReactive_var;

class OBGIOPServerStarterReactive : public OBGIOPServerStarter,
				    public OBEventHandler
{
    //
    // Hide copy-constructor and asignment operator
    //
    OBGIOPServerStarterReactive(const OBGIOPServerStarterReactive&);
    void operator=(const OBGIOPServerStarterReactive&);

protected:

    bool destroy_; // True if destroy() was called

public:
    
    OBGIOPServerStarterReactive(OCI_Acceptor_ptr, bool);
    virtual ~OBGIOPServerStarterReactive();

    static inline OBGIOPServerStarterReactive_ptr
    _duplicate(OBGIOPServerStarterReactive_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline OBGIOPServerStarterReactive_ptr _nil()
    { return 0; }

    //
    // Destroy the server starter
    //
    virtual void destroy();

    //
    // Handle event
    //
    virtual void handleEvent(OBMask);
};

inline void
CORBA_release(OBGIOPServerStarterReactive_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(OBGIOPServerStarterReactive_ptr p)
{
    return p == 0;
}

#ifdef HAVE_JTC

//
// The OBGIOPServerStarterThreaded class
//
class OBGIOPServerStarterThreaded;
typedef OBGIOPServerStarterThreaded* OBGIOPServerStarterThreaded_ptr;
void OBDuplicate(OBGIOPServerStarterThreaded_ptr);
void OBRelease(OBGIOPServerStarterThreaded_ptr);
typedef OBObjVar< OBGIOPServerStarterThreaded >
OBGIOPServerStarterThreaded_var;

class OBGIOPServerStarterThreaded : public OBGIOPServerStarter
{
    //
    // Hide copy-constructor and asignment operator
    //
    OBGIOPServerStarterThreaded(const OBGIOPServerStarterThreaded&);
    void operator=(const OBGIOPServerStarterThreaded&);

protected:

    bool destroy_; // True if destroy() was called

    //
    // The starter thread
    //
    class StarterThread : public JTCThread
    {
	OBGIOPServerStarterThreaded_var starter_;

    public:
	
	StarterThread(OBGIOPServerStarterThreaded_ptr starter)
	    : starter_(OBGIOPServerStarterThreaded::_duplicate(starter)) { }
	virtual ~StarterThread() { }
	virtual void run();
    };
    friend class StarterThread;
    JTCThreadHandle starterThread_;

public:
    
    OBGIOPServerStarterThreaded(OCI_Acceptor_ptr, bool);
    virtual ~OBGIOPServerStarterThreaded();

    static inline OBGIOPServerStarterThreaded_ptr
    _duplicate(OBGIOPServerStarterThreaded_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline OBGIOPServerStarterThreaded_ptr _nil()
    { return 0; }

    //
    // Destroy the server starter
    //
    virtual void destroy();

    //
    // Run method for starter thread
    //
    void starterRun();
};

inline void
CORBA_release(OBGIOPServerStarterThreaded_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(OBGIOPServerStarterThreaded_ptr p)
{
    return p == 0;
}

#endif

#endif
