You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

158 lines
5.4 KiB

// -*- C++ -*-
// Copyright (C) 2009-2010, Vaclav Haisman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, 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.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, 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.
#ifndef LOG4CPLUS_HELPERS_QUEUE_H
#define LOG4CPLUS_HELPERS_QUEUE_H
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
#pragma once
#endif
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
#include <deque>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus/thread/threads.h>
#include <log4cplus/thread/syncprims.h>
namespace log4cplus { namespace thread {
//! Single consumer, multiple producers queue.
class LOG4CPLUS_EXPORT Queue
: public virtual helpers::SharedObject
{
public:
//! Type of the state flags field.
typedef unsigned flags_type;
//! Queue storage type.
typedef std::deque<spi::InternalLoggingEvent> queue_storage_type;
Queue (unsigned len = 100);
virtual ~Queue ();
// Producers' methods.
//! Puts event <code>ev</code> into queue, sets QUEUE flag and
//! sets internal event object into signaled state. If the EXIT
//! flags is already set upon entering the function, nothing is
//! inserted into the queue. The function can block on internal
//! semaphore if the queue has reached maximal allowed
//! length. Calling thread is unblocked either by consumer thread
//! removing item from queue or by any other thread calling
//! signal_exit().
//!
//! \param ev spi::InternalLoggingEvent to be put into the queue.
//! \return Flags.
flags_type put_event (spi::InternalLoggingEvent const & ev);
//! Sets EXIT flag and DRAIN flag and sets internal event object
//! into signaled state.
//! \param drain If true, DRAIN flag will be set, otherwise unset.
//! \return Flags, ERROR_BIT can be set upon error.
flags_type signal_exit (bool drain = true);
// Consumer's methods.
//! The get_events() function is used by queue's consumer. It
//! fills <code>buf</code> argument and sets EVENT flag in return
//! value. If EXIT flag is already set in flags member upon
//! entering the function then depending on DRAIN flag it either
//! fills <code>buf</code> argument or does not fill the argument,
//! if the queue is non-empty. The function blocks by waiting for
//! internal event object to be signaled if the queue is empty,
//! unless EXIT flag is set. The calling thread is unblocked when
//! items are added into the queue or when exit is signaled using
//! the signal_exit() function.
//!
//!
//! Upon error, return value has one of the error flags set.
//!
//! \param buf Pointer to storage of spi::InternalLoggingEvent
//! instances to be filled from queue.
//! \return Flags.
flags_type get_events (queue_storage_type * buf);
//! Possible state flags.
enum Flags
{
//! EVENT flag is set in return value of get_event() call if
//! the <code>ev</code> argument is filled with event from the queue.
EVENT = 0x0001,
//! QUEUE flag is set by producers when they put item into the
//! queue.
QUEUE = 0x0002,
//! EXIT flag is set by signal_exit() call, signaling that the
//! queue worker thread should end itself.
EXIT = 0x0004,
//! When DRAIN flag is set together with EXIT flag, the queue
//! worker thread will first drain the queue before exiting.
DRAIN = 0x0008,
//! ERROR_BIT signals error.
ERROR_BIT = 0x0010,
//! ERROR_AFTER signals error that has occured after queue has
//! already been touched.
ERROR_AFTER = 0x0020
};
protected:
//! Queue storage.
queue_storage_type queue;
//! Mutex protecting queue and flags.
Mutex mutex;
//! Event on which consumer can wait if it finds queue empty.
ManualResetEvent ev_consumer;
//! Semaphore that limits the queue length.
Semaphore sem;
//! State flags.
flags_type flags;
private:
Queue (Queue const &);
Queue & operator = (Queue const &);
};
typedef helpers::SharedObjectPtr<Queue> QueuePtr;
} } // namespace log4cplus { namespace thread {
#endif // LOG4CPLUS_SINGLE_THREADED
#endif // LOG4CPLUS_HELPERS_QUEUE_H