1
0
Fork 0
mirror of https://github.com/gwm17/DaqGrimoire.git synced 2024-11-26 20:28:51 -05:00

Adding the code

This commit is contained in:
Gordon McCann 2022-09-29 20:36:44 -04:00
parent ae9c724d21
commit 6f647bf370
6 changed files with 459 additions and 0 deletions

50
include/DYListData.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef DY_LIST_DATA_H
#define DY_LIST_DATA_H
#include <cstdint>
#include <cstddef>
namespace DaqGrimoire {
namespace Data
{
static constexpr std::size_t Size = 24;
}
struct DYListData
{
uint16_t board;
uint16_t channel;
uint64_t timestamp;
uint32_t energy;
uint32_t energyShort;
uint32_t flags;
};
namespace Utils
{
void GetDataEventFromBuffer(char* bufferIter, DYListData& dataEvent)
{
dataEvent.board = *((uint16_t*)bufferIter);
bufferIter += 2;
dataEvent.channel = *((uint16_t*)bufferIter);
bufferIter += 2;
dataEvent.timestamp = *((uint64_t*)bufferIter);
bufferIter += 8;
dataEvent.energy = *((uint32_t*)bufferIter);
bufferIter += 4;
dataEvent.energyShort = *((uint32_t*)bufferIter);
bufferIter += 4;
dataEvent.flags = *((uint32_t*)bufferIter);
bufferIter += 4;
}
}
}
#endif

10
include/DaqGrimoire.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef DAQ_GRIMOIRE_H
#define DAQ_GRIMOIRE_H
#include "FileIO/DYFileReader.h"
#ifdef DG_HAS_ASIO
#include "NetIO/DYClient.h"
#endif
#endif

View File

@ -0,0 +1,123 @@
#ifndef DY_FILE_READER_H
#define DY_FILE_READER_H
#include "../DYListData.h"
#include <filesystem>
#include <memory>
#include <fstream>
#include <vector>
namespace DaqGrimoire {
class DYFileReader
{
public:
DYFileReader() :
m_fileHandle(nullptr), m_bufferSizeEvents(200000), m_isEOF(false), m_fileSizeBytes(0), m_fileSizeEvents(0), m_bufferIter(nullptr), m_bufferEnd(nullptr)
{
}
DYFileReader(std::size_t bufferSize) :
m_fileHandle(nullptr), m_bufferSizeEvents(bufferSize), m_isEOF(false), m_fileSizeBytes(0), m_fileSizeEvents(0), m_bufferIter(nullptr), m_bufferEnd(nullptr)
{
}
DYFileReader(const std::filesystem::path& filepath, std::size_t bufferSize = 200000) :
m_fileHandle(nullptr), m_bufferSizeEvents(bufferSize), m_isEOF(false), m_fileSizeBytes(0), m_fileSizeEvents(0), m_bufferIter(nullptr), m_bufferEnd(nullptr)
{
Open(filepath);
}
~DYFileReader()
{
Close();
}
void Open(const std::filesystem::path& filepath)
{
m_filepath = filepath;
m_fileHandle->open(filepath, std::ios::binary | std::ios::in);
m_fileHandle->seekg(0, std::ios_base::end);
m_fileSizeBytes = m_fileHandle->tellg();
//Replace this
if (m_fileSizeBytes == 0 || m_fileSizeBytes < Data::Size)
{
m_isEOF = true;
return;
}
else if (m_fileSizeBytes % Data::Size != 0)
{
m_isEOF = true;
return;
}
m_fileSizeEvents = m_fileSizeBytes / Data::Size;
m_rawBuffer.resize(m_bufferSizeEvents * Data::Size);
}
void Close()
{
if (IsOpen())
m_fileHandle->close();
}
bool GetNextEvent(DYListData& dataEvent)
{
if (!IsOpen() || IsEOF())
return false;
if (m_bufferIter == m_bufferEnd)
{
FillBuffer();
if (IsEOF())
return false;
}
Utils::GetDataEventFromBuffer(m_bufferIter, dataEvent);
return true;
}
const bool IsOpen() const { return m_fileHandle == nullptr ? false : m_fileHandle->is_open(); }
const bool IsEOF() const { return m_isEOF; }
const std::size_t GetFileSizeBytes() const { return m_fileSizeBytes; }
const std::size_t GetFileSizeEvents() const { return m_fileSizeEvents; }
private:
void FillBuffer()
{
if (m_fileHandle->eof())
{
m_isEOF = true;
return;
}
m_fileHandle->read(m_rawBuffer.data(), m_rawBuffer.size());
m_bufferIter = m_rawBuffer.data();
m_bufferEnd = m_bufferIter + m_fileHandle->gcount(); //one past the last datum
}
std::filesystem::path m_filepath;
std::shared_ptr<std::ifstream> m_fileHandle;
std::vector<char> m_rawBuffer;
std::size_t m_bufferSizeEvents; //in units of data events
std::size_t m_fileSizeBytes; //in bytes
std::size_t m_fileSizeEvents; //in data events
bool m_isEOF;
char* m_bufferIter;
char* m_bufferEnd;
};
}
#endif

129
include/NetIO/DYClient.h Normal file
View File

@ -0,0 +1,129 @@
#ifndef DY_CLIENT_H
#define DY_CLIENT_H
#include "DYMessage.h"
#include "ThreadSafeQueue.h"
#include "asio.hpp"
namespace DaqGrimoire {
class DYClient
{
public:
DYClient(const std::string& address, const std::string& port) :
m_socket(m_context)
{
Connect(address, port);
}
~DYClient()
{
Disconnect();
}
bool GetNextEvent(DYListData& dataEvent)
{
if (m_dataQueue.IsEmpty())
return false;
dataEvent = m_dataQueue.Front();
m_dataQueue.PopFront();
return true;
}
void Connect(const std::string& address, const std::string& port)
{
try
{
asio::ip::tcp::resolver resolver(m_context);
auto end_points = resolver.resolve(address, port);
asio::async_connect(m_socket, end_points,
[this](std::error_code ec, asio::ip::tcp::endpoint endpoint)
{
if (!ec)
{
ReadHeader();
}
}
);
m_asioThread = std::thread([this]() { m_context.run() });
}
catch (asio::system_error& e)
{
continue;
}
}
void Disconnect()
{
if (IsConnected())
{
asio::post(m_context, [this]() { m_socket.close(); })
}
m_context.stop();
if (m_asioThread.joinable())
m_asioThread.join();
}
bool IsConnected() { return m_socket.is_open(); }
private:
void ReadHeader()
{
asio::async_read(m_socket, asio::buffer(&m_tempMessage.size, sizeof(m_tempMessage.size)),
[this](std::error_code ec, std::size_t size)
{
if (!ec)
{
if (m_tempMessage.size > 0)
{
m_tempMessage.body.resize(m_tempMessage.size);
ReadBody();
}
else
ReadHeader();
}
}
);
}
void ReadBody()
{
asio::async_read(m_socket, asio::buffer(m_tempMessage.body.data(), m_tempMessage.body.size()),
[this](std::error_code ec, std::size_t size)
{
if (!ec)
{
char* dataPtr = m_tempMessage.body.data();
char* endPtr = m_tempMessage.body.data() + m_tempMessage.body.size();
DYListData tempData;
while (dataPtr != endPtr)
{
Utils::GetDataEventFromBuffer(dataPtr, tempData);
m_dataQueue.PushBack(tempData);
}
ReadHeader();
}
}
);
}
asio::io_context m_context;
asio::ip::tcp::socket m_socket;
std::thread m_asioThread;
DYMessage m_tempMessage;
ThreadSafeQueue<DYListData> m_dataQueue;
};
}
#endif

19
include/NetIO/DYMessage.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef DY_MESSAGE_H
#define DY_MESSAGE_H
#include "../DYListData.h"
#include <vector>
namespace DaqGrimoire {
struct DYMessage
{
DYMessage() = default;
uint64_t size;
std::vector<char> body;
};
}
#endif

View File

@ -0,0 +1,128 @@
#ifndef THREAD_SAFE_QUEUE_H
#define THREAD_SAFE_QUEUE_H
#include <deque>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <atomic>
namespace DaqGrimoire {
template<typename T>
class ThreadSafeQueue
{
public:
ThreadSafeQueue() = default;
ThreadSafeQueue(const ThreadSafeQueue&) = delete; //no copy
~ThreadSafeQueue() { Clear(); }
void PushBack(const T& data)
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
m_queue.push_back(data);
std::scoped_lock<std::mutex> condGuard(m_conditionMutex);
m_conditional.notify_one();
}
void PushFront(const T& data)
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
m_queue.push_front(data);
std::scoped_lock<std::mutex> conditionGuard(m_conditionMutex);
m_conditional.notify_one();
}
void PopBack()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
m_queue.pop_back();
}
void PopFront()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
m_queue.pop_front();
}
const T& Front()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
return m_queue.front();
}
const T& Back()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
return m_queue.back();
}
std::size_t Size()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
return m_queue.size();
}
bool IsEmpty()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
return m_queue.empty();
}
void Clear()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
m_queue.clear();
}
//For iterator loops, need begin()/end() idiom
std::deque<T>::iterator begin()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
return m_queue.begin();
}
std::deque<T>::iterator end()
{
std::scoped_lock<std::mutex> guard(m_queueMutex);
return m_queue.end();
}
void Wait()
{
while (IsEmpty() && !m_isForceWakeup)
{
std::unique_lock<std::mutex> guard(m_conditionMutex);
m_conditional.wait(guard);
}
}
void ForceWakeup()
{
m_isForceWakeup = true;
std::unique_lock<std::mutex> guard(m_conditionMutex);
m_conditional.notify_one();
}
void ResetWakeup()
{
m_isForceWakeup = false;
}
private:
std::mutex m_queueMutex;
std::deque<T> m_queue;
std::mutex m_conditionMutex;
std::condition_variable m_conditional;
std::atomic<bool> m_isForceWakeup = false;
};
}
#endif