mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-14 04:30:29 +01:00
replace bs_t with rx::EnumBitSet
This commit is contained in:
parent
3f14b99f24
commit
2965aaf3e3
|
|
@ -124,7 +124,7 @@ enum class lv2_mp_flag {
|
|||
strict_get_block_size,
|
||||
cache,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last = cache,
|
||||
};
|
||||
|
||||
enum class lv2_file_type {
|
||||
|
|
@ -140,7 +140,7 @@ struct lv2_fs_mount_point {
|
|||
const u32 sector_size = 512;
|
||||
const u64 sector_count = 256;
|
||||
const u32 block_size = 4096;
|
||||
const bs_t<lv2_mp_flag> flags{};
|
||||
const rx::EnumBitSet<lv2_mp_flag> flags{};
|
||||
lv2_fs_mount_point *const next = nullptr;
|
||||
|
||||
mutable shared_mutex mutex;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/bit_set.h"
|
||||
#include "util/mutex.h"
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// Error codes
|
||||
enum sys_net_error : s32 {
|
||||
SYS_NET_ENOENT = 2,
|
||||
|
|
@ -54,7 +46,7 @@ enum sys_net_error : s32 {
|
|||
};
|
||||
|
||||
static constexpr sys_net_error operator-(sys_net_error v) {
|
||||
return sys_net_error{-+v};
|
||||
return sys_net_error{-static_cast<s32>(v)};
|
||||
}
|
||||
|
||||
// Socket types (prefixed with SYS_NET_)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include "Emu/IdManager.h"
|
||||
#include "Emu/NP/ip_address.h"
|
||||
#include "cellos/sys_net.h"
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
#include "util/atomic_bit_set.h"
|
||||
#include "util/mutex.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
@ -32,7 +34,7 @@ public:
|
|||
write,
|
||||
error,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
union sockopt_data {
|
||||
|
|
@ -62,10 +64,10 @@ public:
|
|||
std::unique_lock<shared_mutex> lock();
|
||||
|
||||
void set_lv2_id(u32 id);
|
||||
bs_t<poll_t> get_events() const;
|
||||
void set_poll_event(bs_t<poll_t> event);
|
||||
void poll_queue(shared_ptr<ppu_thread> ppu, bs_t<poll_t> event,
|
||||
std::function<bool(bs_t<poll_t>)> poll_cb);
|
||||
rx::EnumBitSet<poll_t> get_events() const;
|
||||
void set_poll_event(rx::EnumBitSet<poll_t> event);
|
||||
void poll_queue(shared_ptr<ppu_thread> ppu, rx::EnumBitSet<poll_t> event,
|
||||
std::function<bool(rx::EnumBitSet<poll_t>)> poll_cb);
|
||||
u32 clear_queue(ppu_thread *);
|
||||
void handle_events(const pollfd &native_fd, bool unset_connecting = false);
|
||||
void queue_wake(ppu_thread *ppu);
|
||||
|
|
@ -110,7 +112,7 @@ public:
|
|||
virtual s32 shutdown(s32 how) = 0;
|
||||
|
||||
virtual s32 poll(sys_net_pollfd &sn_pfd, pollfd &native_pfd) = 0;
|
||||
virtual std::tuple<bool, bool, bool> select(bs_t<poll_t> selected,
|
||||
virtual std::tuple<bool, bool, bool> select(rx::EnumBitSet<poll_t> selected,
|
||||
pollfd &native_pfd) = 0;
|
||||
|
||||
error_code abort_socket(s32 flags);
|
||||
|
|
@ -137,8 +139,8 @@ protected:
|
|||
atomic_bs_t<poll_t> events{};
|
||||
|
||||
// Event processing workload (pair of thread id and the processing function)
|
||||
std::vector<
|
||||
std::pair<shared_ptr<ppu_thread>, std::function<bool(bs_t<poll_t>)>>>
|
||||
std::vector<std::pair<shared_ptr<ppu_thread>,
|
||||
std::function<bool(rx::EnumBitSet<poll_t>)>>>
|
||||
queue;
|
||||
|
||||
// Socket options value keepers
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public:
|
|||
bool is_lock = true) override;
|
||||
|
||||
s32 poll(sys_net_pollfd &sn_pfd, pollfd &native_pfd) override;
|
||||
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected,
|
||||
std::tuple<bool, bool, bool> select(rx::EnumBitSet<poll_t> selected,
|
||||
pollfd &native_pfd) override;
|
||||
|
||||
bool is_socket_connected();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "lv2_socket.h"
|
||||
#include <queue>
|
||||
|
||||
class lv2_socket_p2p : public lv2_socket {
|
||||
public:
|
||||
|
|
@ -38,7 +39,7 @@ public:
|
|||
s32 shutdown(s32 how) override;
|
||||
|
||||
s32 poll(sys_net_pollfd &sn_pfd, pollfd &native_pfd) override;
|
||||
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected,
|
||||
std::tuple<bool, bool, bool> select(rx::EnumBitSet<poll_t> selected,
|
||||
pollfd &native_pfd) override;
|
||||
|
||||
void handle_new_data(sys_net_sockaddr_in_p2p p2p_addr,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#ifdef _WIN32
|
||||
#include <WS2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
|
|
@ -101,7 +102,7 @@ public:
|
|||
s32 shutdown(s32 how) override;
|
||||
|
||||
s32 poll(sys_net_pollfd &sn_pfd, pollfd &native_pfd) override;
|
||||
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected,
|
||||
std::tuple<bool, bool, bool> select(rx::EnumBitSet<poll_t> selected,
|
||||
pollfd &native_pfd) override;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -40,6 +40,6 @@ public:
|
|||
s32 shutdown(s32 how) override;
|
||||
|
||||
s32 poll(sys_net_pollfd &sn_pfd, pollfd &native_pfd) override;
|
||||
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected,
|
||||
std::tuple<bool, bool, bool> select(rx::EnumBitSet<poll_t> selected,
|
||||
pollfd &native_pfd) override;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "sys_usbd.h"
|
||||
#include "sys_vm.h"
|
||||
|
||||
#include "util/atomic_bit_set.h"
|
||||
#include "util/init_mutex.hpp"
|
||||
#include "util/sysinfo.hpp"
|
||||
#include "util/tsc.hpp"
|
||||
|
|
@ -1762,17 +1763,18 @@ bool lv2_obj::sleep_unlocked(cpu_thread &thread, u64 timeout,
|
|||
return_val = false;
|
||||
}
|
||||
|
||||
const auto [_, ok] = ppu->state.fetch_op([&](bs_t<cpu_flag> &val) {
|
||||
if (!(val & cpu_flag::signal)) {
|
||||
val += cpu_flag::suspend;
|
||||
const auto [_, ok] =
|
||||
ppu->state.fetch_op([&](rx::EnumBitSet<cpu_flag> &val) {
|
||||
if (!(val & cpu_flag::signal)) {
|
||||
val += cpu_flag::suspend;
|
||||
|
||||
// Flag used for forced timeout notification
|
||||
ensure(!timeout || !(val & cpu_flag::notify));
|
||||
return true;
|
||||
}
|
||||
// Flag used for forced timeout notification
|
||||
ensure(!timeout || !(val & cpu_flag::notify));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!ok) {
|
||||
ppu_log.fatal("sleep() failed (signaled) (%s)", ppu->current_function);
|
||||
|
|
@ -2075,7 +2077,7 @@ void lv2_obj::schedule_all(u64 current_time) {
|
|||
ppu_log.trace("schedule(): %s", target->id);
|
||||
|
||||
// Remove yield if it was sleeping until now
|
||||
const bs_t<cpu_flag> remove_yield =
|
||||
const rx::EnumBitSet<cpu_flag> remove_yield =
|
||||
target->start_time == 0 ? +cpu_flag::suspend
|
||||
: (cpu_flag::yield + cpu_flag::preempt);
|
||||
|
||||
|
|
|
|||
|
|
@ -740,7 +740,7 @@ lv2_file::open_raw_result_t lv2_file::open_raw(const std::string &local_path,
|
|||
return {CELL_EISDIR};
|
||||
}
|
||||
|
||||
bs_t<fs::open_mode> open_mode{};
|
||||
rx::EnumBitSet<fs::open_mode> open_mode{};
|
||||
|
||||
switch (flags & CELL_FS_O_ACCMODE) {
|
||||
case CELL_FS_O_RDONLY:
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ error_code sys_net_bnet_accept(ppu_thread &ppu, s32 s,
|
|||
|
||||
sock.poll_queue(idm::get_unlocked<named_thread<ppu_thread>>(ppu.id),
|
||||
lv2_socket::poll_t::read,
|
||||
[&](bs_t<lv2_socket::poll_t> events) -> bool {
|
||||
[&](rx::EnumBitSet<lv2_socket::poll_t> events) -> bool {
|
||||
if (events & lv2_socket::poll_t::read) {
|
||||
auto [success, res, res_socket, res_addr] =
|
||||
sock.accept(false);
|
||||
|
|
@ -554,7 +554,7 @@ error_code sys_net_bnet_connect(ppu_thread &ppu, s32 s,
|
|||
|
||||
sock.poll_queue(idm::get_unlocked<named_thread<ppu_thread>>(ppu.id),
|
||||
lv2_socket::poll_t::write,
|
||||
[&](bs_t<lv2_socket::poll_t> events) -> bool {
|
||||
[&](rx::EnumBitSet<lv2_socket::poll_t> events) -> bool {
|
||||
if (events & lv2_socket::poll_t::write) {
|
||||
result = sock.connect_followup();
|
||||
|
||||
|
|
@ -819,7 +819,7 @@ error_code sys_net_bnet_recvfrom(ppu_thread &ppu, s32 s, vm::ptr<void> buf,
|
|||
sock.poll_queue(
|
||||
idm::get_unlocked<named_thread<ppu_thread>>(ppu.id),
|
||||
lv2_socket::poll_t::read,
|
||||
[&](bs_t<lv2_socket::poll_t> events) -> bool {
|
||||
[&](rx::EnumBitSet<lv2_socket::poll_t> events) -> bool {
|
||||
if (events & lv2_socket::poll_t::read) {
|
||||
const auto success = sock.recvfrom(flags, len, false);
|
||||
|
||||
|
|
@ -929,7 +929,7 @@ error_code sys_net_bnet_sendmsg(ppu_thread &ppu, s32 s,
|
|||
|
||||
sock.poll_queue(idm::get_unlocked<named_thread<ppu_thread>>(ppu.id),
|
||||
lv2_socket::poll_t::write,
|
||||
[&](bs_t<lv2_socket::poll_t> events) -> bool {
|
||||
[&](rx::EnumBitSet<lv2_socket::poll_t> events) -> bool {
|
||||
if (events & lv2_socket::poll_t::write) {
|
||||
const auto success =
|
||||
sock.sendmsg(flags, *netmsg, false);
|
||||
|
|
@ -1023,7 +1023,7 @@ error_code sys_net_bnet_sendto(ppu_thread &ppu, s32 s, vm::cptr<void> buf,
|
|||
// Enable write event
|
||||
sock.poll_queue(idm::get_unlocked<named_thread<ppu_thread>>(ppu.id),
|
||||
lv2_socket::poll_t::write,
|
||||
[&](bs_t<lv2_socket::poll_t> events) -> bool {
|
||||
[&](rx::EnumBitSet<lv2_socket::poll_t> events) -> bool {
|
||||
if (events & lv2_socket::poll_t::write) {
|
||||
auto success =
|
||||
sock.sendto(flags, buf_copy, sn_addr, false);
|
||||
|
|
@ -1336,7 +1336,7 @@ error_code sys_net_bnet_poll(ppu_thread &ppu, vm::ptr<sys_net_pollfd> fds,
|
|||
sock->set_connecting(connecting[i]);
|
||||
#endif
|
||||
|
||||
bs_t<lv2_socket::poll_t> selected = +lv2_socket::poll_t::error;
|
||||
rx::EnumBitSet<lv2_socket::poll_t> selected = +lv2_socket::poll_t::error;
|
||||
|
||||
if (fds_buf[i].events & SYS_NET_POLLIN)
|
||||
selected += lv2_socket::poll_t::read;
|
||||
|
|
@ -1348,7 +1348,7 @@ error_code sys_net_bnet_poll(ppu_thread &ppu, vm::ptr<sys_net_pollfd> fds,
|
|||
sock->poll_queue(idm::get_unlocked<named_thread<ppu_thread>>(ppu.id),
|
||||
selected,
|
||||
[sock, selected, &fds_buf, i, &signaled,
|
||||
&ppu](bs_t<lv2_socket::poll_t> events) {
|
||||
&ppu](rx::EnumBitSet<lv2_socket::poll_t> events) {
|
||||
if (events & selected) {
|
||||
if (events & selected & lv2_socket::poll_t::read)
|
||||
fds_buf[i].revents |= SYS_NET_POLLIN;
|
||||
|
|
@ -1457,7 +1457,7 @@ error_code sys_net_bnet_select(ppu_thread &ppu, s32 nfds,
|
|||
|
||||
for (s32 i = 0; i < nfds; i++) {
|
||||
_fds[i].fd = -1;
|
||||
bs_t<lv2_socket::poll_t> selected{};
|
||||
rx::EnumBitSet<lv2_socket::poll_t> selected{};
|
||||
|
||||
if (readfds && _readfds.bit(i))
|
||||
selected += lv2_socket::poll_t::read;
|
||||
|
|
@ -1529,7 +1529,7 @@ error_code sys_net_bnet_select(ppu_thread &ppu, s32 nfds,
|
|||
}
|
||||
|
||||
for (s32 i = 0; i < nfds; i++) {
|
||||
bs_t<lv2_socket::poll_t> selected{};
|
||||
rx::EnumBitSet<lv2_socket::poll_t> selected{};
|
||||
|
||||
if (readfds && _readfds.bit(i))
|
||||
selected += lv2_socket::poll_t::read;
|
||||
|
|
@ -1554,7 +1554,7 @@ error_code sys_net_bnet_select(ppu_thread &ppu, s32 nfds,
|
|||
sock->poll_queue(
|
||||
idm::get_unlocked<named_thread<ppu_thread>>(ppu.id), selected,
|
||||
[sock, selected, i, &rread, &rwrite, &rexcept, &signaled,
|
||||
&ppu](bs_t<lv2_socket::poll_t> events) {
|
||||
&ppu](rx::EnumBitSet<lv2_socket::poll_t> events) {
|
||||
if (events & selected) {
|
||||
if (selected & lv2_socket::poll_t::read &&
|
||||
events &
|
||||
|
|
|
|||
|
|
@ -32,17 +32,17 @@ void lv2_socket::set_connecting(bool connecting) {
|
|||
|
||||
void lv2_socket::set_lv2_id(u32 id) { lv2_id = id; }
|
||||
|
||||
bs_t<lv2_socket::poll_t> lv2_socket::get_events() const {
|
||||
rx::EnumBitSet<lv2_socket::poll_t> lv2_socket::get_events() const {
|
||||
return events.load();
|
||||
}
|
||||
|
||||
void lv2_socket::set_poll_event(bs_t<lv2_socket::poll_t> event) {
|
||||
void lv2_socket::set_poll_event(rx::EnumBitSet<lv2_socket::poll_t> event) {
|
||||
events += event;
|
||||
}
|
||||
|
||||
void lv2_socket::poll_queue(
|
||||
shared_ptr<ppu_thread> ppu, bs_t<lv2_socket::poll_t> event,
|
||||
std::function<bool(bs_t<lv2_socket::poll_t>)> poll_cb) {
|
||||
shared_ptr<ppu_thread> ppu, rx::EnumBitSet<lv2_socket::poll_t> event,
|
||||
std::function<bool(rx::EnumBitSet<lv2_socket::poll_t>)> poll_cb) {
|
||||
set_poll_event(event);
|
||||
queue.emplace_back(std::move(ppu), poll_cb);
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ u32 lv2_socket::clear_queue(ppu_thread *ppu) {
|
|||
|
||||
void lv2_socket::handle_events(const pollfd &native_pfd,
|
||||
[[maybe_unused]] bool unset_connecting) {
|
||||
bs_t<lv2_socket::poll_t> events_happening{};
|
||||
rx::EnumBitSet<lv2_socket::poll_t> events_happening{};
|
||||
|
||||
if (native_pfd.revents & (POLLIN | POLLHUP) &&
|
||||
events.test_and_reset(lv2_socket::poll_t::read))
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ std::optional<s32> lv2_socket_native::connect(const sys_net_sockaddr &addr) {
|
|||
#endif
|
||||
this->poll_queue(
|
||||
null_ptr, lv2_socket::poll_t::write,
|
||||
[this](bs_t<lv2_socket::poll_t> events) -> bool {
|
||||
[this](rx::EnumBitSet<lv2_socket::poll_t> events) -> bool {
|
||||
if (events & lv2_socket::poll_t::write) {
|
||||
int native_error;
|
||||
::socklen_t size = sizeof(native_error);
|
||||
|
|
@ -1101,7 +1101,7 @@ s32 lv2_socket_native::poll(sys_net_pollfd &sn_pfd, pollfd &native_pfd) {
|
|||
}
|
||||
|
||||
std::tuple<bool, bool, bool>
|
||||
lv2_socket_native::select(bs_t<lv2_socket::poll_t> selected,
|
||||
lv2_socket_native::select(rx::EnumBitSet<lv2_socket::poll_t> selected,
|
||||
pollfd &native_pfd) {
|
||||
native_pfd.fd = native_socket;
|
||||
if (selected & lv2_socket::poll_t::read) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "sys_net/lv2_socket_p2p.h"
|
||||
#include "sys_net/network_context.h"
|
||||
#include "sys_net/sys_net_helpers.h"
|
||||
#include <deque>
|
||||
|
||||
LOG_CHANNEL(sys_net);
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ void lv2_socket_p2p::handle_new_data(sys_net_sockaddr_in_p2p p2p_addr,
|
|||
|
||||
// Check if poll is happening
|
||||
if (events.test_and_reset(lv2_socket::poll_t::read)) {
|
||||
bs_t<lv2_socket::poll_t> read_event = lv2_socket::poll_t::read;
|
||||
rx::EnumBitSet<lv2_socket::poll_t> read_event = lv2_socket::poll_t::read;
|
||||
for (auto it = queue.begin(); it != queue.end();) {
|
||||
if (it->second(read_event)) {
|
||||
it = queue.erase(it);
|
||||
|
|
@ -378,7 +379,7 @@ s32 lv2_socket_p2p::poll(sys_net_pollfd &sn_pfd,
|
|||
}
|
||||
|
||||
std::tuple<bool, bool, bool>
|
||||
lv2_socket_p2p::select(bs_t<lv2_socket::poll_t> selected,
|
||||
lv2_socket_p2p::select(rx::EnumBitSet<lv2_socket::poll_t> selected,
|
||||
[[maybe_unused]] pollfd &native_pfd) {
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ bool lv2_socket_p2ps::handle_connected(p2ps_encapsulated_tcp *tcp_header,
|
|||
|
||||
// check if polling is happening
|
||||
if (data_available && events.test_and_reset(lv2_socket::poll_t::read)) {
|
||||
bs_t<lv2_socket::poll_t> read_event = lv2_socket::poll_t::read;
|
||||
rx::EnumBitSet<lv2_socket::poll_t> read_event = lv2_socket::poll_t::read;
|
||||
for (auto it = queue.begin(); it != queue.end();) {
|
||||
if (it->second(read_event)) {
|
||||
it = queue.erase(it);
|
||||
|
|
@ -479,7 +479,7 @@ bool lv2_socket_p2ps::handle_listening(p2ps_encapsulated_tcp *tcp_header,
|
|||
|
||||
backlog.push_back(new_sock_id);
|
||||
if (events.test_and_reset(lv2_socket::poll_t::read)) {
|
||||
bs_t<lv2_socket::poll_t> read_event = lv2_socket::poll_t::read;
|
||||
rx::EnumBitSet<lv2_socket::poll_t> read_event = lv2_socket::poll_t::read;
|
||||
for (auto it = queue.begin(); it != queue.end();) {
|
||||
if (it->second(read_event)) {
|
||||
it = queue.erase(it);
|
||||
|
|
@ -983,7 +983,7 @@ s32 lv2_socket_p2ps::poll(sys_net_pollfd &sn_pfd,
|
|||
}
|
||||
|
||||
std::tuple<bool, bool, bool>
|
||||
lv2_socket_p2ps::select(bs_t<lv2_socket::poll_t> selected,
|
||||
lv2_socket_p2ps::select(rx::EnumBitSet<lv2_socket::poll_t> selected,
|
||||
[[maybe_unused]] pollfd &native_pfd) {
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ s32 lv2_socket_raw::poll([[maybe_unused]] sys_net_pollfd &sn_pfd,
|
|||
}
|
||||
|
||||
std::tuple<bool, bool, bool>
|
||||
lv2_socket_raw::select([[maybe_unused]] bs_t<lv2_socket::poll_t> selected,
|
||||
lv2_socket_raw::select([[maybe_unused]] rx::EnumBitSet<lv2_socket::poll_t> selected,
|
||||
[[maybe_unused]] pollfd &native_pfd) {
|
||||
LOG_ONCE(raw_select, "lv2_socket_raw::select");
|
||||
return {};
|
||||
|
|
|
|||
|
|
@ -1295,7 +1295,7 @@ error_code sys_spu_thread_group_terminate(ppu_thread &ppu, u32 id, s32 value) {
|
|||
|
||||
for (auto &thread : group->threads) {
|
||||
if (thread) {
|
||||
thread->state.fetch_op([](bs_t<cpu_flag> &flags) {
|
||||
thread->state.fetch_op([](rx::EnumBitSet<cpu_flag> &flags) {
|
||||
if (flags & cpu_flag::stop) {
|
||||
// In case the thread raised the ret flag itself at some point do not
|
||||
// raise it again
|
||||
|
|
|
|||
|
|
@ -1612,7 +1612,7 @@ enum class strkey_flag : u32
|
|||
// set_other, // writing is allowed for other types of PARAM.SFO (not
|
||||
// possible)
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
struct string_key_info
|
||||
|
|
@ -1620,7 +1620,7 @@ struct string_key_info
|
|||
public:
|
||||
string_key_info() = default;
|
||||
string_key_info(std::string_view _name, u32 _max_size,
|
||||
bs_t<strkey_flag> _flags)
|
||||
rx::EnumBitSet<strkey_flag> _flags)
|
||||
: name(_name), max_size(_max_size), flags(_flags) {}
|
||||
|
||||
std::string_view name;
|
||||
|
|
@ -1653,7 +1653,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
bs_t<strkey_flag> flags{}; // allowed operations
|
||||
rx::EnumBitSet<strkey_flag> flags{}; // allowed operations
|
||||
};
|
||||
|
||||
static string_key_info get_param_string_key(s32 id)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
#include "sha256.h"
|
||||
#include "key_vault.h"
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include "util/StrFmt.h"
|
||||
#include "util/StrUtil.h"
|
||||
#include "util/File.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
|
|||
case cpu_flag::dbg_global_pause: return "G-PAUSE";
|
||||
case cpu_flag::dbg_pause: return "PAUSE";
|
||||
case cpu_flag::dbg_step: return "STEP";
|
||||
case cpu_flag::__bitset_enum_max: break;
|
||||
case cpu_flag::bitset_last: break;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
|
|
@ -72,7 +72,7 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
|
|||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<bs_t<cpu_flag>>::format(std::string& out, u64 arg)
|
||||
void fmt_class_string<rx::EnumBitSet<cpu_flag>>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_bitset(out, arg, "[", "|", "]", &fmt_class_string<cpu_flag>::format);
|
||||
}
|
||||
|
|
@ -799,7 +799,7 @@ cpu_thread::cpu_thread(u32 id)
|
|||
}
|
||||
}
|
||||
|
||||
void cpu_thread::cpu_wait(bs_t<cpu_flag> old)
|
||||
void cpu_thread::cpu_wait(rx::EnumBitSet<cpu_flag> old)
|
||||
{
|
||||
state.wait(old);
|
||||
}
|
||||
|
|
@ -816,8 +816,8 @@ bool cpu_thread::check_state() noexcept
|
|||
while (true)
|
||||
{
|
||||
// Process all flags in a single atomic op
|
||||
bs_t<cpu_flag> state1;
|
||||
auto state0 = state.fetch_op([&](bs_t<cpu_flag>& flags)
|
||||
rx::EnumBitSet<cpu_flag> state1;
|
||||
auto state0 = state.fetch_op([&](rx::EnumBitSet<cpu_flag>& flags)
|
||||
{
|
||||
bool store = false;
|
||||
|
||||
|
|
@ -1168,9 +1168,9 @@ cpu_thread& cpu_thread::operator=(thread_state)
|
|||
return *this;
|
||||
}
|
||||
|
||||
void cpu_thread::add_remove_flags(bs_t<cpu_flag> to_add, bs_t<cpu_flag> to_remove)
|
||||
void cpu_thread::add_remove_flags(rx::EnumBitSet<cpu_flag> to_add, rx::EnumBitSet<cpu_flag> to_remove)
|
||||
{
|
||||
bs_t<cpu_flag> result{};
|
||||
rx::EnumBitSet<cpu_flag> result{};
|
||||
|
||||
if (!to_remove)
|
||||
{
|
||||
|
|
@ -1183,7 +1183,7 @@ void cpu_thread::add_remove_flags(bs_t<cpu_flag> to_add, bs_t<cpu_flag> to_remov
|
|||
}
|
||||
else
|
||||
{
|
||||
result = state.atomic_op([&](bs_t<cpu_flag>& v)
|
||||
result = state.atomic_op([&](rx::EnumBitSet<cpu_flag>& v)
|
||||
{
|
||||
v += to_add;
|
||||
v -= to_remove;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/Thread.h"
|
||||
#include "util/bit_set.h"
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
#include "util/atomic_bit_set.h"
|
||||
|
||||
#include <vector>
|
||||
#include <any>
|
||||
|
|
@ -33,17 +34,17 @@ enum class cpu_flag : u32
|
|||
dbg_pause, // Thread paused
|
||||
dbg_step, // Thread forced to pause after one step (one instruction, etc)
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
// Test stopped state
|
||||
constexpr bool is_stopped(bs_t<cpu_flag> state)
|
||||
constexpr bool is_stopped(rx::EnumBitSet<cpu_flag> state)
|
||||
{
|
||||
return !!(state & (cpu_flag::stop + cpu_flag::exit + cpu_flag::again));
|
||||
}
|
||||
|
||||
// Test paused state
|
||||
constexpr bool is_paused(bs_t<cpu_flag> state)
|
||||
constexpr bool is_paused(rx::EnumBitSet<cpu_flag> state)
|
||||
{
|
||||
return !!(state & (cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause)) && !is_stopped(state);
|
||||
}
|
||||
|
|
@ -87,12 +88,12 @@ public:
|
|||
}
|
||||
|
||||
// Wrappers
|
||||
static constexpr bool is_stopped(bs_t<cpu_flag> s)
|
||||
static constexpr bool is_stopped(rx::EnumBitSet<cpu_flag> s)
|
||||
{
|
||||
return ::is_stopped(s);
|
||||
}
|
||||
|
||||
static constexpr bool is_paused(bs_t<cpu_flag> s)
|
||||
static constexpr bool is_paused(rx::EnumBitSet<cpu_flag> s)
|
||||
{
|
||||
return ::is_paused(s);
|
||||
}
|
||||
|
|
@ -155,7 +156,7 @@ public:
|
|||
cpu_thread& operator=(thread_state);
|
||||
|
||||
// Add/remove CPU state flags in an atomic operations, notifying if required
|
||||
void add_remove_flags(bs_t<cpu_flag> to_add, bs_t<cpu_flag> to_remove);
|
||||
void add_remove_flags(rx::EnumBitSet<cpu_flag> to_add, rx::EnumBitSet<cpu_flag> to_remove);
|
||||
|
||||
// Thread stats for external observation
|
||||
static atomic_t<u64> g_threads_created, g_threads_deleted, g_suspend_counter;
|
||||
|
|
@ -194,7 +195,7 @@ public:
|
|||
virtual void cpu_return() {}
|
||||
|
||||
// Callback for thread_ctrl::wait or RSX wait
|
||||
virtual void cpu_wait(bs_t<cpu_flag> old);
|
||||
virtual void cpu_wait(rx::EnumBitSet<cpu_flag> old);
|
||||
|
||||
// Callback for function abortion stats on Emu.Kill()
|
||||
virtual void cpu_on_stop() {}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ void fmt_class_string<ppu_attr>::format(std::string& out, u64 arg)
|
|||
case ppu_attr::no_return: return "no_return";
|
||||
case ppu_attr::no_size: return "no_size";
|
||||
case ppu_attr::has_mfvscr: return "has_mfvscr";
|
||||
case ppu_attr::__bitset_enum_max: break;
|
||||
case ppu_attr::bitset_last: break;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
|
|
@ -33,7 +33,7 @@ void fmt_class_string<ppu_attr>::format(std::string& out, u64 arg)
|
|||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<bs_t<ppu_attr>>::format(std::string& out, u64 arg)
|
||||
void fmt_class_string<rx::EnumBitSet<ppu_attr>>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_bitset(out, arg, "[", ",", "]", &fmt_class_string<ppu_attr>::format);
|
||||
}
|
||||
|
|
@ -857,7 +857,7 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
|
|||
// u32 stack_frame = 0;
|
||||
u32 single_target = 0;
|
||||
u32 trampoline = 0;
|
||||
bs_t<ppu_attr> attr{};
|
||||
rx::EnumBitSet<ppu_attr> attr{};
|
||||
|
||||
std::set<u32> callers{};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "util/asm.hpp"
|
||||
#include "util/to_endian.hpp"
|
||||
|
||||
#include "util/bit_set.h"
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
#include "PPUOpcodes.h"
|
||||
|
||||
// PPU Function Attributes
|
||||
|
|
@ -19,7 +19,7 @@ enum class ppu_attr : u8
|
|||
no_size,
|
||||
has_mfvscr,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
// PPU Function Information
|
||||
|
|
@ -131,7 +131,7 @@ struct ppu_module : public Type
|
|||
std::string name{}; // Filename
|
||||
std::string path{}; // Filepath
|
||||
s64 offset = 0; // Offset of file
|
||||
mutable bs_t<ppu_attr> attr{}; // Shared module attributes
|
||||
mutable rx::EnumBitSet<ppu_attr> attr{}; // Shared module attributes
|
||||
std::string cache{}; // Cache file path
|
||||
std::vector<ppu_reloc> relocs{}; // Relocations
|
||||
std::vector<ppu_segment> segs{}; // Segments
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ enum class ppu_exec_bit : u64
|
|||
set_call_history,
|
||||
use_feed_data,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
using enum ppu_exec_bit;
|
||||
|
|
@ -80,7 +80,7 @@ template <ppu_exec_bit... Flags0>
|
|||
struct ppu_exec_select
|
||||
{
|
||||
template <ppu_exec_bit Flag, ppu_exec_bit... Flags, typename F>
|
||||
static ppu_intrp_func_t select(bs_t<ppu_exec_bit> selected, F func)
|
||||
static ppu_intrp_func_t select(rx::EnumBitSet<ppu_exec_bit> selected, F func)
|
||||
{
|
||||
// Make sure there is no flag duplication, otherwise skip flag
|
||||
if constexpr (((Flags0 != Flag) && ...))
|
||||
|
|
@ -97,7 +97,7 @@ struct ppu_exec_select
|
|||
}
|
||||
|
||||
template <typename F>
|
||||
static ppu_intrp_func_t select(bs_t<ppu_exec_bit>, F func)
|
||||
static ppu_intrp_func_t select(rx::EnumBitSet<ppu_exec_bit>, F func)
|
||||
{
|
||||
// Instantiate interpreter function with required set of flags
|
||||
return func.template operator()<Flags0...>();
|
||||
|
|
@ -107,7 +107,7 @@ struct ppu_exec_select
|
|||
static auto select()
|
||||
{
|
||||
#ifndef __INTELLISENSE__
|
||||
return [](bs_t<ppu_exec_bit> selected, auto func)
|
||||
return [](rx::EnumBitSet<ppu_exec_bit> selected, auto func)
|
||||
{
|
||||
return ppu_exec_select::select<Flags1...>(selected, func);
|
||||
};
|
||||
|
|
@ -2350,7 +2350,7 @@ template <u32 Count>
|
|||
struct VSLDOI
|
||||
{
|
||||
template <ppu_exec_bit... Flags>
|
||||
static auto select(bs_t<ppu_exec_bit> selected, auto func)
|
||||
static auto select(rx::EnumBitSet<ppu_exec_bit> selected, auto func)
|
||||
{
|
||||
return ppu_exec_select<>::select<Flags...>(selected, func);
|
||||
}
|
||||
|
|
@ -3891,7 +3891,7 @@ template <u32 N>
|
|||
struct MFOCRF
|
||||
{
|
||||
template <ppu_exec_bit... Flags>
|
||||
static auto select(bs_t<ppu_exec_bit> selected, auto func)
|
||||
static auto select(rx::EnumBitSet<ppu_exec_bit> selected, auto func)
|
||||
{
|
||||
return ppu_exec_select<>::select<Flags...>(selected, func);
|
||||
}
|
||||
|
|
@ -7547,7 +7547,7 @@ struct ppu_interpreter_t
|
|||
ppu_interpreter_rt_base::ppu_interpreter_rt_base() noexcept
|
||||
{
|
||||
// Obtain required set of flags from settings
|
||||
bs_t<ppu_exec_bit> selected{};
|
||||
rx::EnumBitSet<ppu_exec_bit> selected{};
|
||||
if (g_cfg.core.ppu_set_sat_bit)
|
||||
selected += set_sat;
|
||||
if (g_cfg.core.ppu_use_nj_bit)
|
||||
|
|
|
|||
|
|
@ -3254,7 +3254,7 @@ bool ppu_load_rel_exec(const ppu_rel_object& elf)
|
|||
|
||||
std::stable_sort(shdrs.begin(), shdrs.end(), [](auto& a, auto& b) -> bool
|
||||
{
|
||||
const bs_t<sh_flag> flags_a_has = a->sh_flags() - b->sh_flags();
|
||||
const rx::EnumBitSet<sh_flag> flags_a_has = a->sh_flags() - b->sh_flags();
|
||||
return flags_a_has.all_of(sh_flag::shf_execinstr);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1261,7 +1261,7 @@ static void ppu_break(ppu_thread& ppu, ppu_opcode_t, be_t<u32>* this_op, ppu_int
|
|||
ppu.cia = old_cia;
|
||||
|
||||
// Pause
|
||||
ppu.state.atomic_op([&](bs_t<cpu_flag>& state)
|
||||
ppu.state.atomic_op([&](rx::EnumBitSet<cpu_flag>& state)
|
||||
{
|
||||
if (pause_all)
|
||||
state += cpu_flag::dbg_global_pause;
|
||||
|
|
@ -2423,7 +2423,7 @@ void ppu_thread::cpu_on_stop()
|
|||
}
|
||||
}
|
||||
|
||||
void ppu_thread::cpu_wait(bs_t<cpu_flag> old)
|
||||
void ppu_thread::cpu_wait(rx::EnumBitSet<cpu_flag> old)
|
||||
{
|
||||
// Meanwhile while waiting, notify SPU waiters
|
||||
if (u32 addr = res_notify)
|
||||
|
|
@ -2781,7 +2781,7 @@ ppu_thread::ppu_thread(utils::serial& ar)
|
|||
void ppu_thread::save(utils::serial& ar)
|
||||
{
|
||||
// For debugging purposes, load this as soon as this function enters
|
||||
const bs_t<cpu_flag> state_flags = state;
|
||||
const rx::EnumBitSet<cpu_flag> state_flags = state;
|
||||
|
||||
USING_SERIALIZATION_VERSION(ppu);
|
||||
|
||||
|
|
@ -5421,10 +5421,10 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||
accurate_nj_mode,
|
||||
contains_symbol_resolver,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
be_t<bs_t<ppu_settings>> settings{};
|
||||
be_t<rx::EnumBitSet<ppu_settings>> settings{};
|
||||
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
settings += ppu_settings::platform_bit;
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ public:
|
|||
virtual void cpu_task() override final;
|
||||
virtual void cpu_sleep() override;
|
||||
virtual void cpu_on_stop() override;
|
||||
virtual void cpu_wait(bs_t<cpu_flag> old) override;
|
||||
virtual void cpu_wait(rx::EnumBitSet<cpu_flag> old) override;
|
||||
virtual ~ppu_thread() override;
|
||||
|
||||
SAVESTATE_INIT_POS(3);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class PPUTranslator final : public cpu_translator
|
|||
u64 m_addr = 0;
|
||||
|
||||
// Function attributes
|
||||
bs_t<ppu_attr> m_attr{};
|
||||
rx::EnumBitSet<ppu_attr> m_attr{};
|
||||
|
||||
// Relocation info
|
||||
const ppu_segment* m_reloc = nullptr;
|
||||
|
|
|
|||
|
|
@ -2920,7 +2920,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
|||
}
|
||||
|
||||
// Weak constant propagation context (for guessing branch targets)
|
||||
std::array<bs_t<vf>, 128> vflags{};
|
||||
std::array<rx::EnumBitSet<vf>, 128> vflags{};
|
||||
|
||||
// Associated constant values for 32-bit preferred slot
|
||||
std::array<u32, 128> values;
|
||||
|
|
@ -5596,7 +5596,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
|||
pos = ra.origin;
|
||||
}
|
||||
|
||||
const bs_t<vf> flag = (ra.flag & rb.flag) - vf::is_null;
|
||||
const rx::EnumBitSet<vf> flag = (ra.flag & rb.flag) - vf::is_null;
|
||||
|
||||
vregs[reg] = reg_state_t{flag, value, flag & vf::is_const ? u32{umax} : reg_state_t::alloc_tag(), 0, 0, pos};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ enum class spu_exec_bit : u64
|
|||
{
|
||||
use_dfma,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
using enum spu_exec_bit;
|
||||
|
|
@ -43,7 +43,7 @@ template <spu_exec_bit... Flags0>
|
|||
struct spu_exec_select
|
||||
{
|
||||
template <spu_exec_bit Flag, spu_exec_bit... Flags, typename F>
|
||||
static spu_intrp_func_t select(bs_t<spu_exec_bit> selected, F func)
|
||||
static spu_intrp_func_t select(rx::EnumBitSet<spu_exec_bit> selected, F func)
|
||||
{
|
||||
// Make sure there is no flag duplication, otherwise skip flag
|
||||
if constexpr (((Flags0 != Flag) && ...))
|
||||
|
|
@ -60,7 +60,7 @@ struct spu_exec_select
|
|||
}
|
||||
|
||||
template <typename F>
|
||||
static spu_intrp_func_t select(bs_t<spu_exec_bit>, F func)
|
||||
static spu_intrp_func_t select(rx::EnumBitSet<spu_exec_bit>, F func)
|
||||
{
|
||||
// Instantiate interpreter function with required set of flags
|
||||
return func.template operator()<Flags0...>();
|
||||
|
|
@ -3131,7 +3131,7 @@ struct spu_interpreter_t
|
|||
spu_interpreter_rt_base::spu_interpreter_rt_base() noexcept
|
||||
{
|
||||
// Obtain required set of flags from settings
|
||||
bs_t<spu_exec_bit> selected{};
|
||||
rx::EnumBitSet<spu_exec_bit> selected{};
|
||||
if (g_cfg.core.use_accurate_dfma)
|
||||
selected += use_dfma;
|
||||
|
||||
|
|
|
|||
|
|
@ -198,12 +198,12 @@ public:
|
|||
is_rel,
|
||||
is_null,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
struct reg_state_t
|
||||
{
|
||||
bs_t<vf> flag{+vf::is_null};
|
||||
rx::EnumBitSet<vf> flag{+vf::is_null};
|
||||
u32 value{};
|
||||
u32 tag = umax;
|
||||
u32 known_ones{};
|
||||
|
|
|
|||
|
|
@ -2027,7 +2027,7 @@ void spu_thread::cpu_work()
|
|||
if (!work_left)
|
||||
{
|
||||
// No more pending work
|
||||
state.atomic_op([](bs_t<cpu_flag>& flags)
|
||||
state.atomic_op([](rx::EnumBitSet<cpu_flag>& flags)
|
||||
{
|
||||
if (flags & cpu_flag::pending_recheck)
|
||||
{
|
||||
|
|
@ -7010,7 +7010,7 @@ bool spu_thread::stop_and_signal(u32 code)
|
|||
{
|
||||
if (thread)
|
||||
{
|
||||
thread->state.fetch_op([](bs_t<cpu_flag>& flags)
|
||||
thread->state.fetch_op([](rx::EnumBitSet<cpu_flag>& flags)
|
||||
{
|
||||
if (flags & cpu_flag::stop)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "GDB.h"
|
||||
#include "util/bit_set.h"
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
#include "util/logs.hpp"
|
||||
#include "util/StrUtil.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
|
|
@ -823,7 +823,7 @@ bool gdb_thread::cmd_vcont(gdb_cmd& cmd)
|
|||
|
||||
if (ppu)
|
||||
{
|
||||
bs_t<cpu_flag> add_flags{};
|
||||
rx::EnumBitSet<cpu_flag> add_flags{};
|
||||
|
||||
if (cmd.data[1] == 's')
|
||||
{
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ namespace vm
|
|||
|
||||
bool temporary_unlock(cpu_thread& cpu) noexcept
|
||||
{
|
||||
bs_t<cpu_flag> add_state = cpu_flag::wait;
|
||||
rx::EnumBitSet<cpu_flag> add_state = cpu_flag::wait;
|
||||
|
||||
if (g_tls_locked && g_tls_locked->compare_and_swap_test(&cpu, nullptr))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -850,7 +850,7 @@ namespace rsx
|
|||
on_exit();
|
||||
}
|
||||
|
||||
void thread::cpu_wait(bs_t<cpu_flag> old)
|
||||
void thread::cpu_wait(rx::EnumBitSet<cpu_flag> old)
|
||||
{
|
||||
if (external_interrupt_lock)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ namespace rsx
|
|||
u32 get_fifo_cmd() const;
|
||||
|
||||
void dump_regs(std::string&, std::any& custom_data) const override;
|
||||
void cpu_wait(bs_t<cpu_flag> old) override;
|
||||
void cpu_wait(rx::EnumBitSet<cpu_flag> old) override;
|
||||
|
||||
static constexpr u32 id_base = 0x5555'5555; // See get_current_cpu_thread()
|
||||
|
||||
|
|
|
|||
|
|
@ -2654,7 +2654,7 @@ void Emulator::FinalizeRunRequest()
|
|||
{
|
||||
const bool autostart = !m_ar || !!g_cfg.misc.autostart;
|
||||
|
||||
bs_t<cpu_flag> add_flags = cpu_flag::dbg_global_pause;
|
||||
rx::EnumBitSet<cpu_flag> add_flags = cpu_flag::dbg_global_pause;
|
||||
|
||||
if (autostart)
|
||||
{
|
||||
|
|
@ -2663,7 +2663,7 @@ void Emulator::FinalizeRunRequest()
|
|||
|
||||
auto spu_select = [&](u32, spu_thread& spu)
|
||||
{
|
||||
bs_t<cpu_flag> sub_flags = cpu_flag::stop;
|
||||
rx::EnumBitSet<cpu_flag> sub_flags = cpu_flag::stop;
|
||||
|
||||
if (spu.group && spu.index == spu.group->waiter_spu_index)
|
||||
{
|
||||
|
|
@ -3605,7 +3605,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
|||
|
||||
set_progress_message("Finalizing File");
|
||||
|
||||
bs_t<SaveStateExtentionFlags1> extension_flags{SaveStateExtentionFlags1::SupportsMenuOpenResume};
|
||||
rx::EnumBitSet<SaveStateExtentionFlags1> extension_flags{SaveStateExtentionFlags1::SupportsMenuOpenResume};
|
||||
|
||||
if (g_fxo->get<SysutilMenuOpenStatus>().active)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "util/shared_ptr.hpp"
|
||||
#include "util/bit_set.h"
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
#include "config_mode.h"
|
||||
#include "games_config.h"
|
||||
#include <functional>
|
||||
|
|
@ -188,10 +188,10 @@ class Emulator final
|
|||
SupportsMenuOpenResume,
|
||||
ShouldCloseMenu,
|
||||
|
||||
__bitset_enum_max,
|
||||
bitset_last,
|
||||
};
|
||||
|
||||
bs_t<SaveStateExtentionFlags1> m_savestate_extension_flags1{};
|
||||
rx::EnumBitSet<SaveStateExtentionFlags1> m_savestate_extension_flags1{};
|
||||
|
||||
public:
|
||||
static constexpr std::string_view game_id_boot_prefix = "%RPCS3_GAMEID%:";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "util/types.hpp"
|
||||
#include "util/File.h"
|
||||
#include "util/bit_set.h"
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
#include "util/endian.hpp"
|
||||
|
||||
#include <span>
|
||||
|
|
@ -56,10 +56,10 @@ enum class sh_flag : u32
|
|||
shf_alloc,
|
||||
shf_execinstr,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
constexpr bool is_memorizable_section(sec_type type, bs_t<sh_flag> flags)
|
||||
constexpr bool is_memorizable_section(sec_type type, rx::EnumBitSet<sh_flag> flags)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
|
@ -184,9 +184,9 @@ struct elf_shdr
|
|||
en_t<sz_t> sh_addralign;
|
||||
en_t<sz_t> sh_entsize;
|
||||
|
||||
bs_t<sh_flag> sh_flags() const
|
||||
rx::EnumBitSet<sh_flag> sh_flags() const
|
||||
{
|
||||
return std::bit_cast<bs_t<sh_flag>>(static_cast<u32>(+_sh_flags));
|
||||
return std::bit_cast<rx::EnumBitSet<sh_flag>>(static_cast<u32>(+_sh_flags));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ enum class elf_opt : u32
|
|||
no_sections, // Don't load shdrs
|
||||
no_data, // Load phdrs without data
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
// ELF loading error
|
||||
|
|
@ -266,12 +266,12 @@ public:
|
|||
public:
|
||||
elf_object() = default;
|
||||
|
||||
elf_object(const fs::file& stream, u64 offset = 0, bs_t<elf_opt> opts = {})
|
||||
elf_object(const fs::file& stream, u64 offset = 0, rx::EnumBitSet<elf_opt> opts = {})
|
||||
{
|
||||
open(stream, offset, opts);
|
||||
}
|
||||
|
||||
elf_error open(const fs::file& stream, u64 offset = 0, bs_t<elf_opt> opts = {})
|
||||
elf_error open(const fs::file& stream, u64 offset = 0, rx::EnumBitSet<elf_opt> opts = {})
|
||||
{
|
||||
highest_offset = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ bool iso_dev::statfs(const std::string& path, fs::device_stat& info)
|
|||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<fs::file_base> iso_dev::open(const std::string& path, bs_t<fs::open_mode> mode)
|
||||
std::unique_ptr<fs::file_base> iso_dev::open(const std::string& path, rx::EnumBitSet<fs::open_mode> mode)
|
||||
{
|
||||
if (mode & fs::write)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ public:
|
|||
|
||||
bool stat(const std::string& path, fs::stat_t& info) override;
|
||||
bool statfs(const std::string& path, fs::device_stat& info) override;
|
||||
std::unique_ptr<fs::file_base> open(const std::string& path, bs_t<fs::open_mode> mode) override;
|
||||
std::unique_ptr<fs::file_base> open(const std::string& path, rx::EnumBitSet<fs::open_mode> mode) override;
|
||||
std::unique_ptr<fs::dir_base> open_dir(const std::string& path) override;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1635,7 +1635,7 @@ void fs::sync()
|
|||
fmt::throw_exception("Stream overflow.");
|
||||
}
|
||||
|
||||
fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
fs::file::file(const std::string& path, rx::EnumBitSet<open_mode> mode)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "util/serialization.hpp"
|
||||
#include "util/types.hpp"
|
||||
#include "util/shared_ptr.hpp"
|
||||
#include "bit_set.h"
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
|
@ -35,7 +35,7 @@ namespace fs
|
|||
unread,
|
||||
isfile,
|
||||
|
||||
__bitset_enum_max
|
||||
bitset_last
|
||||
};
|
||||
|
||||
constexpr auto read = +open_mode::read; // Enable reading
|
||||
|
|
@ -174,7 +174,7 @@ namespace fs
|
|||
virtual bool trunc(const std::string& path, u64 length);
|
||||
virtual bool utime(const std::string& path, s64 atime, s64 mtime);
|
||||
|
||||
virtual std::unique_ptr<file_base> open(const std::string& path, bs_t<open_mode> mode) = 0;
|
||||
virtual std::unique_ptr<file_base> open(const std::string& path, rx::EnumBitSet<open_mode> mode) = 0;
|
||||
virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0;
|
||||
};
|
||||
|
||||
|
|
@ -258,7 +258,7 @@ namespace fs
|
|||
file() = default;
|
||||
|
||||
// Open file with specified mode
|
||||
explicit file(const std::string& path, bs_t<open_mode> mode = ::fs::read);
|
||||
explicit file(const std::string& path, rx::EnumBitSet<open_mode> mode = ::fs::read);
|
||||
|
||||
static file from_native_handle(native_handle handle);
|
||||
|
||||
|
|
@ -903,7 +903,7 @@ namespace fs
|
|||
}
|
||||
|
||||
template <bool Flush = false, typename... Args>
|
||||
bool write_file(const std::string& path, bs_t<fs::open_mode> mode, const Args&... args)
|
||||
bool write_file(const std::string& path, rx::EnumBitSet<fs::open_mode> mode, const Args&... args)
|
||||
{
|
||||
// Always use write flag, remove read flag
|
||||
if (fs::file f{path, mode + fs::write - fs::read})
|
||||
|
|
|
|||
175
rpcs3/util/atomic_bit_set.h
Normal file
175
rpcs3/util/atomic_bit_set.h
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
This header implements bs_t<> class for scoped enum types (enum class).
|
||||
To enable bs_t<>, enum scope must contain `bitset_last` entry.
|
||||
|
||||
enum class flagzz : u32
|
||||
{
|
||||
flag1, // Bit indices start from zero
|
||||
flag2,
|
||||
|
||||
bitset_last // It must be the last value
|
||||
};
|
||||
|
||||
This also enables helper operators for this enum type.
|
||||
|
||||
Examples:
|
||||
`+flagzz::flag1` - unary `+` operator convert flagzz value to bs_t<flagzz>
|
||||
`flagzz::flag1 + flagzz::flag2` - bitset union
|
||||
`flagzz::flag1 - flagzz::flag2` - bitset difference
|
||||
Intersection (&) and symmetric difference (^) is also available.
|
||||
*/
|
||||
|
||||
#include "rx/EnumBitSet.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "util/StrFmt.h"
|
||||
|
||||
template <typename T>
|
||||
concept BitSetEnum = std::is_enum_v<T> && requires(T x) {
|
||||
T::bitset_last;
|
||||
};
|
||||
|
||||
// Atomic bitset specialization with optimized operations
|
||||
template <BitSetEnum T>
|
||||
class atomic_bs_t : public atomic_t<rx::EnumBitSet<T>>
|
||||
{
|
||||
// Corresponding bitset type
|
||||
using bs_t = rx::EnumBitSet<T>;
|
||||
|
||||
// Base class
|
||||
using base = atomic_t<rx::EnumBitSet<T>>;
|
||||
|
||||
// Use underlying m_data
|
||||
using base::m_data;
|
||||
|
||||
public:
|
||||
// Underlying type
|
||||
using underlying_type = typename bs_t::underlying_type;
|
||||
|
||||
atomic_bs_t() = default;
|
||||
|
||||
atomic_bs_t(const atomic_bs_t&) = delete;
|
||||
|
||||
atomic_bs_t& operator=(const atomic_bs_t&) = delete;
|
||||
|
||||
explicit constexpr atomic_bs_t(bs_t value)
|
||||
: base(value)
|
||||
{
|
||||
}
|
||||
|
||||
explicit constexpr atomic_bs_t(T bit)
|
||||
: base(bit)
|
||||
{
|
||||
}
|
||||
|
||||
using base::operator bs_t;
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(base::load());
|
||||
}
|
||||
|
||||
explicit operator underlying_type() const
|
||||
{
|
||||
return static_cast<underlying_type>(base::load());
|
||||
}
|
||||
|
||||
bs_t operator+() const
|
||||
{
|
||||
return base::load();
|
||||
}
|
||||
|
||||
bs_t fetch_add(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::fetch_or(m_data.raw(), rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t add_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::or_fetch(m_data.raw(), rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t operator+=(const bs_t& rhs)
|
||||
{
|
||||
return add_fetch(rhs);
|
||||
}
|
||||
|
||||
bs_t fetch_sub(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::fetch_and(m_data.raw(), ~rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t sub_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::and_fetch(m_data.raw(), ~rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t operator-=(const bs_t& rhs)
|
||||
{
|
||||
return sub_fetch(rhs);
|
||||
}
|
||||
|
||||
bs_t fetch_and(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::fetch_and(m_data.raw(), rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t and_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::and_fetch(m_data.raw(), rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t operator&=(const bs_t& rhs)
|
||||
{
|
||||
return and_fetch(rhs);
|
||||
}
|
||||
|
||||
bs_t fetch_xor(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::fetch_xor(m_data.raw(), rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t xor_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t::fromUnderlying(atomic_storage<underlying_type>::xor_fetch(m_data.raw(), rhs.toUnderlying()));
|
||||
}
|
||||
|
||||
bs_t operator^=(const bs_t& rhs)
|
||||
{
|
||||
return xor_fetch(rhs);
|
||||
}
|
||||
|
||||
auto fetch_or(const bs_t&) = delete;
|
||||
auto or_fetch(const bs_t&) = delete;
|
||||
auto operator|=(const bs_t&) = delete;
|
||||
|
||||
bool test_and_set(T rhs)
|
||||
{
|
||||
return atomic_storage<underlying_type>::bts(m_data.raw(), static_cast<uint>(static_cast<underlying_type>(rhs)));
|
||||
}
|
||||
|
||||
bool test_and_reset(T rhs)
|
||||
{
|
||||
return atomic_storage<underlying_type>::btr(m_data.raw(), static_cast<uint>(static_cast<underlying_type>(rhs)));
|
||||
}
|
||||
|
||||
bool test_and_invert(T rhs)
|
||||
{
|
||||
return atomic_storage<underlying_type>::btc(m_data.raw(), static_cast<uint>(static_cast<underlying_type>(rhs)));
|
||||
}
|
||||
|
||||
bool bit_test_set(uint bit) = delete;
|
||||
bool bit_test_reset(uint bit) = delete;
|
||||
bool bit_test_invert(uint bit) = delete;
|
||||
|
||||
bool all_of(bs_t arg) const
|
||||
{
|
||||
return base::load().all_of(arg);
|
||||
}
|
||||
|
||||
bool none_of(bs_t arg) const
|
||||
{
|
||||
return base::load().none_of(arg);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,404 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
This header implements bs_t<> class for scoped enum types (enum class).
|
||||
To enable bs_t<>, enum scope must contain `__bitset_enum_max` entry.
|
||||
|
||||
enum class flagzz : u32
|
||||
{
|
||||
flag1, // Bit indices start from zero
|
||||
flag2,
|
||||
|
||||
__bitset_enum_max // It must be the last value
|
||||
};
|
||||
|
||||
This also enables helper operators for this enum type.
|
||||
|
||||
Examples:
|
||||
`+flagzz::flag1` - unary `+` operator convert flagzz value to bs_t<flagzz>
|
||||
`flagzz::flag1 + flagzz::flag2` - bitset union
|
||||
`flagzz::flag1 - flagzz::flag2` - bitset difference
|
||||
Intersection (&) and symmetric difference (^) is also available.
|
||||
*/
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "util/StrFmt.h"
|
||||
|
||||
template <typename T>
|
||||
concept BitSetEnum = std::is_enum_v<T> && requires(T x) {
|
||||
T::__bitset_enum_max;
|
||||
};
|
||||
|
||||
template <BitSetEnum T>
|
||||
class atomic_bs_t;
|
||||
|
||||
// Bitset type for enum class with available bits [0, T::__bitset_enum_max)
|
||||
template <BitSetEnum T>
|
||||
class bs_t final
|
||||
{
|
||||
public:
|
||||
// Underlying type
|
||||
using under = std::underlying_type_t<T>;
|
||||
|
||||
ENABLE_BITWISE_SERIALIZATION;
|
||||
|
||||
private:
|
||||
// Underlying value
|
||||
under m_data;
|
||||
|
||||
friend class atomic_bs_t<T>;
|
||||
|
||||
// Value constructor
|
||||
constexpr explicit bs_t(int, under data) noexcept
|
||||
: m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr usz bitmax = sizeof(T) * 8;
|
||||
static constexpr usz bitsize = static_cast<under>(T::__bitset_enum_max);
|
||||
|
||||
static_assert(std::is_enum_v<T>, "bs_t<> error: invalid type (must be enum)");
|
||||
static_assert(bitsize <= bitmax, "bs_t<> error: invalid __bitset_enum_max");
|
||||
static_assert(bitsize != bitmax || std::is_unsigned_v<under>, "bs_t<> error: invalid __bitset_enum_max (sign bit)");
|
||||
|
||||
// Helper function
|
||||
static constexpr under shift(T value)
|
||||
{
|
||||
return static_cast<under>(1) << static_cast<under>(value);
|
||||
}
|
||||
|
||||
bs_t() = default;
|
||||
|
||||
// Construct from a single bit
|
||||
constexpr bs_t(T bit) noexcept
|
||||
: m_data(shift(bit))
|
||||
{
|
||||
}
|
||||
|
||||
// Test for empty bitset
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return m_data != 0;
|
||||
}
|
||||
|
||||
// Extract underlying data
|
||||
constexpr explicit operator under() const noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
// Copy
|
||||
constexpr bs_t operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bs_t& operator+=(bs_t rhs)
|
||||
{
|
||||
m_data |= static_cast<under>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bs_t& operator-=(bs_t rhs)
|
||||
{
|
||||
m_data &= ~static_cast<under>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bs_t& operator&=(bs_t rhs)
|
||||
{
|
||||
m_data &= static_cast<under>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bs_t& operator^=(bs_t rhs)
|
||||
{
|
||||
m_data ^= static_cast<under>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend constexpr bs_t operator+(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data | rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr bs_t operator-(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data & ~rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr bs_t operator&(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data & rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr bs_t operator^(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data ^ rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bool operator==(bs_t rhs) const noexcept
|
||||
{
|
||||
return m_data == rhs.m_data;
|
||||
}
|
||||
|
||||
constexpr bool test_and_set(T bit)
|
||||
{
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data |= shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool test_and_reset(T bit)
|
||||
{
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data &= ~shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool test_and_complement(T bit)
|
||||
{
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data ^= shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool all_of(bs_t arg) const
|
||||
{
|
||||
return (m_data & arg.m_data) == arg.m_data;
|
||||
}
|
||||
|
||||
constexpr bool none_of(bs_t arg) const
|
||||
{
|
||||
return (m_data & arg.m_data) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Unary '+' operator: promote plain enum value to bitset value
|
||||
template <BitSetEnum T>
|
||||
constexpr bs_t<T> operator+(T bit)
|
||||
{
|
||||
return bs_t<T>(bit);
|
||||
}
|
||||
|
||||
// Binary '+' operator: bitset union
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator+(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) + bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '+' operator: bitset union
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator+(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) + bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator-(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) - bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator-(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) - bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator&(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) & bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator&(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) & bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator^(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) ^ bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator^(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) ^ bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Atomic bitset specialization with optimized operations
|
||||
template <BitSetEnum T>
|
||||
class atomic_bs_t : public atomic_t<::bs_t<T>>
|
||||
{
|
||||
// Corresponding bitset type
|
||||
using bs_t = ::bs_t<T>;
|
||||
|
||||
// Base class
|
||||
using base = atomic_t<::bs_t<T>>;
|
||||
|
||||
// Use underlying m_data
|
||||
using base::m_data;
|
||||
|
||||
public:
|
||||
// Underlying type
|
||||
using under = typename bs_t::under;
|
||||
|
||||
atomic_bs_t() = default;
|
||||
|
||||
atomic_bs_t(const atomic_bs_t&) = delete;
|
||||
|
||||
atomic_bs_t& operator=(const atomic_bs_t&) = delete;
|
||||
|
||||
explicit constexpr atomic_bs_t(bs_t value)
|
||||
: base(value)
|
||||
{
|
||||
}
|
||||
|
||||
explicit constexpr atomic_bs_t(T bit)
|
||||
: base(bit)
|
||||
{
|
||||
}
|
||||
|
||||
using base::operator bs_t;
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(base::load());
|
||||
}
|
||||
|
||||
explicit operator under() const
|
||||
{
|
||||
return static_cast<under>(base::load());
|
||||
}
|
||||
|
||||
bs_t operator+() const
|
||||
{
|
||||
return base::load();
|
||||
}
|
||||
|
||||
bs_t fetch_add(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::fetch_or(m_data.m_data, rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t add_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::or_fetch(m_data.m_data, rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t operator+=(const bs_t& rhs)
|
||||
{
|
||||
return add_fetch(rhs);
|
||||
}
|
||||
|
||||
bs_t fetch_sub(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::fetch_and(m_data.m_data, ~rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t sub_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::and_fetch(m_data.m_data, ~rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t operator-=(const bs_t& rhs)
|
||||
{
|
||||
return sub_fetch(rhs);
|
||||
}
|
||||
|
||||
bs_t fetch_and(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::fetch_and(m_data.m_data, rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t and_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::and_fetch(m_data.m_data, rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t operator&=(const bs_t& rhs)
|
||||
{
|
||||
return and_fetch(rhs);
|
||||
}
|
||||
|
||||
bs_t fetch_xor(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::fetch_xor(m_data.m_data, rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t xor_fetch(const bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, atomic_storage<under>::xor_fetch(m_data.m_data, rhs.m_data));
|
||||
}
|
||||
|
||||
bs_t operator^=(const bs_t& rhs)
|
||||
{
|
||||
return xor_fetch(rhs);
|
||||
}
|
||||
|
||||
auto fetch_or(const bs_t&) = delete;
|
||||
auto or_fetch(const bs_t&) = delete;
|
||||
auto operator|=(const bs_t&) = delete;
|
||||
|
||||
bool test_and_set(T rhs)
|
||||
{
|
||||
return atomic_storage<under>::bts(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
|
||||
}
|
||||
|
||||
bool test_and_reset(T rhs)
|
||||
{
|
||||
return atomic_storage<under>::btr(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
|
||||
}
|
||||
|
||||
bool test_and_invert(T rhs)
|
||||
{
|
||||
return atomic_storage<under>::btc(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
|
||||
}
|
||||
|
||||
bool bit_test_set(uint bit) = delete;
|
||||
bool bit_test_reset(uint bit) = delete;
|
||||
bool bit_test_invert(uint bit) = delete;
|
||||
|
||||
bool all_of(bs_t arg) const
|
||||
{
|
||||
return base::load().all_of(arg);
|
||||
}
|
||||
|
||||
bool none_of(bs_t arg) const
|
||||
{
|
||||
return base::load().none_of(arg);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct fmt_unveil<bs_t<T>>
|
||||
{
|
||||
// Format as is
|
||||
using type = bs_t<T>;
|
||||
|
||||
static inline u64 get(const bs_t<T>& bitset)
|
||||
{
|
||||
return static_cast<std::underlying_type_t<T>>(bitset);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
This header implements bs_t<> class for scoped enum types (enum class).
|
||||
To enable bs_t<>, enum scope must contain `__bitset_enum_max` entry.
|
||||
|
||||
enum class flagzz : u32
|
||||
{
|
||||
flag1, // Bit indices start from zero
|
||||
flag2,
|
||||
};
|
||||
|
||||
This also enables helper operators for this enum type.
|
||||
|
||||
Examples:
|
||||
`flagzz::flag1 | flagzz::flag2` - bitset union
|
||||
`flagzz::flag1 & ~flagzz::flag2` - bitset difference
|
||||
Intersection (&) and symmetric difference (^) is also available.
|
||||
*/
|
||||
|
||||
#include "refl.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace rx {
|
||||
template <typename T>
|
||||
concept BitSetEnum =
|
||||
std::is_enum_v<T> && requires(T x) { rx::fieldCount<T> > 0; };
|
||||
|
||||
template <BitSetEnum T> class BitSet;
|
||||
|
||||
namespace detail {
|
||||
template <BitSetEnum T> class InvertedBitSet final {
|
||||
using underlying_type = std::underlying_type_t<T>;
|
||||
underlying_type m_data;
|
||||
constexpr InvertedBitSet(underlying_type data) : m_data(data) {}
|
||||
friend BitSet<T>;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
// Bitset type for enum class with available bits [0, fieldCount)
|
||||
template <BitSetEnum T> class BitSet final {
|
||||
public:
|
||||
// Underlying type
|
||||
using underlying_type = std::underlying_type_t<T>;
|
||||
|
||||
private:
|
||||
// Underlying value
|
||||
underlying_type m_data;
|
||||
|
||||
// Value constructor
|
||||
constexpr explicit BitSet(int, underlying_type data) noexcept
|
||||
: m_data(data) {}
|
||||
|
||||
public:
|
||||
static constexpr usz bitmax = sizeof(T) * 8;
|
||||
static constexpr usz bitsize =
|
||||
static_cast<underlying_type>(rx::fieldCount<T>);
|
||||
|
||||
static_assert(std::is_enum_v<T>,
|
||||
"BitSet<> error: invalid type (must be enum)");
|
||||
static_assert(bitsize <= bitmax,
|
||||
"BitSet<> error: failed to determine enum field count");
|
||||
static_assert(bitsize != bitmax || std::is_unsigned_v<underlying_type>,
|
||||
"BitSet<> error: invalid field count (sign bit)");
|
||||
|
||||
// Helper function
|
||||
static constexpr underlying_type shift(T value) {
|
||||
return static_cast<underlying_type>(1)
|
||||
<< static_cast<underlying_type>(value);
|
||||
}
|
||||
|
||||
BitSet() = default;
|
||||
|
||||
// Construct from a single bit
|
||||
constexpr BitSet(T bit) noexcept : m_data(shift(bit)) {}
|
||||
|
||||
// Test for empty bitset
|
||||
constexpr explicit operator bool() const noexcept { return m_data != 0; }
|
||||
|
||||
// Extract underlying data
|
||||
constexpr explicit operator underlying_type() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
constexpr detail::InvertedBitSet<T> operator~() const { return {m_data}; }
|
||||
|
||||
constexpr BitSet &operator+=(BitSet rhs) {
|
||||
m_data |= static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr BitSet &operator-=(BitSet rhs) {
|
||||
m_data &= ~static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr BitSet without(BitSet rhs) const {
|
||||
BitSet result = *this;
|
||||
result.m_data &= ~static_cast<underlying_type>(rhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr BitSet with(BitSet rhs) const {
|
||||
BitSet result = *this;
|
||||
result.m_data |= static_cast<underlying_type>(rhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr BitSet &operator&=(BitSet rhs) {
|
||||
m_data &= static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr BitSet &operator^=(BitSet rhs) {
|
||||
m_data ^= static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[deprecated("Use operator|")]] friend constexpr BitSet
|
||||
operator+(BitSet lhs, BitSet rhs) {
|
||||
return BitSet(0, lhs.m_data | rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr BitSet operator-(BitSet lhs, BitSet rhs) {
|
||||
return BitSet(0, lhs.m_data & ~rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr BitSet operator|(BitSet lhs, BitSet rhs) {
|
||||
return BitSet(0, lhs.m_data | rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr BitSet operator&(BitSet lhs, BitSet rhs) {
|
||||
return BitSet(0, lhs.m_data & rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr BitSet operator&(BitSet lhs, detail::InvertedBitSet<T> rhs) {
|
||||
return BitSet(0, lhs.m_data & rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr BitSet operator^(BitSet lhs, BitSet rhs) {
|
||||
return BitSet(0, lhs.m_data ^ rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bool operator==(BitSet rhs) const noexcept {
|
||||
return m_data == rhs.m_data;
|
||||
}
|
||||
|
||||
constexpr bool test_and_set(T bit) {
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data |= shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool test_and_reset(T bit) {
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data &= ~shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool test_and_complement(T bit) {
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data ^= shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool any_of(BitSet arg) const { return (m_data & arg.m_data) != 0; }
|
||||
|
||||
constexpr bool all_of(BitSet arg) const {
|
||||
return (m_data & arg.m_data) == arg.m_data;
|
||||
}
|
||||
|
||||
constexpr bool none_of(BitSet arg) const {
|
||||
return (m_data & arg.m_data) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
namespace bitset {
|
||||
// Unary '+' operator: promote plain enum value to bitset value
|
||||
template <BitSetEnum T>
|
||||
[[deprecated("Use toBitSet(bit)")]] constexpr BitSet<T> operator+(T bit) {
|
||||
return BitSet<T>(bit);
|
||||
}
|
||||
|
||||
template <BitSetEnum T> constexpr BitSet<T> toBitSet(T bit) {
|
||||
return BitSet<T>(bit);
|
||||
}
|
||||
|
||||
// Binary '+' operator: bitset union
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<BitSet<T>, U>)
|
||||
[[deprecated("Use operator|")]] constexpr BitSet<T> operator+(T lhs,
|
||||
const U &rhs) {
|
||||
return BitSet<T>(lhs) | BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '+' operator: bitset union
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<BitSet<T>, U> && !std::is_enum_v<U>)
|
||||
[[deprecated("Use operator|")]] constexpr BitSet<T> operator+(const U &lhs,
|
||||
T rhs) {
|
||||
return BitSet<T>(lhs) | BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '|' operator: bitset union
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<BitSet<T>, U>)
|
||||
constexpr BitSet<T> operator|(T lhs, const U &rhs) {
|
||||
return BitSet<T>(lhs) | BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '|' operator: bitset union
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<BitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr BitSet<T> operator|(const U &lhs, T rhs) {
|
||||
return BitSet<T>(lhs) | BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<BitSet<T>, U>)
|
||||
constexpr BitSet<T> operator-(T lhs, const U &rhs) {
|
||||
return BitSet<T>(lhs) - BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<BitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr BitSet<T> operator-(const U &lhs, T rhs) {
|
||||
return BitSet<T>(lhs) - BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<BitSet<T>, U>)
|
||||
constexpr BitSet<T> operator&(T lhs, const U &rhs) {
|
||||
return BitSet<T>(lhs) & BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<BitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr BitSet<T> operator&(const U &lhs, T rhs) {
|
||||
return BitSet<T>(lhs) & BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <BitSetEnum T, typename U>
|
||||
constexpr BitSet<T> operator&(T lhs, detail::InvertedBitSet<T> rhs) {
|
||||
return BitSet<T>(lhs) & rhs;
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<BitSet<T>, U>)
|
||||
constexpr BitSet<T> operator^(T lhs, const U &rhs) {
|
||||
return BitSet<T>(lhs) ^ BitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<BitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr BitSet<T> operator^(const U &lhs, T rhs) {
|
||||
return BitSet<T>(lhs) ^ BitSet<T>(rhs);
|
||||
}
|
||||
} // namespace bitset
|
||||
} // namespace rx
|
||||
|
||||
using namespace rx::bitset;
|
||||
287
rx/include/rx/EnumBitSet.hpp
Normal file
287
rx/include/rx/EnumBitSet.hpp
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
This header implements EnumBitSet<> class for scoped enum types (enum class).
|
||||
To enable EnumBitSet<>, enum scope must contain `bitset_last` entry.
|
||||
|
||||
enum class flagzz : u32
|
||||
{
|
||||
flag1, // Bit indices start from zero
|
||||
flag2,
|
||||
|
||||
bitset_last = flag2
|
||||
};
|
||||
|
||||
This also enables helper operators for this enum type.
|
||||
|
||||
Examples:
|
||||
`flagzz::flag1 | flagzz::flag2` - bitset union
|
||||
`flagzz::flag1 & ~flagzz::flag2` - bitset difference
|
||||
Intersection (&) and symmetric difference (^) is also available.
|
||||
*/
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
namespace rx {
|
||||
template <typename T>
|
||||
concept BitSetEnum = std::is_enum_v<T> && requires { T::bitset_last; };
|
||||
|
||||
template <BitSetEnum T> class EnumBitSet;
|
||||
|
||||
namespace detail {
|
||||
template <BitSetEnum T> class InvertedEnumBitSet final {
|
||||
using underlying_type = std::underlying_type_t<T>;
|
||||
underlying_type m_data;
|
||||
constexpr InvertedEnumBitSet(underlying_type data) : m_data(data) {}
|
||||
friend EnumBitSet<T>;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
// Bitset type for enum class with available bits [0, fieldCount)
|
||||
template <BitSetEnum T> class EnumBitSet final {
|
||||
public:
|
||||
// Underlying type
|
||||
using underlying_type = std::underlying_type_t<T>;
|
||||
|
||||
private:
|
||||
// Underlying value
|
||||
underlying_type m_data;
|
||||
|
||||
// Value constructor
|
||||
constexpr explicit EnumBitSet(int, underlying_type data) noexcept
|
||||
: m_data(data) {}
|
||||
|
||||
public:
|
||||
static constexpr usz bitmax = sizeof(T) * 8;
|
||||
static constexpr usz bitsize =
|
||||
static_cast<underlying_type>(T::bitset_last) + 1;
|
||||
|
||||
static_assert(std::is_enum_v<T>,
|
||||
"BitSet<> error: invalid type (must be enum)");
|
||||
static_assert(bitsize <= bitmax,
|
||||
"BitSet<> error: failed to determine enum field count");
|
||||
static_assert(bitsize != bitmax || std::is_unsigned_v<underlying_type>,
|
||||
"BitSet<> error: invalid field count (sign bit)");
|
||||
|
||||
// Helper function
|
||||
static constexpr underlying_type shift(T value) {
|
||||
return static_cast<underlying_type>(1)
|
||||
<< static_cast<underlying_type>(value);
|
||||
}
|
||||
|
||||
EnumBitSet() = default;
|
||||
|
||||
// Construct from a single bit
|
||||
constexpr EnumBitSet(T bit) noexcept : m_data(shift(bit)) {}
|
||||
|
||||
[[nodiscard]] constexpr underlying_type toUnderlying() const {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr EnumBitSet
|
||||
fromUnderlying(underlying_type raw) {
|
||||
return EnumBitSet(0, raw);
|
||||
}
|
||||
|
||||
// Test for empty bitset
|
||||
constexpr explicit operator bool() const noexcept { return m_data != 0; }
|
||||
|
||||
// Extract underlying data
|
||||
constexpr explicit operator underlying_type() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
constexpr detail::InvertedEnumBitSet<T> operator~() const { return {m_data}; }
|
||||
|
||||
[[deprecated("Use operator|=")]] constexpr EnumBitSet &
|
||||
operator+=(EnumBitSet rhs) {
|
||||
m_data |= static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr EnumBitSet &operator|=(EnumBitSet rhs) {
|
||||
m_data |= static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr EnumBitSet &operator-=(EnumBitSet rhs) {
|
||||
m_data &= ~static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr EnumBitSet without(EnumBitSet rhs) const {
|
||||
EnumBitSet result = *this;
|
||||
result.m_data &= ~static_cast<underlying_type>(rhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr EnumBitSet with(EnumBitSet rhs) const {
|
||||
EnumBitSet result = *this;
|
||||
result.m_data |= static_cast<underlying_type>(rhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr EnumBitSet &operator&=(EnumBitSet rhs) {
|
||||
m_data &= static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr EnumBitSet &operator^=(EnumBitSet rhs) {
|
||||
m_data ^= static_cast<underlying_type>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[deprecated("Use operator|")]] friend constexpr EnumBitSet
|
||||
operator+(EnumBitSet lhs, EnumBitSet rhs) {
|
||||
return EnumBitSet(0, lhs.m_data | rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr EnumBitSet operator-(EnumBitSet lhs, EnumBitSet rhs) {
|
||||
return EnumBitSet(0, lhs.m_data & ~rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr EnumBitSet operator|(EnumBitSet lhs, EnumBitSet rhs) {
|
||||
return EnumBitSet(0, lhs.m_data | rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr EnumBitSet operator&(EnumBitSet lhs, EnumBitSet rhs) {
|
||||
return EnumBitSet(0, lhs.m_data & rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr EnumBitSet operator&(EnumBitSet lhs,
|
||||
detail::InvertedEnumBitSet<T> rhs) {
|
||||
return EnumBitSet(0, lhs.m_data & rhs.m_data);
|
||||
}
|
||||
|
||||
friend constexpr EnumBitSet operator^(EnumBitSet lhs, EnumBitSet rhs) {
|
||||
return EnumBitSet(0, lhs.m_data ^ rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bool operator==(EnumBitSet rhs) const noexcept {
|
||||
return m_data == rhs.m_data;
|
||||
}
|
||||
|
||||
constexpr bool test_and_set(T bit) {
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data |= shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool test_and_reset(T bit) {
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data &= ~shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool test_and_complement(T bit) {
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
m_data ^= shift(bit);
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr bool any_of(EnumBitSet arg) const {
|
||||
return (m_data & arg.m_data) != 0;
|
||||
}
|
||||
|
||||
constexpr bool all_of(EnumBitSet arg) const {
|
||||
return (m_data & arg.m_data) == arg.m_data;
|
||||
}
|
||||
|
||||
constexpr bool none_of(EnumBitSet arg) const {
|
||||
return (m_data & arg.m_data) == 0;
|
||||
}
|
||||
|
||||
underlying_type &raw() { return m_data; }
|
||||
};
|
||||
|
||||
template <BitSetEnum T> constexpr EnumBitSet<T> toBitSet(T bit) {
|
||||
return EnumBitSet<T>(bit);
|
||||
}
|
||||
|
||||
namespace bitset {
|
||||
// Unary '+' operator: promote plain enum value to bitset value
|
||||
template <BitSetEnum T>
|
||||
[[deprecated("Use toBitSet(bit)")]] constexpr EnumBitSet<T> operator+(T bit) {
|
||||
return EnumBitSet<T>(bit);
|
||||
}
|
||||
// Binary '+' operator: bitset union
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U>)
|
||||
[[deprecated("Use operator|")]] constexpr EnumBitSet<T>
|
||||
operator+(T lhs, const U &rhs) {
|
||||
return EnumBitSet<T>(lhs) | EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '+' operator: bitset union
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U> && !std::is_enum_v<U>)
|
||||
[[deprecated("Use operator|")]] constexpr EnumBitSet<T> operator+(const U &lhs,
|
||||
T rhs) {
|
||||
return EnumBitSet<T>(lhs) | EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '|' operator: bitset union
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U>)
|
||||
constexpr EnumBitSet<T> operator|(T lhs, const U &rhs) {
|
||||
return EnumBitSet<T>(lhs) | EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '|' operator: bitset union
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr EnumBitSet<T> operator|(const U &lhs, T rhs) {
|
||||
return EnumBitSet<T>(lhs) | EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U>)
|
||||
constexpr EnumBitSet<T> operator-(T lhs, const U &rhs) {
|
||||
return EnumBitSet<T>(lhs) - EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr EnumBitSet<T> operator-(const U &lhs, T rhs) {
|
||||
return EnumBitSet<T>(lhs) - EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U>)
|
||||
constexpr EnumBitSet<T> operator&(T lhs, const U &rhs) {
|
||||
return EnumBitSet<T>(lhs) & EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr EnumBitSet<T> operator&(const U &lhs, T rhs) {
|
||||
return EnumBitSet<T>(lhs) & EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <BitSetEnum T, typename U>
|
||||
constexpr EnumBitSet<T> operator&(T lhs, detail::InvertedEnumBitSet<T> rhs) {
|
||||
return EnumBitSet<T>(lhs) & rhs;
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <BitSetEnum T, typename U>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U>)
|
||||
constexpr EnumBitSet<T> operator^(T lhs, const U &rhs) {
|
||||
return EnumBitSet<T>(lhs) ^ EnumBitSet<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <typename U, BitSetEnum T>
|
||||
requires(std::is_constructible_v<EnumBitSet<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr EnumBitSet<T> operator^(const U &lhs, T rhs) {
|
||||
return EnumBitSet<T>(lhs) ^ EnumBitSet<T>(rhs);
|
||||
}
|
||||
} // namespace bitset
|
||||
} // namespace rx
|
||||
|
||||
using namespace rx::bitset;
|
||||
Loading…
Reference in a new issue