Browse Source

feat(libstdc++): add priority_queue

greatbridf 1 year ago
parent
commit
1da64db368

+ 202 - 0
gblibstdc++/include/algorithm

@@ -0,0 +1,202 @@
+#ifndef __GBLIBCPP_ALGORITHM__
+#define __GBLIBCPP_ALGORITHM__
+
+#include <functional>
+#include <utility>
+#include <initializer_list>
+#include <cstddef>
+
+namespace std {
+
+template <typename RandomIter, typename Compare>
+constexpr void make_heap(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    if (len < 2)
+        return;
+
+    auto idx = len / 2 - 1;
+    for (;;) {
+        auto& val = first[idx];
+        auto left = idx * 2 + 1;
+        auto right = left + 1;
+
+        if (right < len) {
+            auto& left_val = first[left];
+            auto& right_val = first[right];
+
+            if (comp(left_val, right_val)) {
+                if (comp(val, right_val)) {
+                    std::swap(val, right_val);
+                    idx = right;
+                    continue;
+                }
+            } else {
+                if (comp(val, left_val)) {
+                    std::swap(val, left_val);
+                    idx = left;
+                    continue;
+                }
+            }
+        } else if (left < len) {
+            auto& left_val = first[left];
+
+            if (comp(val, left_val)) {
+                std::swap(val, left_val);
+                idx = left;
+                continue;
+            }
+        }
+
+        if (idx == 0)
+            break;
+        --idx;
+    }
+}
+template <typename RandomIter>
+constexpr void make_heap(RandomIter first, RandomIter last)
+{
+    make_heap(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+template <typename RandomIter, typename Compare>
+constexpr void push_heap(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    if (len < 2)
+        return;
+
+    auto idx = len - 1;
+    for (;;) {
+        auto parent = (idx - 1) / 2;
+        if (parent == idx)
+            break;
+
+        auto& val = first[idx];
+        auto& parent_val = first[parent];
+
+        if (comp(parent_val, val)) {
+            std::swap(val, parent_val);
+            idx = parent;
+            continue;
+        }
+
+        break;
+    }
+}
+template <typename RandomIter>
+constexpr void push_heap(RandomIter first, RandomIter last)
+{
+    push_heap(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+template <typename RandomIter, typename Compare>
+constexpr void pop_heap(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    if (len < 2)
+        return;
+
+    std::swap(first[0], first[len - 1]);
+
+    auto idx = 0;
+    for (;;) {
+        auto& val = first[idx];
+        auto left = idx * 2 + 1;
+        auto right = left + 1;
+
+        if (right < len - 1) {
+            auto& left_val = first[left];
+            auto& right_val = first[right];
+
+            if (comp(left_val, right_val)) {
+                if (comp(val, right_val)) {
+                    std::swap(val, right_val);
+                    idx = right;
+                    continue;
+                }
+            } else {
+                if (comp(val, left_val)) {
+                    std::swap(val, left_val);
+                    idx = left;
+                    continue;
+                }
+            }
+        } else if (left < len - 1) {
+            auto& left_val = first[left];
+
+            if (comp(val, left_val)) {
+                std::swap(val, left_val);
+                idx = left;
+                continue;
+            }
+        }
+
+        if (idx == 0)
+            break;
+        --idx;
+    }
+}
+template <typename RandomIter>
+constexpr void pop_heap(RandomIter first, RandomIter last)
+{
+    pop_heap(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+template <typename RandomIter, typename Compare>
+constexpr void sort(RandomIter first, RandomIter last, Compare comp)
+{
+    auto len = last - first;
+    std::make_heap(first, last, comp);
+
+    for (auto i = len - 1; i > 0; --i) {
+        std::swap(first[0], first[i]);
+
+        auto idx = 0;
+        for (;;) {
+            auto& val = first[idx];
+            auto left = idx * 2 + 1;
+            auto right = left + 1;
+
+            if (right < i) {
+                auto& left_val = first[left];
+                auto& right_val = first[right];
+
+                if (comp(left_val, right_val)) {
+                    if (comp(val, right_val)) {
+                        std::swap(val, right_val);
+                        idx = right;
+                        continue;
+                    }
+                } else {
+                    if (comp(val, left_val)) {
+                        std::swap(val, left_val);
+                        idx = left;
+                        continue;
+                    }
+                }
+            } else if (left < i) {
+                auto& left_val = first[left];
+
+                if (comp(val, left_val)) {
+                    std::swap(val, left_val);
+                    idx = left;
+                    continue;
+                }
+            }
+
+            if (idx == 0)
+                break;
+            --idx;
+        }
+    }
+}
+template <typename RandomIter>
+constexpr void sort(RandomIter first, RandomIter last)
+{
+    sort(first, last, std::less<typename std::decay_t<decltype(*first)>>());
+}
+
+} // namespace std
+
+#endif

+ 14 - 0
gblibstdc++/include/functional

@@ -313,6 +313,20 @@ struct less<void> {
     { return std::forward<T>(lhs) < std::forward<U>(rhs); }
 };
 
+template <typename T = void>
+struct greater {
+    constexpr bool operator()(const T& lhs, const T& rhs) const
+    { return lhs > rhs; }
+};
+
+template <>
+struct greater<void> {
+    template <typename T, typename U>
+    constexpr auto operator()(T&& lhs, U&& rhs) const
+        -> decltype(std::forward<T>(lhs) > std::forward<U>(rhs))
+    { return std::forward<T>(lhs) > std::forward<U>(rhs); }
+};
+
 } // namespace std
 
 #endif

+ 150 - 0
gblibstdc++/include/queue

@@ -0,0 +1,150 @@
+#ifndef __GBLIBCPP_QUEUE__
+#define __GBLIBCPP_QUEUE__
+
+#include <vector>
+#include <functional>
+#include <memory>
+#include <algorithm>
+#include <initializer_list>
+#include <cstddef>
+
+namespace std {
+
+template <typename T,
+    typename Container = std::vector<T>,
+    typename Compare = std::less<typename Container::value_type>>
+class priority_queue {
+public:
+    using container_type = Container;
+    using value_compare = Compare;
+    using value_type = typename Container::value_type;
+    using size_type = typename Container::size_type;
+    using reference = typename Container::reference;
+    using const_reference = typename Container::const_reference;
+    using allocator_type = typename Container::allocator_type;
+
+protected:
+    container_type c;
+    value_compare comp;
+
+public:
+    __GBLIBCPP_CONSTEXPR
+    priority_queue(const Compare& comp, const Container& c)
+        : c(c), comp(comp)
+    {
+        std::make_heap(c.begin(), c.end(), comp);
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    explicit priority_queue(const Compare& comp, Container&& c)
+        : c(std::move(c)), comp(comp)
+    {
+        std::make_heap(c.begin(), c.end(), comp);
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    priority_queue() : priority_queue(Compare(), Container()) {}
+
+    __GBLIBCPP_CONSTEXPR
+    explicit priority_queue(const Compare& comp)
+        : priority_queue(comp, Container()) {}
+    
+    template <typename InputIter>
+    __GBLIBCPP_CONSTEXPR
+    priority_queue(InputIter first, InputIter last,
+        const Compare& comp = Compare())
+        : c(first, last), comp(comp)
+    {
+        std::make_heap(c.begin(), c.end(), comp);
+    }
+
+    template <typename InputIter>
+    __GBLIBCPP_CONSTEXPR
+    priority_queue(InputIter first, InputIter last,
+        const Compare& comp, const Container& c)
+        : c(c), comp(comp)
+    {
+        c.insert(c.end(), first, last);
+        std::make_heap(c.begin(), c.end(), comp);
+    }
+
+    template <typename InputIter>
+    __GBLIBCPP_CONSTEXPR
+    priority_queue(InputIter first, InputIter last,
+        const Compare& comp, Container&& c)
+        : c(std::move(c)), comp(comp)
+    {
+        c.insert(c.end(), first, last);
+        std::make_heap(c.begin(), c.end(), comp);
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    priority_queue(const priority_queue&) = default;
+    __GBLIBCPP_CONSTEXPR
+    priority_queue(priority_queue&&) = default;
+
+    __GBLIBCPP_CONSTEXPR
+    priority_queue& operator=(const priority_queue&) = default;
+    __GBLIBCPP_CONSTEXPR
+    priority_queue& operator=(priority_queue&&) = default;
+
+    [[nodiscard]]
+    __GBLIBCPP_CONSTEXPR
+    bool empty(void) const noexcept { return c.empty(); }
+    __GBLIBCPP_CONSTEXPR
+    size_type size(void) const noexcept { return c.size(); }
+    __GBLIBCPP_CONSTEXPR
+    const_reference top(void) const { return c.front(); }
+
+    __GBLIBCPP_CONSTEXPR
+    void push(const value_type& val)
+    {
+        c.push_back(val);
+        std::push_heap(c.begin(), c.end(), comp);
+    }
+    __GBLIBCPP_CONSTEXPR
+    void push(value_type&& val)
+    {
+        c.push_back(std::move(val));
+        std::push_heap(c.begin(), c.end(), comp);
+    }
+
+    template <typename... Args>
+    __GBLIBCPP_CONSTEXPR
+    void emplace(Args&&... args)
+    {
+        c.emplace_back(std::forward<Args>(args)...);
+        std::push_heap(c.begin(), c.end(), comp);
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    void pop(void)
+    {
+        std::pop_heap(c.begin(), c.end(), comp);
+        c.pop_back();
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    void swap(priority_queue& other) noexcept(
+        noexcept(std::swap(c, other.c)) &&
+        noexcept(std::swap(comp, other.comp)))
+    {
+        std::swap(c, other.c);
+        std::swap(comp, other.comp);
+    }
+};
+
+template <typename Compare, typename Container>
+priority_queue(Compare, Container)
+    -> priority_queue<typename Container::value_type,
+        Container, Compare>;
+
+template <typename T, typename Container, typename Compare>
+void swap(priority_queue<T, Container, Compare>& lhs,
+    priority_queue<T, Container, Compare>& rhs)
+    noexcept(noexcept(lhs.swap(rhs)))
+{ lhs.swap(rhs); }
+
+} // namespace std
+
+#endif

+ 15 - 3
gblibstdc++/include/vector

@@ -56,6 +56,18 @@ public:
         { --m_ptr; return *this; }
         constexpr _iterator operator--(int) noexcept
         { _iterator ret(m_ptr); (void)this->operator--(); return ret; }
+        constexpr _iterator& operator+=(difference_type n) noexcept
+        { m_ptr += n; return *this; }
+        constexpr _iterator& operator-=(difference_type n) noexcept
+        { m_ptr -= n; return *this; }
+        constexpr _iterator operator+(difference_type n) const noexcept
+        { return _iterator { m_ptr + n }; }
+        constexpr _iterator operator-(difference_type n) const noexcept
+        { return _iterator { m_ptr - n }; }
+        constexpr difference_type operator-(const _iterator& other) const noexcept
+        { return m_ptr - other.m_ptr; }
+        constexpr reference operator[](difference_type n) const noexcept
+        { return m_ptr[n]; }
         constexpr operator bool() { return m_ptr; }
         constexpr operator _iterator<true>() { return _iterator<true> { m_ptr }; }
         constexpr operator _iterator<false>() { return _iterator<false> { m_ptr }; }
@@ -166,7 +178,7 @@ public:
         shrink_to_fit();
     }
 
-    vector& operator=(const vector& other)
+    constexpr vector& operator=(const vector& other)
     {
         clear();
 
@@ -181,7 +193,7 @@ public:
         return *this;
     }
 
-    vector& operator=(vector&& other)
+    constexpr vector& operator=(vector&& other)
     {
         clear();
 
@@ -206,7 +218,7 @@ public:
         return *this;
     }
 
-    vector& operator=(std::initializer_list<T> init)
+    constexpr vector& operator=(std::initializer_list<T> init)
     {
         assign(init.begin(), init.end());
         return *this;

+ 19 - 14
include/kernel/process.hpp

@@ -2,6 +2,7 @@
 
 #include <map>
 #include <list>
+#include <queue>
 #include <set>
 #include <tuple>
 #include <utility>
@@ -98,6 +99,8 @@ public:
 private:
     inline static container_type* files;
     array_type arr;
+    std::priority_queue<int, std::vector<int>, std::greater<int>> _fds;
+    int _greatest_fd;
 
 public:
     inline static void init_global_file_container(void)
@@ -126,16 +129,13 @@ private:
             --iter->ref;
     }
 
-    constexpr int _next_fd(void) const
+    constexpr int next_fd()
     {
-        int fd = 0;
-
-        for (auto [ item_fd, iter_file ] : arr) {
-            if (item_fd == fd)
-                ++fd;
-        }
-
-        return fd;
+        if (_fds.empty())
+            return _greatest_fd++;
+        int retval = _fds.top();
+        _fds.pop();
+        return retval;
     }
 
 public:
@@ -147,7 +147,7 @@ public:
 
     constexpr int dup(int old_fd)
     {
-        return dup2(old_fd, _next_fd());
+        return dup2(old_fd, next_fd());
     }
 
     // TODO: the third parameter should be int flags
@@ -170,6 +170,8 @@ public:
 
     constexpr void dup_all(const filearr& orig)
     {
+        this->_fds = orig._fds;
+        this->_greatest_fd = orig._greatest_fd;
         for (auto [ fd, iter_file ] : orig.arr) {
             this->arr.emplace(fd, iter_file);
             ++iter_file->ref;
@@ -202,7 +204,7 @@ public:
         });
 
         bool inserted = false;
-        int fd = _next_fd();
+        int fd = next_fd();
         std::tie(std::ignore, inserted) = arr.emplace(fd, iter);
         assert(inserted);
 
@@ -220,7 +222,7 @@ public:
                 .write = 1,
             },
         });
-        fd = _next_fd();
+        fd = next_fd();
         std::tie(std::ignore, inserted) = arr.emplace(fd, iter);
         assert(inserted);
 
@@ -258,7 +260,7 @@ public:
             },
         });
 
-        int fd = _next_fd();
+        int fd = next_fd();
         auto [ _, inserted ] = arr.emplace(fd, iter);
         assert(inserted);
         return fd;
@@ -271,13 +273,16 @@ public:
             return;
 
         _close(iter->second);
+        _fds.push(fd);
         arr.erase(iter);
     }
 
     constexpr void close_all(void)
     {
-        for (auto&& [ fd, file ] : arr)
+        for (auto&& [ fd, file ] : arr) {
             _close(file);
+            _fds.push(fd);
+        }
         arr.clear();
     }
 

+ 1 - 2
include/kernel/vfs.hpp

@@ -124,8 +124,7 @@ public:
         } flags;
         name_type name;
 
-        explicit dentry(dentry* parent, inode* ind, const name_type& name);
-        explicit dentry(dentry* parent, inode* ind, name_type&& name);
+        explicit dentry(dentry* parent, inode* ind, name_type name);
         dentry(const dentry& val) = delete;
         constexpr dentry(dentry&& val)
             : children(std::exchange(val.children, nullptr))

+ 2 - 0
pretty-print.py

@@ -34,6 +34,8 @@ class vectorPrinter:
         return 'array'
 
     def children(self):
+        if self.val['m_size'] == 0:
+            return [ ('<vector of size 0>', '') ]
         return self._iterator(self.val['m_data'], self.val['m_data'] + self.val['m_size'], 0)
 
 def _leftmost(node):

+ 2 - 16
src/kernel/vfs.cpp

@@ -24,22 +24,8 @@ struct tmpfs_file_entry {
     char filename[128];
 };
 
-fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, const name_type& _name)
-    : parent(_parent)
-    , ind(_ind)
-    , flags { 0 }
-    , name(_name)
-{
-    if (!_ind || _ind->flags.in.directory) {
-        children = types::pnew<allocator_type>(children);
-        idx_children = types::pnew<allocator_type>(idx_children);
-    }
-}
-fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type&& _name)
-    : parent(_parent)
-    , ind(_ind)
-    , flags { 0 }
-    , name(std::move(_name))
+fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
+    : parent(_parent) , ind(_ind) , flags { } , name(_name)
 {
     if (!_ind || _ind->flags.in.directory) {
         children = types::pnew<allocator_type>(children);