本文整理汇总了C++中common::SPSCQueue类的典型用法代码示例。如果您正苦于以下问题:C++ SPSCQueue类的具体用法?C++ SPSCQueue怎么用?C++ SPSCQueue使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了SPSCQueue类的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。
示例1: DoState
void DoState(PointerWrap& p)
{
// By waiting for the DVD thread to be done working, we ensure
// that s_request_queue will be empty and that the DVD thread
// won't be touching anything while this function runs.
WaitUntilIdle();
// Move all results from s_result_queue to s_result_map because
// PointerWrap::Do supports std::map but not Common::SPSCQueue.
// This won't affect the behavior of FinishRead.
ReadResult result;
while (s_result_queue.Pop(result))
s_result_map.emplace(result.first.id, std::move(result));
// Both queues are now empty, so we don't need to savestate them.
p.Do(s_result_map);
p.Do(s_next_id);
// s_disc isn't savestated (because it points to files on the
// local system). Instead, we check that the status of the disc
// is the same as when the savestate was made. This won't catch
// cases of having the wrong disc inserted, though.
// TODO: Check the game ID, disc number, revision?
bool had_disc = HasDisc();
p.Do(had_disc);
if (had_disc != HasDisc())
{
if (had_disc)
PanicAlertT("An inserted disc was expected but not found.");
else
s_disc.reset();
}
// TODO: Savestates can be smaller if the buffers of results aren't saved,
// but instead get re-read from the disc when loading the savestate.
// TODO: It would be possible to create a savestate faster by stopping
// the DVD thread regardless of whether there are pending requests.
// After loading a savestate, the debug log in FinishRead will report
// screwed up times for requests that were submitted before the savestate
// was made. Handling that properly may be more effort than it's worth.
}
开发者ID:booto,项目名称:dolphin,代码行数:43,代码来源:DVDThread.cpp
示例2: StartDVDThread
namespace DVDThread
{
struct ReadRequest
{
bool copy_to_ram;
u32 output_address;
u64 dvd_offset;
u32 length;
DiscIO::Partition partition;
// This determines which code DVDInterface will run to reply
// to the emulated software. We can't use callbacks,
// because function pointers can't be stored in savestates.
DVDInterface::ReplyType reply_type;
// IDs are used to uniquely identify a request. They must not be
// identical to IDs of any other requests that currently exist, but
// it's fine to re-use IDs of requests that have existed in the past.
u64 id;
// Only used for logging
u64 time_started_ticks;
u64 realtime_started_us;
u64 realtime_done_us;
};
using ReadResult = std::pair<ReadRequest, std::vector<u8>>;
static void StartDVDThread();
static void StopDVDThread();
static void DVDThread();
static void WaitUntilIdle();
static void StartReadInternal(bool copy_to_ram, u32 output_address, u64 dvd_offset, u32 length,
const DiscIO::Partition& partition,
DVDInterface::ReplyType reply_type, s64 ticks_until_completion);
static void FinishRead(u64 id, s64 cycles_late);
static CoreTiming::EventType* s_finish_read;
static u64 s_next_id = 0;
static std::thread s_dvd_thread;
static Common::Event s_request_queue_expanded; // Is set by CPU thread
static Common::Event s_result_queue_expanded; // Is set by DVD thread
static Common::Flag s_dvd_thread_exiting(false); // Is set by CPU thread
static Common::SPSCQueue<ReadRequest, false> s_request_queue;
static Common::SPSCQueue<ReadResult, false> s_result_queue;
static std::map<u64, ReadResult> s_result_map;
static std::unique_ptr<DiscIO::Volume> s_disc;
void Start()
{
s_finish_read = CoreTiming::RegisterEvent("FinishReadDVDThread", FinishRead);
s_request_queue_expanded.Reset();
s_result_queue_expanded.Reset();
s_request_queue.Clear();
s_result_queue.Clear();
// This is reset on every launch for determinism, but it doesn't matter
// much, because this will never get exposed to the emulated game.
s_next_id = 0;
StartDVDThread();
}
static void StartDVDThread()
{
ASSERT(!s_dvd_thread.joinable());
s_dvd_thread_exiting.Clear();
s_dvd_thread = std::thread(DVDThread);
}
void Stop()
{
StopDVDThread();
s_disc.reset();
}
static void StopDVDThread()
{
ASSERT(s_dvd_thread.joinable());
// By setting s_DVD_thread_exiting, we ask the DVD thread to cleanly exit.
// In case the request queue is empty, we need to set s_request_queue_expanded
// so that the DVD thread will wake up and check s_DVD_thread_exiting.
s_dvd_thread_exiting.Set();
s_request_queue_expanded.Set();
s_dvd_thread.join();
}
void DoState(PointerWrap& p)
{
// By waiting for the DVD thread to be done working, we ensure
// that s_request_queue will be empty and that the DVD thread
//.........这里部分代码省略.........
开发者ID:booto,项目名称:dolphin,代码行数:101,代码来源:DVDThread.cpp
示例3: tie
namespace CoreTiming
{
struct EventType
{
TimedCallback callback;
const std::string* name;
};
struct Event
{
s64 time;
u64 fifo_order;
u64 userdata;
EventType* type;
};
// Sort by time, unless the times are the same, in which case sort by the order added to the queue
static bool operator>(const Event& left, const Event& right)
{
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order);
}
static bool operator<(const Event& left, const Event& right)
{
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order);
}
// unordered_map stores each element separately as a linked list node so pointers to elements
// remain stable regardless of rehashes/resizing.
static std::unordered_map<std::string, EventType> s_event_types;
// STATE_TO_SAVE
// The queue is a min-heap using std::make_heap/push_heap/pop_heap.
// We don't use std::priority_queue because we need to be able to serialize, unserialize and
// erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't accomodated
// by the standard adaptor class.
static std::vector<Event> s_event_queue;
static u64 s_event_fifo_id;
static std::mutex s_ts_write_lock;
static Common::SPSCQueue<Event, false> s_ts_queue;
static float s_last_OC_factor;
static constexpr int MAX_SLICE_LENGTH = 20000;
static s64 s_idled_cycles;
static u32 s_fake_dec_start_value;
static u64 s_fake_dec_start_ticks;
// Are we in a function that has been called from Advance()
static bool s_is_global_timer_sane;
Globals g;
static EventType* s_ev_lost = nullptr;
static void EmptyTimedCallback(u64 userdata, s64 cyclesLate)
{
}
// Changing the CPU speed in Dolphin isn't actually done by changing the physical clock rate,
// but by changing the amount of work done in a particular amount of time. This tends to be more
// compatible because it stops the games from actually knowing directly that the clock rate has
// changed, and ensures that anything based on waiting a specific number of cycles still works.
//
// Technically it might be more accurate to call this changing the IPC instead of the CPU speed,
// but the effect is largely the same.
static int DowncountToCycles(int downcount)
{
return static_cast<int>(downcount * g.last_OC_factor_inverted);
}
static int CyclesToDowncount(int cycles)
{
return static_cast<int>(cycles * s_last_OC_factor);
}
EventType* RegisterEvent(const std::string& name, TimedCallback callback)
{
// check for existing type with same name.
// we want event type names to remain unique so that we can use them for serialization.
ASSERT_MSG(POWERPC, s_event_types.find(name) == s_event_types.end(),
"CoreTiming Event \"%s\" is already registered. Events should only be registered "
"during Init to avoid breaking save states.",
name.c_str());
auto info = s_event_types.emplace(name, EventType{callback, nullptr});
EventType* event_type = &info.first->second;
event_type->name = &info.first->first;
return event_type;
}
void UnregisterAllEvents()
{
ASSERT_MSG(POWERPC, s_event_queue.empty(), "Cannot unregister events with events pending");
s_event_types.clear();
}
void Init()
{
s_last_OC_factor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
g.last_OC_factor_inverted = 1.0f / s_last_OC_factor;
//.........这里部分代码省略.........
开发者ID:AdmiralCurtiss,项目名称:dolphin,代码行数:101,代码来源:CoreTiming.cpp
示例4: DVDThread
static void DVDThread()
{
Common::SetCurrentThreadName("DVD thread");
while (true)
{
s_request_queue_expanded.Wait();
if (s_dvd_thread_exiting.IsSet())
return;
ReadRequest request;
while (s_request_queue.Pop(request))
{
FileMonitor::Log(*s_disc, request.partition, request.dvd_offset);
std::vector<u8> buffer(request.length);
if (!s_disc->Read(request.dvd_offset, request.length, buffer.data(), request.partition))
buffer.resize(0);
request.realtime_done_us = Common::Timer::GetTimeUs();
s_result_queue.Push(ReadResult(std::move(request), std::move(buffer)));
s_result_queue_expanded.Set();
if (s_dvd_thread_exiting.IsSet())
return;
}
}
}
开发者ID:booto,项目名称:dolphin,代码行数:30,代码来源:DVDThread.cpp
示例5: Start
void Start()
{
s_finish_read = CoreTiming::RegisterEvent("FinishReadDVDThread", FinishRead);
s_request_queue_expanded.Reset();
s_result_queue_expanded.Reset();
s_request_queue.Clear();
s_result_queue.Clear();
// This is reset on every launch for determinism, but it doesn't matter
// much, because this will never get exposed to the emulated game.
s_next_id = 0;
StartDVDThread();
}
开发者ID:booto,项目名称:dolphin,代码行数:15,代码来源:DVDThread.cpp
示例6: FinishRead
static void FinishRead(u64 id, s64 cycles_late)
{
// We can't simply pop s_result_queue and always get the ReadResult
// we want, because the DVD thread may add ReadResults to the queue
// in a different order than we want to get them. What we do instead
// is to pop the queue until we find the ReadResult we want (the one
// whose ID matches userdata), which means we may end up popping
// ReadResults that we don't want. We can't add those unwanted results
// back to the queue, because the queue can only have one writer.
// Instead, we add them to a map that only is used by the CPU thread.
// When this function is called again later, it will check the map for
// the wanted ReadResult before it starts searching through the queue.
ReadResult result;
auto it = s_result_map.find(id);
if (it != s_result_map.end())
{
result = std::move(it->second);
s_result_map.erase(it);
}
else
{
while (true)
{
while (!s_result_queue.Pop(result))
s_result_queue_expanded.Wait();
if (result.first.id == id)
break;
else
s_result_map.emplace(result.first.id, std::move(result));
}
}
// We have now obtained the right ReadResult.
const ReadRequest& request = result.first;
const std::vector<u8>& buffer = result.second;
DEBUG_LOG(DVDINTERFACE, "Disc has been read. Real time: %" PRIu64 " us. "
"Real time including delay: %" PRIu64 " us. "
"Emulated time including delay: %" PRIu64 " us.",
request.realtime_done_us - request.realtime_started_us,
Common::Timer::GetTimeUs() - request.realtime_started_us,
(CoreTiming::GetTicks() - request.time_started_ticks) /
(SystemTimers::GetTicksPerSecond() / 1000000));
if (buffer.size() != request.length)
{
PanicAlertT("The disc could not be read (at 0x%" PRIx64 " - 0x%" PRIx64 ").",
request.dvd_offset, request.dvd_offset + request.length);
}
else
{
if (request.copy_to_ram)
Memory::CopyToEmu(request.output_address, buffer.data(), request.length);
}
// Notify the emulated software that the command has been executed
DVDInterface::FinishExecutingCommand(request.reply_type, DVDInterface::INT_TCINT, cycles_late,
buffer);
}
开发者ID:marissa2249,项目名称:dolphin,代码行数:60,代码来源:DVDThread.cpp
示例7: StartReadInternal
static void StartReadInternal(bool copy_to_ram, u32 output_address, u64 dvd_offset, u32 length,
const DiscIO::Partition& partition,
DVDInterface::ReplyType reply_type, s64 ticks_until_completion)
{
ASSERT(Core::IsCPUThread());
ReadRequest request;
request.copy_to_ram = copy_to_ram;
request.output_address = output_address;
request.dvd_offset = dvd_offset;
request.length = length;
request.partition = partition;
request.reply_type = reply_type;
u64 id = s_next_id++;
request.id = id;
request.time_started_ticks = CoreTiming::GetTicks();
request.realtime_started_us = Common::Timer::GetTimeUs();
s_request_queue.Push(std::move(request));
s_request_queue_expanded.Set();
CoreTiming::ScheduleEvent(ticks_until_completion, s_finish_read, id);
}
开发者ID:booto,项目名称:dolphin,代码行数:26,代码来源:DVDThread.cpp
示例8: MoveEvents
void MoveEvents()
{
for (Event ev; s_ts_queue.Pop(ev);)
{
ev.fifo_order = s_event_fifo_id++;
s_event_queue.emplace_back(std::move(ev));
std::push_heap(s_event_queue.begin(), s_event_queue.end(), std::greater<Event>());
}
}
开发者ID:AdmiralCurtiss,项目名称:dolphin,代码行数:9,代码来源:CoreTiming.cpp
示例9: WaitUntilIdle
void WaitUntilIdle()
{
ASSERT(Core::IsCPUThread());
while (!s_request_queue.Empty())
s_result_queue_expanded.Wait();
StopDVDThread();
StartDVDThread();
}
开发者ID:booto,项目名称:dolphin,代码行数:10,代码来源:DVDThread.cpp
示例10: ScheduleEvent
void ScheduleEvent(s64 cycles_into_future, EventType* event_type, u64 userdata, FromThread from)
{
ASSERT_MSG(POWERPC, event_type, "Event type is nullptr, will crash now.");
bool from_cpu_thread;
if (from == FromThread::ANY)
{
from_cpu_thread = Core::IsCPUThread();
}
else
{
from_cpu_thread = from == FromThread::CPU;
ASSERT_MSG(POWERPC, from_cpu_thread == Core::IsCPUThread(),
"A \"%s\" event was scheduled from the wrong thread (%s)", event_type->name->c_str(),
from_cpu_thread ? "CPU" : "non-CPU");
}
if (from_cpu_thread)
{
s64 timeout = GetTicks() + cycles_into_future;
// If this event needs to be scheduled before the next advance(), force one early
if (!s_is_global_timer_sane)
ForceExceptionCheck(cycles_into_future);
s_event_queue.emplace_back(Event{timeout, s_event_fifo_id++, userdata, event_type});
std::push_heap(s_event_queue.begin(), s_event_queue.end(), std::greater<Event>());
}
else
{
if (Core::WantsDeterminism())
{
ERROR_LOG(POWERPC,
"Someone scheduled an off-thread \"%s\" event while netplay or "
"movie play/record was active. This is likely to cause a desync.",
event_type->name->c_str());
}
std::lock_guard<std::mutex> lk(s_ts_write_lock);
s_ts_queue.Push(Event{g.global_timer + cycles_into_future, 0, userdata, event_type});
}
}
开发者ID:AdmiralCurtiss,项目名称:dolphin,代码行数:42,代码来源:CoreTiming.cpp
注:本文中的common::SPSCQueue类示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论