duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

cdrom_async_reader.h (2849B)


      1 // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #pragma once
      5 #include "util/cd_image.h"
      6 #include "types.h"
      7 #include <array>
      8 #include <atomic>
      9 #include <condition_variable>
     10 #include <thread>
     11 
     12 class ProgressCallback;
     13 
     14 class CDROMAsyncReader
     15 {
     16 public:
     17   using SectorBuffer = std::array<u8, CDImage::RAW_SECTOR_SIZE>;
     18 
     19   struct BufferSlot
     20   {
     21     CDImage::LBA lba;
     22     SectorBuffer data;
     23     CDImage::SubChannelQ subq;
     24     bool result;
     25   };
     26 
     27   CDROMAsyncReader();
     28   ~CDROMAsyncReader();
     29 
     30   CDImage::LBA GetLastReadSector() const { return m_buffers[m_buffer_front.load()].lba; }
     31   const SectorBuffer& GetSectorBuffer() const { return m_buffers[m_buffer_front.load()].data; }
     32   const CDImage::SubChannelQ& GetSectorSubQ() const { return m_buffers[m_buffer_front.load()].subq; }
     33   u32 GetBufferedSectorCount() const { return m_buffer_count.load(); }
     34   bool HasBufferedSectors() const { return (m_buffer_count.load() > 0); }
     35   u32 GetReadaheadCount() const { return static_cast<u32>(m_buffers.size()); }
     36 
     37   bool HasMedia() const { return static_cast<bool>(m_media); }
     38   const CDImage* GetMedia() const { return m_media.get(); }
     39   CDImage* GetMedia() { return m_media.get(); }
     40   const std::string& GetMediaFileName() const { return m_media->GetFileName(); }
     41 
     42   bool IsUsingThread() const { return m_read_thread.joinable(); }
     43   void StartThread(u32 readahead_count = 8);
     44   void StopThread();
     45 
     46   void SetMedia(std::unique_ptr<CDImage> media);
     47   std::unique_ptr<CDImage> RemoveMedia();
     48 
     49   /// Precaches image, either to memory, or using the underlying image precache.
     50   bool Precache(ProgressCallback* callback);
     51 
     52   void QueueReadSector(CDImage::LBA lba);
     53 
     54   bool WaitForReadToComplete();
     55   void WaitForIdle();
     56 
     57   /// Bypasses the sector cache and reads directly from the image.
     58   bool ReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data);
     59 
     60 private:
     61   void EmptyBuffers();
     62   bool ReadSectorIntoBuffer(std::unique_lock<std::mutex>& lock);
     63   void ReadSectorNonThreaded(CDImage::LBA lba);
     64   bool InternalReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data);
     65   void CancelReadahead();
     66 
     67   void WorkerThreadEntryPoint();
     68 
     69   std::unique_ptr<CDImage> m_media;
     70 
     71   std::mutex m_mutex;
     72   std::thread m_read_thread;
     73   std::condition_variable m_do_read_cv;
     74   std::condition_variable m_notify_read_complete_cv;
     75 
     76   std::atomic<CDImage::LBA> m_next_position{};
     77   std::atomic_bool m_next_position_set{false};
     78   std::atomic_bool m_shutdown_flag{true};
     79 
     80   std::atomic_bool m_is_reading{false};
     81   std::atomic_bool m_can_readahead{false};
     82   std::atomic_bool m_seek_error{false};
     83 
     84   std::vector<BufferSlot> m_buffers;
     85   std::atomic<u32> m_buffer_front{0};
     86   std::atomic<u32> m_buffer_back{0};
     87   std::atomic<u32> m_buffer_count{0};
     88 };