aboutsummaryrefslogtreecommitdiff
path: root/zencore
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-10-05 22:25:53 +0200
committerStefan Boberg <[email protected]>2021-10-05 22:25:53 +0200
commit20ac7384f8ca558f1fb933eda846604792240ea0 (patch)
treee5c95b422b847af50b77807af916e389fcaf83aa /zencore
parentstats: Mean returns zero when the count is zero (diff)
downloadzen-20ac7384f8ca558f1fb933eda846604792240ea0.tar.xz
zen-20ac7384f8ca558f1fb933eda846604792240ea0.zip
Merged from upstream
Diffstat (limited to 'zencore')
-rw-r--r--zencore/compactbinary.cpp51
-rw-r--r--zencore/filesystem.cpp9
-rw-r--r--zencore/include/zencore/blockingqueue.h73
-rw-r--r--zencore/include/zencore/refcount.h9
-rw-r--r--zencore/include/zencore/timer.h15
-rw-r--r--zencore/timer.cpp16
6 files changed, 169 insertions, 4 deletions
diff --git a/zencore/compactbinary.cpp b/zencore/compactbinary.cpp
index 4072ab5cf..c4694733c 100644
--- a/zencore/compactbinary.cpp
+++ b/zencore/compactbinary.cpp
@@ -1474,10 +1474,30 @@ public:
Builder << Accessor.AsIntegerNegative();
break;
case CbFieldType::Float32:
- Builder.Append("{:.9g}"_format(Accessor.AsFloat32()));
+ {
+ const float Value = Accessor.AsFloat32();
+ if (std::isfinite(Value))
+ {
+ Builder.Append("{:.9g}"_format(Value));
+ }
+ else
+ {
+ Builder << "null"sv;
+ }
+ }
break;
case CbFieldType::Float64:
- Builder.Append("{:.17g}"_format(Accessor.AsFloat64()));
+ {
+ const double Value = Accessor.AsFloat64();
+ if (std::isfinite(Value))
+ {
+ Builder.Append("{:.17g}"_format(Value));
+ }
+ else
+ {
+ Builder << "null"sv;
+ }
+ }
break;
case CbFieldType::BoolFalse:
Builder << "false"sv;
@@ -1834,7 +1854,7 @@ TEST_CASE("uson.json")
SUBCASE("number")
{
- const double ExpectedFloatValue = 21.21f;
+ const float ExpectedFloatValue = 21.21f;
const double ExpectedDoubleValue = 42.42;
CbObjectWriter Writer;
@@ -1856,6 +1876,31 @@ TEST_CASE("uson.json")
CHECK(FloatValue == doctest::Approx(ExpectedFloatValue));
CHECK(DoubleValue == doctest::Approx(ExpectedDoubleValue));
}
+
+ SUBCASE("number.nan")
+ {
+ const float FloatNan = std::numeric_limits<float>::quiet_NaN();
+ const double DoubleNan = std::numeric_limits<double>::quiet_NaN();
+
+ CbObjectWriter Writer;
+ Writer << "FloatNan" << FloatNan;
+ Writer << "DoubleNan" << DoubleNan;
+
+ CbObject Obj = Writer.Save();
+
+ StringBuilder<128> Sb;
+ const std::string_view JsonText = Obj.ToJson(Sb).ToView();
+
+ std::string JsonError;
+ json11::Json Json = json11::Json::parse(JsonText.data(), JsonError);
+
+ const double FloatValue = Json["FloatNan"].number_value();
+ const double DoubleValue = Json["DoubleNan"].number_value();
+
+ CHECK(JsonError.empty());
+ CHECK(FloatValue == 0);
+ CHECK(DoubleValue == 0);
+ }
}
#endif
diff --git a/zencore/filesystem.cpp b/zencore/filesystem.cpp
index f6ba92f98..745fe0779 100644
--- a/zencore/filesystem.cpp
+++ b/zencore/filesystem.cpp
@@ -63,6 +63,13 @@ DeleteReparsePoint(const wchar_t* Path, DWORD dwReparseTag)
bool
CreateDirectories(const wchar_t* Dir)
{
+ // This may be suboptimal, in that it appears to try and create directories
+ // from the root on up instead of from some directory which is known to
+ // be present
+ //
+ // We should implement a smarter version at some point since this can be
+ // pretty expensive in aggregate
+
return std::filesystem::create_directories(Dir);
}
@@ -522,7 +529,7 @@ WriteFile(std::filesystem::path Path, IoBuffer Data)
WriteFile(Path, &DataPtr, 1);
}
-IoBuffer
+IoBuffer
FileContents::Flatten()
{
if (Data.size() == 1)
diff --git a/zencore/include/zencore/blockingqueue.h b/zencore/include/zencore/blockingqueue.h
new file mode 100644
index 000000000..fbb4480a1
--- /dev/null
+++ b/zencore/include/zencore/blockingqueue.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include <atomic>
+#include <deque>
+#include <mutex>
+
+namespace zen {
+
+template<typename T>
+class BlockingQueue
+{
+public:
+ BlockingQueue() = default;
+
+ ~BlockingQueue() { CompleteAdding(); }
+
+ void Enqueue(T&& Item)
+ {
+ {
+ std::lock_guard Lock(m_Lock);
+ m_Queue.emplace_back(std::move(Item));
+ m_Size++;
+ }
+
+ m_NewItemSignal.notify_one();
+ }
+
+ bool WaitAndDequeue(T& Item)
+ {
+ if (m_CompleteAdding.load())
+ {
+ return false;
+ }
+
+ std::unique_lock Lock(m_Lock);
+ m_NewItemSignal.wait(Lock, [this]() { return !m_Queue.empty() || m_CompleteAdding.load(); });
+
+ if (!m_Queue.empty())
+ {
+ Item = std::move(m_Queue.front());
+ m_Queue.pop_front();
+ m_Size--;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ void CompleteAdding()
+ {
+ if (!m_CompleteAdding.load())
+ {
+ m_CompleteAdding.store(true);
+ m_NewItemSignal.notify_all();
+ }
+ }
+
+ std::size_t Size() const
+ {
+ std::unique_lock Lock(m_Lock);
+ return m_Queue.size();
+ }
+
+private:
+ mutable std::mutex m_Lock;
+ std::condition_variable m_NewItemSignal;
+ std::deque<T> m_Queue;
+ std::atomic_bool m_CompleteAdding{false};
+ std::atomic_uint32_t m_Size;
+};
+
+} // namespace zen
diff --git a/zencore/include/zencore/refcount.h b/zencore/include/zencore/refcount.h
index 320718f5b..7167ab3b5 100644
--- a/zencore/include/zencore/refcount.h
+++ b/zencore/include/zencore/refcount.h
@@ -4,6 +4,8 @@
#include "atomic.h"
#include "zencore.h"
+#include <concepts>
+
namespace zen {
/**
@@ -114,6 +116,10 @@ public:
inline Ref(T* Ptr) : m_Ref(Ptr) { m_Ref && m_Ref->AddRef(); }
inline ~Ref() { m_Ref && m_Ref->Release(); }
+ template<typename DerivedType>
+ requires std::derived_from<DerivedType, T>
+ inline Ref(const Ref<DerivedType>& Rhs) : Ref(Rhs.m_Ref) {}
+
[[nodiscard]] inline bool IsNull() const { return m_Ref == nullptr; }
inline explicit operator bool() const { return m_Ref != nullptr; }
inline T* operator->() const { return m_Ref; }
@@ -152,6 +158,9 @@ public:
private:
T* m_Ref = nullptr;
+
+ template<class T>
+ friend class Ref;
};
void refcount_forcelink();
diff --git a/zencore/include/zencore/timer.h b/zencore/include/zencore/timer.h
index 693b6daaa..e4ddc3505 100644
--- a/zencore/include/zencore/timer.h
+++ b/zencore/include/zencore/timer.h
@@ -38,6 +38,21 @@ private:
uint64_t m_StartValue;
};
+// Low frequency timers
+
+namespace detail {
+ extern ZENCORE_API uint64_t g_LofreqTimerValue;
+} // namespace detail
+
+inline uint64_t
+GetLofreqTimerValue()
+{
+ return detail::g_LofreqTimerValue;
+}
+
+ZENCORE_API void UpdateLofreqTimerValue();
+ZENCORE_API uint64_t GetLofreqTimerFrequency();
+
void timer_forcelink(); // internal
} // namespace zen
diff --git a/zencore/timer.cpp b/zencore/timer.cpp
index 5d30d9b29..9180519bd 100644
--- a/zencore/timer.cpp
+++ b/zencore/timer.cpp
@@ -69,6 +69,22 @@ GetHifreqTimerFrequencySafe()
}
//////////////////////////////////////////////////////////////////////////
+
+uint64_t detail::g_LofreqTimerValue = GetHifreqTimerValue();
+
+void
+UpdateLofreqTimerValue()
+{
+ detail::g_LofreqTimerValue = GetHifreqTimerValue();
+}
+
+uint64_t
+GetLofreqTimerFrequency()
+{
+ return GetHifreqTimerFrequencySafe();
+}
+
+//////////////////////////////////////////////////////////////////////////
//
// Testing related code follows...
//