[+] AuTime::Clock<T>::GetCurrentTimeNS();
[+] AuTime::Clock<T>::GetFrequency(); where T = [+] AuTime::ClockWall [+] AuTime::ClockSteady [+] AuTime::ClockProcessTime [+] AuTime::ClockProcessKernelTime [+] AuTime::ClockProcessUserTime [+] AuTime::ClockThreadTime [+] AuTime::ClockThreadKernelTime [+] AuTime::ClockThreadUserTime
This commit is contained in:
parent
a1b07c634a
commit
83fad7c538
@ -32,7 +32,7 @@ namespace Aurora::Time
|
||||
}
|
||||
|
||||
private:
|
||||
Stopwatch stopwatch_;
|
||||
Stopwatch<ClockSteady> stopwatch_;
|
||||
AuString message_;
|
||||
};
|
||||
|
||||
|
66
Include/Aurora/Time/StaticClocks.hpp
Normal file
66
Include/Aurora/Time/StaticClocks.hpp
Normal file
@ -0,0 +1,66 @@
|
||||
/***
|
||||
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: StaticClocks.hpp
|
||||
Date: 2023-tbd (<6)
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetWallClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetSteadyClock();
|
||||
|
||||
/**
|
||||
* @brief kernel + userland cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetProcessClock();
|
||||
|
||||
/**
|
||||
* @brief user time used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetProcessUserClock();
|
||||
|
||||
/**
|
||||
* @brief kernel (if known) cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetProcessKernelClock();
|
||||
|
||||
/**
|
||||
* @brief kernel + userland cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetThreadClock();
|
||||
|
||||
/**
|
||||
* @brief user time used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetThreadUserClock();
|
||||
|
||||
/**
|
||||
* @brief kernel (if known) cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetThreadKernelClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param clock
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetClockFromEnum(EClock clock);
|
||||
}
|
109
Include/Aurora/Time/StaticClocksClasses.hpp
Normal file
109
Include/Aurora/Time/StaticClocksClasses.hpp
Normal file
@ -0,0 +1,109 @@
|
||||
/***
|
||||
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: StaticClocksClasses.hpp
|
||||
Date: 2023-07-07
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
struct ClockBase
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
template <typename T = void>
|
||||
struct Clock
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
#define AURT_ADD_CLOCK_A(name, oldClockType) \
|
||||
struct Clock ## name : ClockBase \
|
||||
{ \
|
||||
static inline AuUInt64 GetCurrentTimeNS() \
|
||||
{ \
|
||||
return oldClockType ## ClockNS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetCurrentTimeMS() \
|
||||
{ \
|
||||
return oldClockType ## ClockMS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetFrequency() \
|
||||
{ \
|
||||
return oldClockType ## ClockJiffies(); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <> \
|
||||
struct Clock<Clock ## name> \
|
||||
{ \
|
||||
static inline AuUInt64 GetCurrentTimeNS() \
|
||||
{ \
|
||||
return Clock## name::GetCurrentTimeNS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetCurrentTimeMS() \
|
||||
{ \
|
||||
return Clock ## name::GetCurrentTimeMS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetFrequency() \
|
||||
{ \
|
||||
return Clock ## name::GetFrequency(); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define AURT_ADD_CLOCK_B(name, oldClockType) \
|
||||
struct Clock ## name : ClockBase \
|
||||
{ \
|
||||
static inline AuUInt64 GetCurrentTimeNS() \
|
||||
{ \
|
||||
return oldClockType ## ClockNS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetCurrentTimeMS() \
|
||||
{ \
|
||||
return oldClockType ## ClockMS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetFrequency() \
|
||||
{ \
|
||||
return 1000; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <> \
|
||||
struct Clock<Clock ## name> \
|
||||
{ \
|
||||
static inline AuUInt64 GetCurrentTimeNS() \
|
||||
{ \
|
||||
return Clock## name::GetCurrentTimeNS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetCurrentTimeMS() \
|
||||
{ \
|
||||
return Clock ## name::GetCurrentTimeMS(); \
|
||||
} \
|
||||
\
|
||||
static inline AuUInt64 GetFrequency() \
|
||||
{ \
|
||||
return Clock ## name::GetFrequency(); \
|
||||
} \
|
||||
};
|
||||
|
||||
AURT_ADD_CLOCK_B(Wall, Current);
|
||||
AURT_ADD_CLOCK_A(Steady, Steady);
|
||||
AURT_ADD_CLOCK_A(ProcessTime, Process);
|
||||
AURT_ADD_CLOCK_A(ProcessKernelTime, ProcessKernel);
|
||||
AURT_ADD_CLOCK_A(ProcessUserTime, ProcessUser);
|
||||
AURT_ADD_CLOCK_A(ThreadTime, Thread);
|
||||
AURT_ADD_CLOCK_A(ThreadKernelTime, ThreadKernel);
|
||||
AURT_ADD_CLOCK_A(ThreadUserTime, ThreadUser);
|
||||
|
||||
#undef AURT_ADD_CLOCK_A
|
||||
}
|
168
Include/Aurora/Time/StaticClocksDirect.hpp
Normal file
168
Include/Aurora/Time/StaticClocksDirect.hpp
Normal file
@ -0,0 +1,168 @@
|
||||
/***
|
||||
Copyright (C) 2021-2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: StaticClocksDirect.hpp
|
||||
Date: 2021-6-10
|
||||
Date: 2023-tbd (<6)
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
/**
|
||||
Retrieves wall clock in milliseconds from the Aurora epoch
|
||||
*/
|
||||
AUKN_SYM AuInt64 CurrentClockMS();
|
||||
|
||||
/**
|
||||
Retrieves wall clock in nanoseconds from the Aurora epoch
|
||||
*/
|
||||
AUKN_SYM AuInt64 CurrentClockNS();
|
||||
|
||||
/**
|
||||
* @brief Steady clock in jiffies
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClock();
|
||||
|
||||
/**
|
||||
Returns a steady system clock of SteadyClockJiffies() with an undefined epoch.
|
||||
|
||||
These values should be used to drive thread primitives, IO time, and tick delta.
|
||||
On a modern plaform, these should be affected by the users' calendar or NTP.
|
||||
On stinkier platforms, who cares if we can run mostly bug free with an assumed-sane wall-clock, right?
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClockMS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClockNS();
|
||||
|
||||
/**
|
||||
Retrieves the freqency of jiffies per second
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief frequency in jiffies per second
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this thread [in jiffies]
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClock();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this thread [in nanoseconds]
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClockNS();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this thread [in milliseconds]
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency in jiffies per second
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this process [in jiffies]
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClock();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this process [in nanoseconds]
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClockNS();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this process [in milliseconds]
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClockMS();
|
||||
|
||||
// Advanced clocks: ////////////////////////
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClockMS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClockJiffies();
|
||||
}
|
@ -7,10 +7,12 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "StaticClocksDirect.hpp"
|
||||
#include "StaticClocksClasses.hpp"
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
AUKN_SYM AuUInt64 SteadyClockNS();
|
||||
|
||||
template <typename DefaultClock_t = ClockSteady>
|
||||
struct Stopwatch
|
||||
{
|
||||
inline Stopwatch()
|
||||
@ -25,29 +27,42 @@ namespace Aurora::Time
|
||||
|
||||
inline void Start()
|
||||
{
|
||||
this->start_ = SteadyClockNS();
|
||||
this->qwStart_ = GetTimeInNanosecond();
|
||||
}
|
||||
|
||||
inline void Reset()
|
||||
{
|
||||
this->start_ = SteadyClockNS();
|
||||
this->end_ = 0;
|
||||
this->qwStart_ = GetTimeInNanosecond();
|
||||
this->qwEnd_ = 0;
|
||||
}
|
||||
|
||||
inline AuUInt64 EndNS()
|
||||
{
|
||||
if (!this->end_) this->end_ = SteadyClockNS();
|
||||
return this->end_ - this->start_;
|
||||
if (!this->qwEnd_)
|
||||
{
|
||||
this->qwEnd_ = GetTimeInNanosecond();
|
||||
}
|
||||
|
||||
return this->qwEnd_ - this->qwStart_;
|
||||
}
|
||||
|
||||
inline AuUInt64 EndMS()
|
||||
{
|
||||
if (!this->end_) this->end_ = SteadyClockNS();
|
||||
return AuNSToMS<AuUInt64>(this->end_ - this->start_);
|
||||
if (!this->qwEnd_)
|
||||
{
|
||||
this->qwEnd_ = GetTimeInNanosecond();
|
||||
}
|
||||
|
||||
return AuNSToMS<AuUInt64>(this->qwEnd_ - this->qwStart_);
|
||||
}
|
||||
|
||||
private:
|
||||
AuUInt64 start_ {};
|
||||
AuUInt64 end_ {};
|
||||
AuUInt64 qwStart_ {};
|
||||
AuUInt64 qwEnd_ {};
|
||||
|
||||
inline AuUInt64 GetTimeInNanosecond()
|
||||
{
|
||||
return Clock<DefaultClock_t>::GetCurrentTimeNS();
|
||||
}
|
||||
};
|
||||
}
|
@ -9,6 +9,10 @@
|
||||
|
||||
#include "_Time.hpp"
|
||||
|
||||
#include "StaticClocks.hpp"
|
||||
#include "StaticClocksDirect.hpp"
|
||||
#include "StaticClocksClasses.hpp"
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
/**
|
||||
@ -48,189 +52,7 @@ namespace Aurora::Time
|
||||
*/
|
||||
AUKN_SYM AuInt64 ConvertUnixToAuroraNS(AuInt64 in);
|
||||
|
||||
/**
|
||||
Retrieves wall clock in milliseconds from the Aurora epoch
|
||||
*/
|
||||
AUKN_SYM AuInt64 CurrentClockMS();
|
||||
|
||||
/**
|
||||
Retrieves wall clock in nanoseconds from the Aurora epoch
|
||||
*/
|
||||
AUKN_SYM AuInt64 CurrentClockNS();
|
||||
|
||||
/**
|
||||
* @brief Steady clock in jiffies
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClock();
|
||||
|
||||
/**
|
||||
Returns a steady system clock of SteadyClockJiffies() with an undefined epoch.
|
||||
|
||||
These values should be used to drive thread primitives, IO time, and tick delta.
|
||||
On a modern plaform, these should be affected by the users' calendar or NTP.
|
||||
On stinkier platforms, who cares if we can run mostly bug free with an assumed-sane wall-clock, right?
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClockMS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClockNS();
|
||||
|
||||
/**
|
||||
Retrieves the freqency of jiffies per second
|
||||
*/
|
||||
AUKN_SYM AuUInt64 SteadyClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief frequency in jiffies per second
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this thread [in jiffies]
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClock();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this thread [in nanoseconds]
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClockNS();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this thread [in milliseconds]
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency in jiffies per second
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this process [in jiffies]
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClock();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this process [in nanoseconds]
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClockNS();
|
||||
|
||||
/**
|
||||
* @brief time spent in userspace and in the kernel under this process [in milliseconds]
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessClockMS();
|
||||
|
||||
// Advanced clocks: ////////////////////////
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadUserClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessUserClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClockMS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ThreadKernelClockJiffies();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClockNS();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClockMS();
|
||||
|
||||
/**
|
||||
* @brief frequency
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuUInt64 ProcessKernelClockJiffies();
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
Converts seconds from the Aurora epoch to time_t
|
||||
@ -249,60 +71,6 @@ namespace Aurora::Time
|
||||
|
||||
AUKN_SYM AuInt64 CTimeToMS(time_t time);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetWallClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetSteadyClock();
|
||||
|
||||
/**
|
||||
* @brief kernel + userland cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetProcessClock();
|
||||
|
||||
/**
|
||||
* @brief user time used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetProcessUserClock();
|
||||
|
||||
/**
|
||||
* @brief kernel (if known) cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetProcessKernelClock();
|
||||
|
||||
/**
|
||||
* @brief kernel + userland cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetThreadClock();
|
||||
|
||||
/**
|
||||
* @brief user time used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetThreadUserClock();
|
||||
|
||||
/**
|
||||
* @brief kernel (if known) cycles used
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetThreadKernelClock();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param clock
|
||||
* @return
|
||||
*/
|
||||
AUKN_SYM AuSPtr<IClock> GetClockFromEnum(EClock clock);
|
||||
|
||||
// TODO: Unix style of GetClockTimeNSByEnum/GetClockResNSByEnum?
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user