#ifndef FRAME_CACHE_HPP #define FRAME_CACHE_HPP #include #include #include #include #include #include #include #include #include #include "jungfraujoch.hpp" /** Frame cache Reimplemented RamBuffer for the better handling of image assembly and concurrency. The class operates on in-memory arrays via pointer/reference access. It uses a linearly increasing pulseID index to provide some headroom for collecting frames from multiple detectors. **/ class FrameCache{ public: FrameCache(uint64_t capacity, uint64_t line_size, uint64_t block_size, std::function*)> callback): m_capacity(capacity), m_linesize(line_size), m_blocksize(block_size), f_send(callback), m_vlock(capacity), m_valid(capacity), m_fill(capacity), m_meta(capacity), m_data(capacity) { // Reserve the data buffer for(auto& it: m_data){ it.resize(m_linesize*m_blocksize); } }; /** Emplace a specific frame and module **/ void emplace(uint64_t pulseID, uint64_t moduleID, char* ptr_source, ModuleFrame& ref_meta){ uint64_t idx = pulseID % m_capacity; // Wait for unlocking block while(m_vlock[idx]){ std::this_thread::yield(); } // Invalid cache line: Just start a new line if(m_valid[idx]){ start_line(idx, ref_meta); } // A new frame is starting if(ref_meta.frame_index != m_meta[idx].frame_index){ flush_line(idx); start_line(idx, ref_meta); } m_fill[idx]++; char* ptr_dest = m_data[idx].data() + moduleID * m_blocksize; std::memcpy(ptr_dest, (void*)ptr_source, m_blocksize); std::memcpy(&m_meta[idx], (void*)&ref_meta, sizeof(ModuleFrame)); } void flush_all(){ for(int64_t idx=0; idx< m_capacity; idx++){ flush_line(idx); } } void flush_line(uint64_t idx){ if(m_valid[idx]){ m_vlock[idx] = 1; std::cout << "Send action" << std::endl; f_send(&m_meta[idx], &m_data[idx]); m_valid[idx] = 0; m_fill[idx] = 0; m_vlock[idx] = 0; } } void start_line(uint64_t idx, ModuleFrame& ref_meta){ m_vlock[idx] = 1; m_meta[idx].pulse_id = ref_meta.pulse_id; m_meta[idx].frame_index = ref_meta.frame_index; m_meta[idx].daq_rec = ref_meta.daq_rec; m_meta[idx].is_good_image = true; m_valid[idx] = 1; m_fill[idx] = 0; m_vlock[idx] = 0; } private: const uint64_t m_capacity; const uint64_t m_linesize; const uint64_t m_blocksize; std::function*)> f_send; /** Main container and mutex guard **/ std::vector> m_vlock; std::vector> m_valid; std::vector> m_fill; std::vector m_meta; std::vector> m_data; }; #endif // FRAME_CACHE_HPP