Source: classlib/include/classlib/squeue.h


Annotated List
Files
Globals
Hierarchy
Index
// squeue.h : coda generica con controllo multithread
// Nicola De Nisco			S.Lucia di Piave, 8 Giugno 1998

#if !defined( __CLASSLIB_SQUEUE_H )
#define __CLASSLIB_SQUEUE_H

#if !defined( __CLASSLIB_QUEUES_H )
#include "classlib/queues.h"
#endif  // __CLASSLIB_DEFS_H

#include "classlib/mtsync.h"

template  class TISTQueueIterator;

/**
	Thread safe queue.
	This class implements a thread safe queue ready to use
	in multitread application. The queue have a CriticalSection (see)
	for syncronization of insertion end extraction from the queue.
	It can notify a waiting thread when new item are inserted into the queue
	(see the LockIfEmpty method).
	The internal implementation is a linked list queue.
*/
template  class TISTQueue :
    private TIQueueAsDoubleList
{

    typedef TIQueueAsDoubleList Parent;

public:

    //enum DeleteType { NoDelete, DefDelete, Delete };

    friend class TISTQueueIterator;

	/**
		Construct the queue and the semaphore in non blocking state
	*/
	TISTQueue() : evitem( FALSE, TRUE )
		{
		evitem.ResetEvent();
		}

	/**
		Get an element from the queue. The get operation request the lock
		of a CriticalSection (see) to proceed. The calling thread will be locked
		if another thread is accessing another lock method.
	*/
    T *Get()
        {
		csec.Lock();
        T* ptTmp = Parent::Get();
		if( IsEmpty() )
			evitem.ResetEvent();
		csec.Unlock();
		return ptTmp;
        }

	/**
		Put an element into the queue. The put operation request the lock
		of a CriticalSection (see) to proceed. The calling thread will be locked
		if another thread is accessing another lock method.
	*/
    void Put( T *t )
        {
		csec.Lock();
        Parent::Put( t );
		evitem.SetEvent();
		csec.Unlock();
        }

	/**
		Destroy all elements into the queue. The flush operation request the lock
		of a CriticalSection (see) to proceed. The calling thread will be locked
		if another thread is accessing another lock method.
	*/
    void Flush()
        {
		csec.Lock();
		Parent::Flush();
		evitem.ResetEvent();
		csec.Unlock();
        }

	/**
		Detach an element from the queue. The detach operation request the lock
		of a CriticalSection (see) to proceed. The calling thread will be locked
		if another thread is accessing another lock method.
	*/
    int Detach( T *t )
        {
		csec.Lock();
        int rv = Parent::Detach(t);
		if( IsEmpty() )
			evitem.ResetEvent();
		csec.Unlock();
		return rv;
        }

    typedef void (*IterFunc)(T&, void *);
    typedef int  (*CondFunc)(const T&, void *);

	/** auto iterator: use an iterator function calling it for every element of the array;
		the function must have a prototype like this: void iterFunc(T&, void* args);
		The operation request the lock
		of a CriticalSection (see) to proceed. The calling thread will be locked
		if another thread is accessing another lock method.	*/
    void ForEach( IterFunc iter, void *args )
        {
		csec.Lock();
		Parent::ForEach( iter, args );
		csec.Unlock();
        }

	/** auto iterator: use a test function calling it for every element of the array;
	    the function must have a prototype like this: int testFunc(const T&, void* args);
		the function must return 0 if the test fail, != 0 if test is ok; the first element
		tested successful will be returned or NULL if no elements is ok.
		The operation request the lock
		of a CriticalSection (see) to proceed. The calling thread will be locked
		if another thread is accessing another lock method.	*/
    T *FirstThat( CondFunc cond, void *args )
        {
		csec.Lock();
        T* rv = Parent::FirstThat( cond, args );
		csec.Unlock();
		return rv;
        }

	/** auto iterator: use a test function calling it for every element of the array;
	    the function must have a prototype like this: int testFunc(const T&, void* args);
		the function must return 0 if the test fail, != 0 if test is ok; the last element
		tested successful will be returned or NULL if no elements is ok.
		The operation request the lock
		of a CriticalSection (see) to proceed. The calling thread will be locked
		if another thread is accessing another lock method.	*/
    T *LastThat( CondFunc cond, void *args )
        {
		csec.Lock();
        T* rv = Parent::LastThat( cond, args );
		csec.Unlock();
		return rv;
        }

	Parent::Peek;
    Parent::IsEmpty;
    Parent::GetItemsInContainer;

	void LockIfEmpty() 
		{
		CSingleLock(&evitem, TRUE);
		}

protected:
	CCriticalSection	csec;
	CEvent				evitem;
};

/**
	The TISTQueue iterator.
	This iterator try to acquire the CriticalSection of the queue.
	The calling thread will be locked if another thread is accessing another lock method.
	IMPORTANT NOTE: the iterator destructor release the lock.
	The queue will be locked for the complete lifecicle of the Iterator instance.
*/
template  class TISTQueueIterator :
    public TIQueueAsDoubleListIterator
{
public:

    TISTQueueIterator( TISTQueue& q ) :
        TIQueueAsDoubleListIterator(q)
        {
			ptQueue = &q;
			ptQueue->csec.Lock();
        }

	virtual ~TISTQueueIterator()
		{
			ptQueue->csec.Unlock();
		}

private:
	TISTQueue* ptQueue;
};

#endif // __CLASSLIB_SQUEUE_H



Generated by: nicola on gulliver.wadahome.it on Sun May 25 13:54:34 2003, using kdoc 2.0a53.