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.
188 lines
4.8 KiB
188 lines
4.8 KiB
// 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.
|
|
|
|
#include <log4cplus/config.hxx>
|
|
#ifndef LOG4CPLUS_SINGLE_THREADED
|
|
|
|
#include <log4cplus/helpers/queue.h>
|
|
#include <log4cplus/helpers/loglog.h>
|
|
#include <log4cplus/thread/syncprims-pub-impl.h>
|
|
#include <stdexcept>
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
|
|
|
|
namespace log4cplus { namespace thread {
|
|
|
|
|
|
Queue::Queue (unsigned len)
|
|
: mutex (Mutex::DEFAULT)
|
|
, ev_consumer (false)
|
|
, sem (len, len)
|
|
, flags (DRAIN)
|
|
{ }
|
|
|
|
|
|
Queue::~Queue ()
|
|
{ }
|
|
|
|
|
|
Queue::flags_type
|
|
Queue::put_event (spi::InternalLoggingEvent const & ev)
|
|
{
|
|
flags_type ret_flags = ERROR_BIT;
|
|
try
|
|
{
|
|
ev.gatherThreadSpecificData ();
|
|
|
|
SemaphoreGuard semguard (sem);
|
|
MutexGuard mguard (mutex);
|
|
|
|
ret_flags |= flags;
|
|
|
|
if (flags & EXIT)
|
|
{
|
|
ret_flags &= ~(ERROR_BIT | ERROR_AFTER);
|
|
return ret_flags;
|
|
}
|
|
else
|
|
{
|
|
queue.push_back (ev);
|
|
ret_flags |= ERROR_AFTER;
|
|
semguard.detach ();
|
|
flags |= QUEUE;
|
|
ret_flags |= flags;
|
|
mguard.unlock ();
|
|
mguard.detach ();
|
|
ev_consumer.signal ();
|
|
}
|
|
}
|
|
catch (std::runtime_error const & e)
|
|
{
|
|
(void)e;
|
|
return ret_flags;
|
|
}
|
|
|
|
ret_flags &= ~(ERROR_BIT | ERROR_AFTER);
|
|
return ret_flags;
|
|
}
|
|
|
|
|
|
Queue::flags_type
|
|
Queue::signal_exit (bool drain)
|
|
{
|
|
flags_type ret_flags = 0;
|
|
|
|
try
|
|
{
|
|
MutexGuard mguard (mutex);
|
|
|
|
ret_flags |= flags;
|
|
|
|
if (! (flags & EXIT))
|
|
{
|
|
if (drain)
|
|
flags |= DRAIN;
|
|
else
|
|
flags &= ~DRAIN;
|
|
flags |= EXIT;
|
|
ret_flags = flags;
|
|
mguard.unlock ();
|
|
mguard.detach ();
|
|
ev_consumer.signal ();
|
|
}
|
|
}
|
|
catch (std::runtime_error const & e)
|
|
{
|
|
(void)e;
|
|
ret_flags |= ERROR_BIT;
|
|
return ret_flags;
|
|
}
|
|
|
|
return ret_flags;
|
|
}
|
|
|
|
|
|
Queue::flags_type
|
|
Queue::get_events (queue_storage_type * buf)
|
|
{
|
|
flags_type ret_flags = 0;
|
|
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
MutexGuard mguard (mutex);
|
|
|
|
ret_flags = flags;
|
|
|
|
if (((QUEUE & flags) && ! (EXIT & flags))
|
|
|| ((EXIT | DRAIN | QUEUE) & flags) == (EXIT | DRAIN | QUEUE))
|
|
{
|
|
assert (! queue.empty ());
|
|
|
|
std::size_t const count = queue.size ();
|
|
queue.swap (*buf);
|
|
queue.clear ();
|
|
flags &= ~QUEUE;
|
|
for (std::size_t i = 0; i != count; ++i)
|
|
sem.unlock ();
|
|
|
|
ret_flags = flags | EVENT;
|
|
break;
|
|
}
|
|
else if (((EXIT | QUEUE) & flags) == (EXIT | QUEUE))
|
|
{
|
|
assert (! queue.empty ());
|
|
queue.clear ();
|
|
flags &= ~QUEUE;
|
|
ev_consumer.reset ();
|
|
sem.unlock ();
|
|
ret_flags = flags;
|
|
break;
|
|
}
|
|
else if (EXIT & flags)
|
|
break;
|
|
else
|
|
{
|
|
ev_consumer.reset ();
|
|
mguard.unlock ();
|
|
mguard.detach ();
|
|
ev_consumer.wait ();
|
|
}
|
|
}
|
|
}
|
|
catch (std::runtime_error const & e)
|
|
{
|
|
(void)e;
|
|
ret_flags |= ERROR_BIT;
|
|
}
|
|
|
|
return ret_flags;
|
|
}
|
|
|
|
|
|
} } // namespace log4cplus { namespace thread {
|
|
|
|
|
|
#endif // LOG4CPLUS_SINGLE_THREADED
|