/* ---- This file is part of SECONDO. Copyright (C) 2019, Faculty of Mathematics and Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //[<] [\ensuremath{<}] //[>] [\ensuremath{>}] \setcounter{tocdepth}{3} \tableofcontents 1 Aux Classes Header File */ #pragma once #include "Operator.h" #include #include #include "condition_variable" #include "Algebras/Relation-C++/RelationAlgebra.h" namespace mthreaded { //global mutex for tuple counter extern std::mutex mutexTupleCounter_; const size_t PAGESIZE = WinUnix::getPageSize(); class MThreadedSingleton { public: static void setCoresToUse(const size_t cores); static size_t getCoresToUse(); private: static size_t cores_used; }; class Buffer { public: virtual void appendTuple(Tuple* tuple) = 0; virtual Tuple* readTuple() = 0; virtual void closeWrite() = 0; virtual void openRead() = 0; virtual bool empty() const = 0; Buffer() = default; ~Buffer() = default; }; class FileBuffer : public Buffer { private: std::string fname; std::shared_ptr tupleBuffer; TupleFileIterator* it; TupleType* tt; bool isEmpty; public: // Constructor FileBuffer explicit FileBuffer(TupleType* _tt); // Destructor FileBuffer ~FileBuffer(); // append single tuple into a file void appendTuple(Tuple* tuple) override; // read single tuple Tuple* readTuple() override; // close writing connection void closeWrite() override; // open for read void openRead() override; bool empty() const override; }; class MemoryBuffer : public Buffer { private: std::queue tupleBuffer; size_t bufferSize; TupleType* tt; bool isEmpty; public: // append single tuple into a file void appendTuple(Tuple* tuple) override; // read single tuple Tuple* readTuple() override; void closeWrite() override {} void openRead() override {} bool empty() const override; explicit MemoryBuffer(TupleType* _tt); ~MemoryBuffer(); }; class MultiBuffer : public Buffer { private: std::shared_ptr memoryBuffer; std::shared_ptr overflowBuffer; TupleType* tt; const size_t bufferSize; size_t bufferCounter; bool overflow; bool isEmpty; public: // append single tuple into a file void appendTuple(Tuple* tuple) override; // read single tuple Tuple* readTuple() override; void closeWrite() override; void openRead() override; bool empty() const override; MultiBuffer(TupleType* _tt, const size_t _bufferSize); ~MultiBuffer(); }; // threadsafe queue, has to be in header as it is a template class template class SafeQueue { public: SafeQueue(size_t _n) : q(), m(), c(), n(_n) { dataReadyQueue = false; } ~SafeQueue() { }; bool empty() const { return q.empty(); } size_t size() const { return q.size(); } // Add an element to the queue. void enqueue(T t) { std::lock_guard lock(m); q.push(t); dataReadyQueue = true; c.notify_one(); } // Get the "front"-element. // If the queue is empty, wait till a element is avaiable. T dequeue() { std::unique_lock lock(m); while (q.empty()) { c.wait(lock, [&] { return dataReadyQueue; }); dataReadyQueue = false; } T val = q.front(); q.pop(); return val; } private: std::queue q; bool dataReadyQueue; mutable std::mutex m; std::condition_variable c; size_t n; }; // threadsafe queue using tuplefiles // if used from several threads mutex has to be used // mutexTupleCounter_ class SafeQueuePersistent { public: SafeQueuePersistent (const size_t _bufferSize, TupleType* _tt); ~SafeQueuePersistent (); bool empty() const; // Add an element to the queue. void enqueue(Tuple* t); // Get the "front"-element. // If the queue is empty, wait till a element is avaiable. Tuple* dequeue(); private: const size_t bufferSize; TupleType* tt; std::shared_ptr tupleBuffer; TupleFileIterator* it; //std::shared_ptr bufferPersist; std::queue q; bool dataReadyQueue; mutable std::mutex m; std::condition_variable c; size_t bufferCounter; bool overflow; }; }