]> code.bitgloo.com Git - clyne/osdev.git/commitdiff
keyboard input buffering
authorClyne Sullivan <clyne@bitgloo.com>
Sat, 28 Sep 2024 15:06:36 +0000 (11:06 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Sat, 28 Sep 2024 15:06:36 +0000 (11:06 -0400)
Makefile
circularbuffer.hpp [new file with mode: 0644]
kernel.cpp
keyboard.cpp
keyboard.hpp
memory.cpp
memory.hpp

index f3674a67774e0eaaf9cf9d5f43bae3a718dfbd36..048094329657c74b73d624b535c71c97a8a9a45a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-CXXFLAGS := -m32 -ggdb -g3 -O0 -fno-pic -ffreestanding -fno-rtti -fno-exceptions -std=c++23
-LDFLAGS := -m32 -static -T link.ld -ffreestanding -nostdlib
+CXXFLAGS := -m32 -ggdb -g3 -O0 -fno-pic -fno-rtti -fno-exceptions -std=c++23
+LDFLAGS := $(CXXFLAGS) -T link.ld -static -nostdlib -fno-use-cxa-atexit
 
 CXXFILES := acpi.cpp \
         boot.cpp \
diff --git a/circularbuffer.hpp b/circularbuffer.hpp
new file mode 100644 (file)
index 0000000..64a9e48
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+MIT License
+
+Copyright (c) 2020 Vinit James
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef CIRCULAR_BUFFER_H
+#define CIRCULAR_BUFFER_H
+
+#include <algorithm>
+#include <iterator>
+#include <mutex>
+#include <memory>
+#include <stdexcept>
+#include <utility>
+
+
+template<typename T>
+class CircularBuffer {
+private:
+       
+       typedef T* pointer;
+       typedef const T* const_pointer;
+       typedef T& reference;
+       typedef const T& const_reference;
+       typedef size_t size_type;
+       typedef ptrdiff_t difference_type;
+    template <bool isConst> struct BufferIterator;
+       
+
+public:
+    typedef T value_type;
+
+    // clyne
+    constexpr CircularBuffer()
+        :_buff{}, _max_size{0} {}
+
+       explicit CircularBuffer(size_t size)
+               :_buff{std::unique_ptr<T[]>(new value_type[size])}, _max_size{size}{}
+
+       CircularBuffer(const CircularBuffer& other)
+               :_buff{std::unique_ptr<T[]>(new value_type[other._max_size])},
+                _max_size{other._max_size},
+                _size{other._size},
+                _head{other._head},
+                _tail{other._tail}{
+                        std::copy(other.data(), other.data() + _max_size, _buff.get());
+                }
+
+       
+       CircularBuffer& operator=(const CircularBuffer& other){
+               if ( this != &other){
+                       _buff.reset(new value_type[other._max_size]);
+                       _max_size = other._max_size;
+                       _size = other._size;
+                       _head = other._head;
+                       _tail = other._tail;
+                       std::copy(other.data(), other.data() + _max_size, _buff.get());
+               }
+               return *this;
+       }
+
+       CircularBuffer(CircularBuffer&& other) noexcept
+               :_buff{std::move(other._buff)},
+                _max_size{other._max_size},
+                _size{other._size},
+                _head{other._head},
+                _tail{other._tail}{
+
+               other._buff = nullptr;
+               other._max_size = 0;
+               other._size = 0;
+               other._head = 0;
+               other._tail = 0;
+       }
+
+       
+       CircularBuffer& operator=(CircularBuffer&& other) noexcept{
+               if ( this != &other){
+                       _buff = std::move(other._buff);
+                       _max_size = other._max_size;
+                       _size = other._size;
+                       _head = other._head;
+                       _tail = other._tail;
+                       
+                       other._buff = nullptr;
+                       other._max_size = 0;
+                       other._size = 0;
+                       other._head = 0;
+                       other._tail = 0;                        
+               }
+               return *this;
+       }
+       
+       void push_back(const value_type& data);
+       void push_back(value_type&& data) noexcept;
+       void pop_front();
+       reference front();
+       reference back(); 
+       const_reference front() const; 
+       const_reference back() const;
+       void clear();
+       bool empty() const ;
+       bool full() const ;
+       size_type capacity() const ;
+       size_type size() const;
+       size_type buffer_size() const {return sizeof(value_type)*_max_size;};
+       const_pointer data() const { return _buff.get(); }
+       
+       const_reference operator[](size_type index) const;
+       reference operator[](size_type index);
+       const_reference at(size_type index) const;
+       reference at(size_type index);
+
+       typedef BufferIterator<false> iterator;
+       typedef BufferIterator<true> const_iterator;
+       
+       iterator begin();
+       const_iterator begin() const;
+       iterator end();
+       const_iterator end() const;
+       const_iterator cbegin() const noexcept;
+       const_iterator cend() const noexcept;
+       iterator rbegin() noexcept;
+       const_iterator rbegin() const noexcept;
+       iterator rend() noexcept;
+       const_iterator rend() const noexcept;
+       
+               
+private:
+       void _increment_bufferstate();
+       void _decrement_bufferstate();
+    // clyne
+       //mutable std::mutex _mtx;
+       std::unique_ptr<value_type[]> _buff;
+       size_type _head = 0;
+       size_type _tail = 0;
+       size_type _size = 0;
+       size_type _max_size = 0;
+                       
+    template<bool isConst = false>
+       struct  BufferIterator{
+       public:
+               friend class CircularBuffer<T>;
+               typedef std::random_access_iterator_tag iterator_category;
+               typedef ptrdiff_t difference_type;
+               typedef T value_type;
+               typedef typename std::conditional<isConst, const value_type&, value_type&>::type reference;
+               typedef typename std::conditional<isConst, const value_type*, value_type*>::type pointer;
+               typedef typename std::conditional<isConst, const CircularBuffer<value_type>*,
+                                                                                 CircularBuffer<value_type>*>::type cbuf_pointer;
+       private:
+               cbuf_pointer _ptrToBuffer;
+               size_type _offset;
+               size_type _index;
+               bool _reverse;
+               
+               bool _comparable(const BufferIterator<isConst>& other) const{
+                       return (_ptrToBuffer == other._ptrToBuffer)&&(_reverse == other._reverse);
+               }
+               
+       public:
+               BufferIterator()
+                       :_ptrToBuffer{nullptr}, _offset{0}, _index{0}, _reverse{false}{}
+               
+               BufferIterator(const BufferIterator<false>& it)
+                       :_ptrToBuffer{it._ptrToBuffer},
+                        _offset{it._offset},
+                        _index{it._index},
+                        _reverse{it._reverse}{}
+
+               reference operator*(){
+                       if(_reverse)
+                               return (*_ptrToBuffer)[(_ptrToBuffer->size() - _index - 1)];
+                       return (*_ptrToBuffer)[_index];
+               }
+
+               pointer  operator->() { return &(operator*()); }
+
+               reference operator[](size_type index){
+                       BufferIterator iter = *this;
+                       iter._index += index;
+                       return *iter;
+               }
+
+               BufferIterator& operator++(){
+                       ++_index;
+                       return *this;
+               }
+
+               BufferIterator operator++(int){
+                       BufferIterator iter = *this;
+                       ++_index;
+                       return iter;
+               }
+
+               BufferIterator& operator--(){
+                       --_index;
+                       return *this;
+               }
+
+               BufferIterator operator--(int){
+                       BufferIterator iter = *this;
+                       --_index;
+                       return iter;
+               }       
+
+               friend BufferIterator operator+(BufferIterator lhsiter, difference_type n){
+                       lhsiter._index += n;
+                       return lhsiter;
+               }
+
+               friend BufferIterator operator+(difference_type n, BufferIterator rhsiter){
+                       rhsiter._index += n;
+                       return rhsiter;
+               }
+               
+
+               BufferIterator& operator+=(difference_type n){
+                       _index += n;
+                       return *this;
+               }
+
+               friend BufferIterator operator-(BufferIterator lhsiter, difference_type n){
+                       lhsiter._index -= n;
+                       return lhsiter;
+               }
+
+               friend difference_type operator-(const BufferIterator& lhsiter, const BufferIterator& rhsiter){
+                       
+                       return lhsiter._index - rhsiter._index;
+               }
+
+               BufferIterator& operator-=(difference_type n){
+                       _index -= n;
+                       return *this;
+               }
+
+               bool operator==(const BufferIterator& other) const{
+                       if (!_comparable(other))
+                               return false;
+                       return ((_index == other._index)&&(_offset == other._offset));
+               }
+               
+               bool operator!=(const BufferIterator& other) const{
+                       if (!_comparable(other))
+                               return true;
+                       return ((_index != other._index)||(_offset != other._offset));
+               }
+
+               bool operator<(const BufferIterator& other) const {
+                       if (!_comparable(other))
+                               return false;
+                       return ((_index + _offset)<(other._index+other._offset));
+               }
+
+               bool operator>(const BufferIterator& other) const{
+                       if (!_comparable(other))
+                               return false;
+                       return ((_index + _offset)>(other._index+other._offset));
+               }
+
+               bool operator<=(const BufferIterator& other) const {
+                       if (!_comparable(other))
+                               return false;
+                       return ((_index + _offset)<=(other._index+other._offset));
+               }
+
+               bool operator>=(const BufferIterator& other) const {
+                       if (!_comparable(other))
+                               return false;
+                       return ((_index + _offset)>=(other._index+other._offset));
+               }
+       };
+};
+
+template<typename T>
+inline 
+bool CircularBuffer<T>::full() const{
+       return _size == _max_size;
+}
+
+template<typename T>
+inline 
+bool CircularBuffer<T>::empty() const{
+       return _size == 0;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::size_type CircularBuffer<T>::capacity() const{
+       return _max_size;
+}
+
+template<typename T>
+inline 
+void  CircularBuffer<T>::clear(){
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       _head = _tail = _size = 0;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::size_type CircularBuffer<T>::size() const{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       return _size;
+       }
+
+template<typename T>
+inline
+typename CircularBuffer<T>::reference CircularBuffer<T>::front() {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+    // clyne
+       if(empty())
+               abort(); //throw std::length_error("front function called on empty buffer");
+       return _buff[_tail];
+}
+
+template<typename T>
+inline
+typename CircularBuffer<T>::reference CircularBuffer<T>::back() {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if(empty())
+               abort(); //throw std::length_error("back function called on empty buffer");
+       return _head == 0 ? _buff[_max_size - 1] : _buff[_head - 1];
+}
+
+template<typename T>
+inline
+typename CircularBuffer<T>::const_reference CircularBuffer<T>::front() const{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if(empty())
+               abort(); //throw std::length_error("front function called on empty buffer");
+       return _buff[_tail];
+}
+
+template<typename T>
+inline
+typename CircularBuffer<T>::const_reference CircularBuffer<T>::back() const{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if(empty())
+               abort(); //throw std::length_error("back function called on empty buffer");
+       return _head == 0 ? _buff[_max_size - 1] : _buff[_head - 1];
+}
+
+template<typename T>
+inline
+void CircularBuffer<T>::push_back(const T& data){
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       //if(full())
+       //      _buff[_tail].~T();
+       _buff[_head] = data;
+       _increment_bufferstate();
+}
+
+template<typename T>
+inline
+void CircularBuffer<T>::push_back(T&& data) noexcept{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       _buff[_head] = std::move(data);
+       _increment_bufferstate();
+}
+
+
+template<typename T>
+inline 
+void CircularBuffer<T>::_increment_bufferstate(){
+       if(full())
+               _tail = (_tail + 1)%_max_size;
+       else
+               ++_size;
+       _head = (_head + 1)%_max_size;  
+}
+
+template<typename T>
+inline 
+void CircularBuffer<T>::pop_front(){
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if(empty())
+               abort(); //throw std::length_error("pop_front called on empty buffer");
+       _decrement_bufferstate();
+}
+
+template<typename T>
+inline 
+void CircularBuffer<T>::_decrement_bufferstate(){
+       --_size;
+       _tail = (_tail + 1)%_max_size;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::reference CircularBuffer<T>::operator[](size_t index) {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if((index<0)||(index>=_size))
+               abort(); //throw std::out_of_range("Index is out of Range of buffer size");
+       index += _tail;
+       index %= _max_size;
+       return _buff[index];
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_reference CircularBuffer<T>::operator[](size_t index) const {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if((index<0)||(index>=_size))
+               abort(); //throw std::out_of_range("Index is out of Range of buffer size");
+       index += _tail;
+       index %= _max_size;
+       return _buff[index];
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::reference CircularBuffer<T>::at(size_t index) {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if((index<0)||(index>=_size))
+               abort(); //throw std::out_of_range("Index is out of Range of buffer size");
+       index += _tail;
+       index %= _max_size;
+       return _buff[index];
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_reference CircularBuffer<T>::at(size_t index) const {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       if((index<0)||(index>=_size))
+               abort(); //throw std::out_of_range("Index is out of Range of buffer size");
+       index += _tail;
+       index %= _max_size;
+       return _buff[index];
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::iterator CircularBuffer<T>::begin() {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = 0;
+       iter._reverse = false;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_iterator CircularBuffer<T>::begin() const{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       const_iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = 0;
+       iter._reverse = false;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::iterator CircularBuffer<T>::end() {
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = _size;
+       iter._reverse = false;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_iterator CircularBuffer<T>::end() const{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       const_iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = _size;
+       iter._reverse = false;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cbegin() const noexcept{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       const_iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = 0;
+       iter._reverse = false;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_iterator CircularBuffer<T>::cend() const noexcept{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       const_iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = _size;
+       iter._reverse = false;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::iterator CircularBuffer<T>::rbegin() noexcept{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = 0;
+       iter._reverse = true;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rbegin() const noexcept{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       const_iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = 0;
+       iter._reverse = true;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::iterator CircularBuffer<T>::rend()  noexcept{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = _size;
+       iter._reverse = true;
+       return iter;
+}
+
+template<typename T>
+inline 
+typename CircularBuffer<T>::const_iterator CircularBuffer<T>::rend() const noexcept{
+       //std::lock_guard<std::mutex> _lck(_mtx);
+       const_iterator iter;
+       iter._ptrToBuffer = this;
+       iter._offset = _tail;
+       iter._index = _size;
+       iter._reverse = true;
+       return iter;
+}
+
+#endif /* CIRCULAR_BUFFER_H */
index 26d5b7dc303f15d054484a0d641805ddf63d6aa1..408a19ed20846db2b1c5217aa781e550263f5b22 100644 (file)
@@ -40,35 +40,28 @@ void kernel_main(void)
     tasking_initialize();
     term.write("Tasking enabled.\n");
 
-    //tasking_spawn([] {
-    //    for (;;) {
-    //        do pit_delay_ms(1);
-    //        while (termBusy);
-
-    //        termBusy = true;
-    //        term.write('B');
-    //        termBusy = false;
-    //    }
-    //}, 256);
-
-    //tasking_spawn([] {
-    //    for (;;) {
-    //        do pit_delay_ms(1);
-    //        while (termBusy);
-
-    //        termBusy = true;
-    //        term.write('C');
-    //        termBusy = false;
-    //    }
-    //}, 256);
-
     for (;;) {
-        pit_delay_ms(100);
-        //while (termBusy);
+        const auto ch = keyboard_read();
+        if (ch)
+            term.write(*ch);
 
-        //termBusy = true;
-        //term.write('A');
-        //termBusy = false;
+        pit_delay_ms(10);
     }
 }
 
+extern "C"
+void abort()
+{
+    term.write("!!! abort() called !!!");
+    asm volatile("cli");
+    for (;;);
+}
+
+extern "C"
+int __cxa_atexit(void (*func)(void *), void *arg, void *dso_handle)
+{
+    return 0;
+}
+
+int __dso_handle = 0;
+
index 18d7acd478e22ab5ea7d6db8722762078009313d..29178f96f93e66c2b16a022b21e21dc610f46618 100644 (file)
@@ -1,33 +1,16 @@
+#include "circularbuffer.hpp"
 #include "idt.hpp"
+#include "keyboard.hpp"
 #include "portio.hpp"
 #include "vgaterminal.hpp"
 
 #include <array>
 #include <cstdint>
 
-#define K_CONTROL_L -1
-#define K_SHIFT_L   -2
-#define K_ALT_L     -3
-#define K_CAPS      -4
-#define K_NUM       -5
-#define K_SCROLL    -6
-#define K_SHIFT_R   -7
-#define K_ESCAPE    -8
-#define K_F1        -10
-#define K_F2        -11
-#define K_F3        -12
-#define K_F4        -13
-#define K_F5        -14
-#define K_F6        -15
-#define K_F7        -16
-#define K_F8        -17
-#define K_F9        -18
-#define K_F10       -19
-#define K_F11       -20
-#define K_F12       -21
-
 extern TextOutput& term;
 
+static CircularBuffer<char> keyboardBuffer;
+
 static const std::array<char, 0x59> ScanCodeSet1 {{
     0, K_ESCAPE,
     '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
@@ -52,14 +35,29 @@ static constexpr auto keycode(auto ch) {
 
 void keyboard_initialize()
 {
+    keyboardBuffer = CircularBuffer<char>(128);
+
     idt_register_callback(33, [](auto& regs) {
         const auto kc = inb(0x60);
 
         if (!isReleased(kc)) {
             const auto ch = ScanCodeSet1[keycode(kc)];
-            if (ch > 0)
-                term.write(ch);
+            //if (ch > 0)
+            //    term.write(ch);
+
+            keyboardBuffer.push_back(ch);
         }
     });
 }
 
+std::optional<char> keyboard_read()
+{
+    if (keyboardBuffer.empty()) {
+        return {};
+    } else {
+        const auto ch = keyboardBuffer.front();
+        keyboardBuffer.pop_front();
+        return ch;
+    }
+}
+
index 40b57c9e80363d44156c2bd33f5574b372ac27b8..694ff89d26ec3a75b64106b259b18004ec8ff9e8 100644 (file)
@@ -1,7 +1,32 @@
 #ifndef KEYBOARD_HPP
 #define KEYBOARD_HPP
 
+#include <optional>
+
+#define K_CONTROL_L -1
+#define K_SHIFT_L   -2
+#define K_ALT_L     -3
+#define K_CAPS      -4
+#define K_NUM       -5
+#define K_SCROLL    -6
+#define K_SHIFT_R   -7
+#define K_ESCAPE    -8
+#define K_F1        -10
+#define K_F2        -11
+#define K_F3        -12
+#define K_F4        -13
+#define K_F5        -14
+#define K_F6        -15
+#define K_F7        -16
+#define K_F8        -17
+#define K_F9        -18
+#define K_F10       -19
+#define K_F11       -20
+#define K_F12       -21
+
 void keyboard_initialize();
 
+std::optional<char> keyboard_read();
+
 #endif // KEYBOARD_HPP
 
index 2cc15bea2b4326345b0362e9360f174b439cdb01..59e2bbeb9a20a3c4918b879e8a25403952d13c54 100644 (file)
@@ -85,3 +85,12 @@ void *operator new[](std::size_t size)
     return memory_alloc(size);
 }
 
+void operator delete(void *ptr)
+{
+
+}
+
+void operator delete[](void *ptr)
+{
+
+}
index 89552626f00cb5f77baca71dc9e471325f8a856a..0467bf637b18be01d07f397561dc58669ee8ab17 100644 (file)
@@ -1,6 +1,37 @@
 #ifndef MEMORY_HPP
 #define MEMORY_HPP
 
+#include <cstddef>
+#include <type_traits>
+
+template<typename T>
+struct kallocator
+{
+    using value_type = T;
+    using size_type = std::size_t;
+    using difference_type = std::ptrdiff_t;
+    using propagate_on_container_move_assignment = std::true_type;
+    using is_always_equal = std::true_type;
+
+    template<class U>
+    struct rebind {
+        typedef kallocator<U> other;
+    };
+
+    kallocator() = default;
+
+    template<typename U>
+    kallocator(const kallocator<U>&) noexcept {}
+
+    T* allocate(std::size_t n) {
+        return new T[n];
+    }
+
+    void deallocate([[maybe_unused]] T* p, [[maybe_unused]] std::size_t n) {
+
+    }
+};
+
 void memory_initialize();
 
 #endif // MEMORY_HPP