#if !defined(VOCAL_FIFOBASE_H)
#define VOCAL_FIFOBASE_H
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@vovida.org.
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
static const char* const FifoBase_h_Version =
"$Id: FifoBase.h,v 1.23.2.1 2003/01/30 22:39:09 bko Exp $";
#include "Mutex.hxx"
#include "Condition.hxx"
#include "TimerContainer.hxx"
#include "Sptr.hxx"
#include "Lock.hxx"
#include "TimeVal.hxx"
#include "NonCopyable.hxx"
#include <list>
using namespace Vocal::TimeAndDate;
namespace Vocal {
namespace TimeAndDate {
class TimeVal;
}
}
/** Infrastructure common to VOCAL.
*/
namespace Vocal
{
using Vocal::TimeAndDate::TimeVal;
using Vocal::Threads::Mutex;
using Vocal::Threads::Condition;
using Vocal::Threads::Lock;
using std::list;
/**
First in first out queue interface, with the added functionality of
being able to handle timed entries.
<P>
<B>Example 1:</b>
<p>
In a shared context:
<pre>
Fifo<int> f;
</pre>
<p>
In thread 1:
<p>
<pre>
f.add(1); // add the number 1 to the fifo f
</pre>
<p>
In thread 2:
<p>
<pre>
int x = f.getNext();
// now, x == 1
</pre>
<b>Example 2:</b>
<p>
In a shared context:
<pre>
Fifo<int> f;
</pre>
<p>
In thread 1:
<p>
<pre>
// add the number 1 to the fifo f after 1000 ms delay
f.addDelayMs(1, 1000);
</pre>
<p>
In thread 2:
<p>
<pre>
int x = f.getNext();
// now, x == 1
// note that this will block for 1000ms for the number to be put
// in the fifo.
</pre>
*/
template < class Msg >
class FifoBase : public NonCopyable
{
public:
/** Id for delayed events. Needed to cancel an event.
*/
typedef Vocal::TimeAndDate::TimerEntryId EventId;
protected:
/** Create an empty fifo.
*/
FifoBase();
public:
/** Delete the fifo.
*/
virtual ~FifoBase();
/** Add a message to the fifo.
*/
void add(const Msg &);
/** If the relative timeout is greater than 0, the message will
* be added to the fifo after the number of milliseconds have passed.
*
* The returned value is an opaque id that can be used
* to cancel the event before the timer expires. If the
* time is specified as 0, this defaults the to the
* regular add(), returning an id of 0.
*/
EventId addDelay(
const Msg &,
const TimeVal & relativeTimeout);
/** If the expiry time is later than the time now, the message will
* be added to the fifo after the time has passed.
*
* The returned value is an opaque id that can be used
* to cancel the event before the timer expires. If the
* time is specified as 0, this defaults the to the
* regular add(), returning an id of 0.
*/
EventId addUntil(
const Msg &,
const TimeVal & when);
/** If the relative timeout (in milliseconds) is greater than 0,
* the message will be added to the fifo after the number of
* milliseconds have passed.
*
* The returned value is an opaque id that can be used
* to cancel the event before the timer expires. If the
* time is specified as 0, this defaults the to the
* regular add(), returning an id of 0.
*/
EventId addDelayMs(
const Msg &,
const milliseconds_t relativeTimeout);
/** If the expiry time (in milliseconds) is later than the
* time now, the message will be added to the fifo after the
* time has passed.
*
* The returned value is an opaque id that can be used
* to cancel the event before the timer expires. If the
* time is specified as 0, this defaults the to the
* regular add(), returning an id of 0.
*/
EventId addUntilMs(
const Msg &,
const milliseconds_t when);
/** Cancel a delayed event.
*/
void cancel(EventId);
/** Blocks until a message is available, or the specified timeout has
* expired. If the return code is 0, then the fifo was interrupted
* via a signal or the timeout expired without a message being added
* to the queue. Using block is the only way to guarantee detection
* of a signal has been thrown.
*/
int block(milliseconds_t relativeTimeout = -1)
throw ( VException );
/** Returns the first message available. It will wait if no
* messages are available. If a signal interrupts the wait,
* it will retry the wait. Signals can therefore not be caught
* via getNext. If you need to detect a signal, use block
* prior to calling getNext.
*/
Msg getNext() throw ( VException );
/** Get the current size of the fifo. Note that the current
* size includes all of the pending events, even those which
* have not yet activated so you should not use this function
* to determine whether a call to getNext() will block or not.
* Use messageAvailable() instead.
*/
unsigned int size() const;
/** Get the current number of messages available. Note that
* the size does not include all of the pending events.
* You may not want to this function to determine the number of times
* you could call getNext() before it would block, since messages
* may become available during message processing. Consider using
* messageAvailable() instead.
*/
unsigned int sizeAvailable() const;
/** Get the current number of messages pending. Note that the current
* size does not include the available messages. You should not use
* this function to determine whether a call to getNext() will block
* or not. Use messageAvailable() instead.
*/
unsigned int sizePending() const;
/** Returns true if a message is available.
*/
bool messageAvailable();
/** Indicate that the fifo no longer accepts messages.
*/
void shutdown();
/** Relational operators. Useful if this is ever in a container.
*/
bool operator==(const FifoBase &) const;
/** Relational operators. Useful if this is ever in a container.
*/
bool operator!=(const FifoBase &) const;
/** Relational operators. Useful if this is ever in a container.
*/
bool operator< (const FifoBase &) const;
/** Relational operators. Useful if this is ever in a container.
*/
bool operator<=(const FifoBase &) const;
/** Relational operators. Useful if this is ever in a container.
*/
bool operator> (const FifoBase &) const;
/** Relational operators. Useful if this is ever in a container.
*/
bool operator>=(const FifoBase &) const;
protected:
/** Returns true if a message is available. The default implementation
* looks at the size of the fifo. Derived classes may also observe
* other resources as well. Note that the mutex should not be locked
* by this routine, since it would cause a deadlock.
*/
virtual bool messageAvailableNoLock();
/** Wake's up the blocked thread. Note that the mutex is locked
* upon entry. It is the responsibility of the user to unlock
* the mutex if necessary, making sure to relock it before exit.
*/
virtual void wakeup() throw ( VException ) = 0;
/** Blocks the thread, for the given time, waiting for a message.
* Note that the mutex is locked upon entry. It is the responsibility
* of the user to unlock the mutex if necessary, making sure
* to relock it before exit. The return code is positive for
* to indicate activity, i.e. messages added to the queue. For
* a signal or a timeout, 0 should be returned.
*/
virtual int wait(milliseconds_t relativeTimeout)
throw ( VException ) = 0;
typedef list < Sptr < Msg > > MessageContainer;
/**
*/
MessageContainer myFifo;
unsigned long myFifoSize;
/** Protects fifo and timer.
*/
mutable Threads::Mutex myMutex;
private:
int blockNoLock(milliseconds_t relativeTimeout = -1)
throw ( VException );
void postAddTimed(const EventId &);
Vocal::TimeAndDate::TimerContainer < Msg > myTimer;
unsigned long myTimerSize;
bool myShutdown;
};
/** Opaque id so that time delayed fifo events may be cancelled.
* For backwards compatibility. Use FifoBase::EventId instead.
*/
typedef Vocal::TimeAndDate::TimerEntryId FifoEventId;
#include "FifoBase.cc"
} // namespace Vocal
#endif // !defined(VOCAL_FIFOBASE_H)
syntax highlighted by Code2HTML, v. 0.9.1