(file) Return to IPC.h CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

File: [Pegasus] / pegasus / src / Pegasus / Common / Attic / IPC.h (download)
Revision: 1.53, Wed Aug 9 20:12:42 2006 UTC (17 years, 10 months ago) by mike
Branch: MAIN
CVS Tags: TASK-PEP362_RestfulService-merged_out_from_trunk, TASK-PEP348_SCMO-merged_out_from_trunk, TASK-PEP317_pullop-merged_out_from_trunk, TASK-PEP317_pullop-merged_in_to_trunk, TASK-PEP311_WSMan-root, TASK-PEP311_WSMan-branch, HPUX_TEST, HEAD
Changes since 1.52: +0 -0 lines
FILE REMOVED
BUG#: 5314
TITLE: IPC Refactoring

DESCRIPTION: This patch cleans up the IPC related classes. It (1) reorganizes
related classes into their own headers, (2) makes the mutex class recursive to
eliminate recursive lock exclusion logic, (3) reimplements condition variables,
renames dozens of global functions.

//%2006////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation, The Open Group.
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; Symantec Corporation; The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Mike Day (mdday@us.ibm.com)
//
// Modified By: Markus Mueller
//              Ramnath Ravindran (Ramnath.Ravindran@compaq.com)
//              David Eger (dteger@us.ibm.com)
//              Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
//              Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
//              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
//              David Dillard, VERITAS Software Corp.
//                  (david.dillard@veritas.com)
//              Aruran, IBM (ashanmug@in.ibm.com) for BUG# 3518, 4067
//
//%/////////////////////////////////////////////////////////////////////////////

#ifndef Pegasus_IPC_h
#define Pegasus_IPC_h

#include <Pegasus/Common/Config.h>
#include <Pegasus/Common/Network.h>
#include <Pegasus/Common/Linkage.h>
#include <Pegasus/Common/AutoPtr.h>
#include <Pegasus/Common/IPCTypes.h>
#include <Pegasus/Common/Mutex.h>
#include <Pegasus/Common/AtomicInt.h>

#define PEG_SEM_READ 1
#define PEG_SEM_WRITE 2

#include <Pegasus/Common/List.h>

PEGASUS_NAMESPACE_BEGIN

int timeval_subtract (struct timeval *result,
                      struct timeval *x,
                      struct timeval *y);

//%///////////////// ----- IPC related functions ------- //////////////////////
// ----- NOTE - these functions are PRIMITIVES that MUST be implemented
//               by the platform. e.g., see IPCUnix.cpp

void PEGASUS_COMMON_LINKAGE disable_cancel();
void PEGASUS_COMMON_LINKAGE enable_cancel();
//void PEGASUS_COMMON_LINKAGE native_cleanup_push( void (*)(void *), void * );
void PEGASUS_COMMON_LINKAGE native_cleanup_pop(Boolean execute);

#ifdef PEGASUS_NEED_CRITICAL_TYPE
void PEGASUS_COMMON_LINKAGE init_crit(PEGASUS_CRIT_TYPE *crit);
void PEGASUS_COMMON_LINKAGE enter_crit(PEGASUS_CRIT_TYPE *crit);
void PEGASUS_COMMON_LINKAGE try_crit(PEGASUS_CRIT_TYPE *crit);
void PEGASUS_COMMON_LINKAGE destroy_crit(PEGASUS_CRIT_TYPE *crit);
void PEGASUS_COMMON_LINKAGE exit_crit(PEGASUS_CRIT_TYPE *crit);
#endif

PEGASUS_THREAD_TYPE PEGASUS_COMMON_LINKAGE pegasus_thread_self();
void PEGASUS_COMMON_LINKAGE exit_thread(PEGASUS_THREAD_RETURN rc);
void PEGASUS_COMMON_LINKAGE pegasus_sleep(int ms);
void PEGASUS_COMMON_LINKAGE destroy_thread(PEGASUS_THREAD_TYPE th, PEGASUS_THREAD_RETURN rc);



//%//////// -------- IPC Exception Classes -------- ///////////////////////////////

class PEGASUS_COMMON_LINKAGE IPCException
{
public:
    IPCException(PEGASUS_THREAD_TYPE owner): _owner(owner) { }
    inline PEGASUS_THREAD_TYPE get_owner() { return(_owner); }
private:
    PEGASUS_THREAD_TYPE _owner;
};

class PEGASUS_COMMON_LINKAGE Deadlock: public IPCException
{
public:
    Deadlock(PEGASUS_THREAD_TYPE owner) : IPCException(owner) {}
private:
    Deadlock();
};

class PEGASUS_COMMON_LINKAGE AlreadyLocked: public IPCException
{
public:
    AlreadyLocked(PEGASUS_THREAD_TYPE owner) : IPCException(owner) {}
private:
    AlreadyLocked();
};

class PEGASUS_COMMON_LINKAGE TimeOut: public IPCException
{
public:
    TimeOut(PEGASUS_THREAD_TYPE owner) : IPCException(owner) {}
private:
    TimeOut();
};

class PEGASUS_COMMON_LINKAGE Permission: public IPCException
{
public:
    Permission(PEGASUS_THREAD_TYPE owner) : IPCException(owner) {}
private:
    Permission();
};

class PEGASUS_COMMON_LINKAGE WaitFailed: public IPCException
{
public:
    WaitFailed(PEGASUS_THREAD_TYPE owner) : IPCException(owner) {}
private:
    WaitFailed();
};

class PEGASUS_COMMON_LINKAGE WaitInterrupted: public IPCException
{
public:
    WaitInterrupted(PEGASUS_THREAD_TYPE owner) : IPCException(owner) {}
private:
    WaitInterrupted();
};

class PEGASUS_COMMON_LINKAGE TooManyReaders: public IPCException
{
public:
    TooManyReaders(PEGASUS_THREAD_TYPE owner) : IPCException(owner) { }
private:
    TooManyReaders();
};


class PEGASUS_COMMON_LINKAGE ListFull: public IPCException
{
public:
    ListFull(Uint32 count) : IPCException(pegasus_thread_self())
    {
        _capacity = count;
    }

    Uint32 get_capacity() const throw()
    {
        return _capacity;
    }

private:
    ListFull();
    Uint32 _capacity;
};

class PEGASUS_COMMON_LINKAGE ListClosed: public IPCException
{
public:
    ListClosed() : IPCException(pegasus_thread_self())
    {
    }
};

class PEGASUS_COMMON_LINKAGE ModuleClosed: public IPCException
{
public:
    ModuleClosed() : IPCException(pegasus_thread_self())
    {
    }
};

//%//////////////////////////////////////////////////////////////
//  AutoMutex - use when you could lose scope due to an exception
/////////////////////////////////////////////////////////////////

class PEGASUS_COMMON_LINKAGE AutoMutex
{
public:
    AutoMutex(Mutex& mutex, Boolean autoLock = true)
        : _mutex(mutex),
          _locked(autoLock)
    {
        if (autoLock)
        {
            _mutex.lock(pegasus_thread_self());
        }
    }

    ~AutoMutex()
    {
        try
        {
			if (_locked)
			{
                unlock();
			}
        }
        catch (...)
        {
            // Do not propagate exception from destructor
        }
    }

    void lock()
    {
        if (_locked)
        {
            throw AlreadyLocked(pegasus_thread_self());
        }

        _mutex.lock(pegasus_thread_self());
        _locked = true;
    }

    void unlock()
    {
        if (!_locked)
        {
            throw Permission(pegasus_thread_self());
        }

        _mutex.unlock();
        _locked = false;
    }

    Boolean isLocked() const
    {
        return _locked;
    }

private:
    AutoMutex();    // Unimplemented
    AutoMutex(const AutoMutex& x);    // Unimplemented
    AutoMutex& operator=(const AutoMutex& x);    // Unimplemented

    Mutex& _mutex;
    Boolean _locked;
};


//%////////////////////////////////////////////////////////////////////////////

class PEGASUS_COMMON_LINKAGE Semaphore
{
public:

    /**
        Creates a semaphore and sets its initial value as specified.
        @param initial The initial value for the Semaphore (defaults to 1).
    */
    Semaphore(Uint32 initial = 1);

    ~Semaphore();

    /**
        Blocks until this Semaphore is in a signalled state.
        @param ignoreInterrupt Indicates whether the wait operation should
        continue (true) or an exception should be thrown (false) when an
        interrupt is received.
        @exception WaitFailed If unable to block on the semaphore.
        @exception WaitInterrupted If the operation is interrupted.
    */
    void wait(Boolean ignoreInterrupt = true);

    /**
        Checks whether the Semaphore is signalled without waiting.  This method
        returns normally if the Semaphore has a non-zero count.
        @exception WaitFailed If the wait operation does not immediately
        succeed.
    */
    void try_wait();

    /**
        Waits for the Semaphore to be signalled for a specified time interval.
        This method returns normally if the Semaphore has a non-zero count or
        it is signalled during the specified time interval.
        @param milliseconds The time interval to wait (in milliseconds).
        @exception TimeOut If the wait operation does not succeed within
        the specified time interval.
    */
    void time_wait(Uint32 milliseconds);

    /**
        Increments the count of the semaphore.
    */
    void signal();

    /**
        Return the count of the semaphore.
    */
    int count() const;

private:

    Semaphore(const Semaphore& x);    // Unimplemented
    Semaphore& operator=(const Semaphore& x);    // Unimplemented

    mutable PEGASUS_SEM_HANDLE _semaphore;

    // may not need to use the _count member on
    // platforms that allow you to ask the semaphore for
    // its count
    mutable int _count;

//------------------------------------------------------------------------------
//
// AtomicInt inclusion:
//
//------------------------------------------------------------------------------
    friend class Condition;
};


PEGASUS_NAMESPACE_END

#include <Pegasus/Common/AtomicInt.h>

PEGASUS_NAMESPACE_BEGIN

//-----------------------------------------------------------------
/// Generic definition of read/write semaphore
//-----------------------------------------------------------------

#ifndef PEGASUS_READWRITE_NATIVE

typedef struct pegasus_rwlock {
    Semaphore _rlock;
    Mutex _wlock;
    Mutex _internal_lock;
    PEGASUS_THREAD_TYPE _owner;
    pegasus_rwlock() : _rlock(10), _wlock(), _internal_lock(), _owner(pegasus_thread_self())
    {
    }
} PEGASUS_RWLOCK_HANDLE;

#endif

class PEGASUS_COMMON_LINKAGE ReadWriteSem
{
public:
    ReadWriteSem();
    ~ReadWriteSem();

    // @exception Deadlock
    // @exception Permission
    // @exception WaitFailed
    inline void wait_read(PEGASUS_THREAD_TYPE caller)
    {
        wait(PEG_SEM_READ, caller );
    }

    // @exception Deadlock
    // @exception Permission
    // @exception WaitFailed
    inline void wait_write(PEGASUS_THREAD_TYPE caller)
    {
        wait(PEG_SEM_WRITE, caller);
    }

    // @exception Deadlock
    // @exception Permission
    // @exception AlreadyLocked
    // @exception WaitFailed
    inline void try_wait_read(PEGASUS_THREAD_TYPE caller)
    {
        try_wait(PEG_SEM_READ, caller);
    }

    // @exception Deadlock
    // @exception Permission
    // @exception AlreadyLocked
    // @exception WaitFailed
    inline void try_wait_write(PEGASUS_THREAD_TYPE caller)
    {
        try_wait(PEG_SEM_WRITE, caller);
    }

    // @exception Deadlock
    // @exception Permission
    // @exception TimeOut
    // @exception WaitFailed
    inline void timed_wait_read(PEGASUS_THREAD_TYPE caller, int milliseconds)
    {
        timed_wait(PEG_SEM_READ, caller, milliseconds);
    }

    // @exception Deadlock
    // @exception Permission
    // @exception TimeOut
    // @exception WaitFailed
    inline void timed_wait_write(PEGASUS_THREAD_TYPE caller, int milliseconds)
    {
        timed_wait(PEG_SEM_WRITE, caller, milliseconds);
    }

    // @exception Permission
    inline void unlock_read(PEGASUS_THREAD_TYPE caller)
    {
        unlock(PEG_SEM_READ, caller);
    }

    // @exception Permission
    inline void unlock_write(PEGASUS_THREAD_TYPE caller)
    {
        unlock(PEG_SEM_WRITE, caller);
    }

    int read_count() const;
    int write_count() const;

    // @exception Deadlock
    // @exception Permission
    // @exception WaitFailed
    // @exception TooManyReaders
    void wait(Uint32 mode, PEGASUS_THREAD_TYPE caller);

    // @exception Deadlock
    // @exception Permission
    // @exception WaitFailed
    // @exception TooManyReaders
    void try_wait(Uint32 mode, PEGASUS_THREAD_TYPE caller);

    // @exception Timeout
    // @exception Deadlock
    // @exception Permission
    // @exception WaitFailed
    // @exception TooManyReaders
    void timed_wait(Uint32 mode, PEGASUS_THREAD_TYPE caller, int milliseconds);

    // @exception Permission
    void unlock(Uint32 mode, PEGASUS_THREAD_TYPE caller);

private:
    AtomicInt _readers;
    AtomicInt _writers;
    PEGASUS_RWLOCK_HANDLE _rwlock;
    friend void extricate_read_write(void *);
};


// Classes used for safe locking of ReadWriteSem

class ReadLock
{
public:
    ReadLock(ReadWriteSem & rwsem) : _rwsem(rwsem)
    {
        _rwsem.wait_read(pegasus_thread_self());
    }

    ~ReadLock()
    {
        _rwsem.unlock_read(pegasus_thread_self());
    }

private:
    ReadWriteSem & _rwsem;
};

class WriteLock
{
public:
    WriteLock(ReadWriteSem & rwsem) : _rwsem(rwsem)
    {
        _rwsem.wait_write(pegasus_thread_self());
    }

    ~WriteLock()
    {
        _rwsem.unlock_write(pegasus_thread_self());
    }

private:
    ReadWriteSem & _rwsem;
};


//-----------------------------------------------------------------
/// Generic definition of conditional semaphore
//-----------------------------------------------------------------


#ifndef PEGASUS_CONDITIONAL_NATIVE

// typedef PEGASUS_SEMAPHORE_TYPE PEGASUS_COND_TYPE;

class PEGASUS_COMMON_LINKAGE cond_waiter : public Linkable
{
public:
    cond_waiter( PEGASUS_THREAD_TYPE caller, Sint32 time = -1)
        : waiter(caller), signalled(0) { }

    ~cond_waiter()
    {
       signalled.signal();
    }

private:
      cond_waiter();
      PEGASUS_THREAD_TYPE waiter;
      Semaphore signalled;
      friend class Condition;
};

typedef struct peg_condition{
    List<cond_waiter, NullLock> _waiters;
    Mutex _spin;
    peg_condition() : _waiters(), _spin()  { }
} PEGASUS_COND_TYPE;

#endif

class PEGASUS_COMMON_LINKAGE Condition
{
public:
    // create the condition variable
    Condition();
    ~Condition();
    Condition(Mutex& mutex);

    // signal the condition variable
    // @exception IPCException
    void signal(PEGASUS_THREAD_TYPE caller);

    // @exception IPCException
    void lock_object(PEGASUS_THREAD_TYPE caller);

    // @exception IPCException
    void try_lock_object(PEGASUS_THREAD_TYPE caller);

    // @exception IPCException
    void wait_lock_object(PEGASUS_THREAD_TYPE caller, int milliseconds);

    void unlock_object();

    // without pthread_mutex_lock/unlock
    // @exception IPCException
    void unlocked_wait(PEGASUS_THREAD_TYPE caller);

    // @exception IPCException
    void unlocked_timed_wait(int milliseconds, PEGASUS_THREAD_TYPE caller);

    // @exception IPCException
    void unlocked_signal(PEGASUS_THREAD_TYPE caller);

    void set_owner(PEGASUS_THREAD_TYPE caller)
    {
        _cond_mutex->_set_owner(caller);
    }

    void disallow()
    {
        _disallow++;
    }

    void reallow()
    {
        if(_disallow.get() > 0)
            _disallow--;
    }

    Boolean is_shutdown() const
    {
        if(_disallow.get() > 0)
            return true;
        return false;
    }

private:
    AtomicInt _disallow; // don't allow any further waiters
    Boolean _destroy_mut;
    PEGASUS_COND_TYPE _condition; // special type to control execution flow
    AutoPtr<Mutex> _cond_mutex; // the conditional mutex //PEP101
    friend void extricate_condition(void *);

    // Hide the copy constructor and assignment operator to avoid implicit
    // use of the defaults implementations.
    Condition(const Condition& original);
    Condition& operator=(const Condition& original);
};


#if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC)
# include "IPCWindows_inline.h"
#elif defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_HPUX_ACC)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_SOLARIS_SPARC_GNU)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_AIX_RS_IBMCXX)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_TRU64_ALPHA_DECCXX)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_OS400_ISERIES_IBM)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
# include "IPCUnix_inline.h"
#elif defined(PEGASUS_OS_VMS)
# include "IPCVms_inline.h"
#endif

PEGASUS_NAMESPACE_END

#endif /* Pegasus_IPC_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2