/*************************************************************************** * Copyright (C) gempa GmbH * * All rights reserved. * * Contact: gempa GmbH (seiscomp-dev@gempa.de) * * * * GNU Affero General Public License Usage * * This file may be used under the terms of the GNU Affero * * Public License version 3.0 as published by the Free Software Foundation * * and appearing in the file LICENSE included in the packaging of this * * file. Please review the following information to ensure the GNU Affero * * Public License version 3.0 requirements will be met: * * https://www.gnu.org/licenses/agpl-3.0.html. * * * * Other Usage * * Alternatively, this file may be used in accordance with the terms and * * conditions contained in a signed written agreement between you and * * gempa GmbH. * ***************************************************************************/ #ifndef SEISCOMP_CLIENT_QUEUE_IPP #define SEISCOMP_CLIENT_QUEUE_IPP #include #include #include namespace Seiscomp { namespace Client { namespace { template struct QueueHelper {}; template struct QueueHelper { static void clean(const std::vector &) {} static T defaultValue() { return T(); } }; template struct QueueHelper { static void clean(const std::vector &b) { for ( size_t i = 0; i < b.size(); ++i ) { if ( b[i] ) delete b[i]; } } static T defaultValue() { return nullptr; } }; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template ThreadedQueue::ThreadedQueue() : _begin(0), _end(0), _buffered(0), _closed(false), _buffer(0) {} // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template ThreadedQueue::ThreadedQueue(int n) : _begin(0), _end(0), _buffered(0), _closed(false), _buffer(n) {} // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template ThreadedQueue::~ThreadedQueue() { close(); QueueHelper::value>::clean(_buffer); } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template void ThreadedQueue::resize(int n) { lock lk(_monitor); _buffer.resize(n); } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template bool ThreadedQueue::canPush() const { lock lk(_monitor); if ( _closed ) throw QueueClosedException(); return _buffered < _buffer.size(); } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template bool ThreadedQueue::push(T v) { lock lk(_monitor); while (_buffered == _buffer.size() && !_closed) _notFull.wait(lk); if ( _closed ) { _notEmpty.notify_all(); return false; } _buffer[_end] = v; _end = (_end+1) % _buffer.size(); ++_buffered; _notEmpty.notify_all(); return true; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template bool ThreadedQueue::pushUnique(T v) { lock lk(_monitor); // Find existing item auto it = _begin; while ( it != _end ) { if ( _buffer[it] == v ) { return true; } it = (it + 1) % _buffer.size(); } while (_buffered == _buffer.size() && !_closed) _notFull.wait(lk); if ( _closed ) { _notEmpty.notify_all(); return false; } _buffer[_end] = v; _end = (_end+1) % _buffer.size(); ++_buffered; _notEmpty.notify_all(); return true; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template bool ThreadedQueue::canPop() const { lock lk(_monitor); if ( _closed ) throw QueueClosedException(); return _buffered > 0; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template T ThreadedQueue::pop() { lock lk(_monitor); while (_buffered == 0 && !_closed) { _notEmpty.wait(lk); } if ( _closed ) throw QueueClosedException(); T v = _buffer[_begin]; _buffer[_begin] = QueueHelper::value>::defaultValue(); _begin = (_begin+1) % _buffer.size(); --_buffered; _notFull.notify_all(); return v; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template void ThreadedQueue::close() { lock lk(_monitor); if ( _closed ) return; _closed = true; _notFull.notify_all(); _notEmpty.notify_all(); } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template bool ThreadedQueue::isClosed() const { lock lk(_monitor); return _closed; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template size_t ThreadedQueue::size() const { lock lk(_monitor); return _buffered; } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> template void ThreadedQueue::reset() { lock lk(_monitor); _closed = false; _begin = _end = 0; _buffered = 0; QueueHelper::value>::clean(_buffer); std::fill(_buffer.begin(), _buffer.end(), QueueHelper::value>::defaultValue()); } // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> } } #endif