Compare commits
No commits in common. "63f785563db3828dbea5678a60b478eace2ff526" and "d4d748e153668c2e8d807b86cdd9c1ca94fb50d8" have entirely different histories.
63f785563d
...
d4d748e153
@ -9,12 +9,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/Heap.h>
|
#include <luna/Heap.h>
|
||||||
#include <luna/SharedPtr.h>
|
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @brief Wrapper for callable objects with no arguments.
|
* @brief Wrapper for callable objects.
|
||||||
*
|
*
|
||||||
* Certain callable types such as capture lambdas don't have a named type, thus they can't be passed to functions as
|
* Certain callable types such as capture lambdas don't have a named type, thus they can't be passed to functions as
|
||||||
* arguments. The Action type acts as a callable wrapper for such functions, allowing them to be passed as arguments
|
* arguments. The Action type acts as a callable wrapper for such functions, allowing them to be passed as arguments
|
||||||
@ -41,16 +40,7 @@ namespace os
|
|||||||
*/
|
*/
|
||||||
Action(Action&& other) : m_action(other.m_action)
|
Action(Action&& other) : m_action(other.m_action)
|
||||||
{
|
{
|
||||||
other.m_action = {};
|
other.m_action = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Action object, copying it from another one.
|
|
||||||
*
|
|
||||||
* @param other The old Action object to copy from.
|
|
||||||
*/
|
|
||||||
Action(const Action& other) : m_action(other.m_action)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,8 +52,7 @@ namespace os
|
|||||||
*/
|
*/
|
||||||
template <typename T> Action(T&& function)
|
template <typename T> Action(T&& function)
|
||||||
{
|
{
|
||||||
m_action =
|
m_action = new (std::nothrow) ActionImpl<T>(move(function));
|
||||||
adopt_shared_if_nonnull((ActionBase*)new (std::nothrow) ActionImpl<T>(move(function))).release_value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,8 +65,8 @@ namespace os
|
|||||||
*/
|
*/
|
||||||
template <typename T> Action& operator=(T&& function)
|
template <typename T> Action& operator=(T&& function)
|
||||||
{
|
{
|
||||||
m_action =
|
if (m_action) delete m_action;
|
||||||
adopt_shared_if_nonnull((ActionBase*)new (std::nothrow) ActionImpl<T>(move(function))).release_value();
|
m_action = new (std::nothrow) ActionImpl<T>(move(function));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,8 +79,13 @@ namespace os
|
|||||||
return m_action->call();
|
return m_action->call();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Action()
|
||||||
|
{
|
||||||
|
if (m_action) delete m_action;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ActionBase : public Shareable
|
class ActionBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void call() = 0;
|
virtual void call() = 0;
|
||||||
@ -114,110 +108,6 @@ namespace os
|
|||||||
T m_function;
|
T m_function;
|
||||||
};
|
};
|
||||||
|
|
||||||
SharedPtr<ActionBase> m_action;
|
ActionBase* m_action;
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Wrapper for callable objects.
|
|
||||||
*
|
|
||||||
* Certain callable types such as capture lambdas don't have a named type, thus they can't be passed to functions as
|
|
||||||
* arguments. The Function type acts as a callable wrapper for such functions, allowing them to be passed as
|
|
||||||
* arguments to any function.
|
|
||||||
*/
|
|
||||||
template <class... Args> class Function
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new empty Function object.
|
|
||||||
*
|
|
||||||
* Since it is not wrapping any callable object, this object is invalid and attempting to invoke its
|
|
||||||
* (nonexistent) callable object will result in a crash at runtime.
|
|
||||||
*/
|
|
||||||
Function()
|
|
||||||
{
|
|
||||||
m_action = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Function object, moving it from another one.
|
|
||||||
*
|
|
||||||
* @param other The old Function object to move from. This object will become invalid.
|
|
||||||
*/
|
|
||||||
Function(Function&& other) : m_action(other.m_action)
|
|
||||||
{
|
|
||||||
other.m_action = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Function object, copying it from another one.
|
|
||||||
*
|
|
||||||
* @param other The old Function object to copy from.
|
|
||||||
*/
|
|
||||||
Function(const Function& other) : m_action(other.m_action)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Function object from a callable object.
|
|
||||||
*
|
|
||||||
* @tparam T The type of the callable object. Since this can be guessed by template deduction, the object
|
|
||||||
* doesn't actually need a type name.
|
|
||||||
* @param function The callable object to wrap.
|
|
||||||
*/
|
|
||||||
template <typename T> Function(T&& function)
|
|
||||||
{
|
|
||||||
m_action = adopt_shared_if_nonnull((FunctionBase*)new (std::nothrow) FunctionImpl<T>(move(function)))
|
|
||||||
.release_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assign a new callable object to this Function.
|
|
||||||
*
|
|
||||||
* @tparam T The type of the callable object. Since this can be guessed by template deduction, the object
|
|
||||||
* doesn't actually need a type name.
|
|
||||||
* @param function The callable object to wrap.
|
|
||||||
* @return Action& A reference to this object, as required by operator=().
|
|
||||||
*/
|
|
||||||
template <typename T> Function& operator=(T&& function)
|
|
||||||
{
|
|
||||||
m_action = adopt_shared_if_nonnull((FunctionBase*)new (std::nothrow) FunctionImpl<T>(move(function)))
|
|
||||||
.release_value();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Call the underlying object.
|
|
||||||
*/
|
|
||||||
void operator()(Args... args)
|
|
||||||
{
|
|
||||||
expect(m_action, "os::Function called with no underlying callable object");
|
|
||||||
return m_action->call(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
class FunctionBase : public Shareable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void call(Args... args) = 0;
|
|
||||||
virtual ~FunctionBase() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> class FunctionImpl final : public FunctionBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FunctionImpl(T&& function) : m_function(move(function))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void call(Args... args) override
|
|
||||||
{
|
|
||||||
return m_function(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T m_function;
|
|
||||||
};
|
|
||||||
|
|
||||||
SharedPtr<FunctionBase> m_action;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ namespace os
|
|||||||
* is the file descriptor registered, and the second argument is the type of event (POLLIN or POLLHUP)
|
* is the file descriptor registered, and the second argument is the type of event (POLLIN or POLLHUP)
|
||||||
* @return Result<void> Whether the operation succeeded.
|
* @return Result<void> Whether the operation succeeded.
|
||||||
*/
|
*/
|
||||||
Result<void> register_fd_listener(int fd, Function<int, int> listener);
|
Result<void> register_fd_listener(int fd, void (*listener)(int, int));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Register a new POSIX signal handler.
|
* @brief Register a new POSIX signal handler.
|
||||||
@ -59,7 +59,7 @@ namespace os
|
|||||||
* @param handler The function to call when this signal is caught.
|
* @param handler The function to call when this signal is caught.
|
||||||
* @return Result<void> Whether the operation succeeded.
|
* @return Result<void> Whether the operation succeeded.
|
||||||
*/
|
*/
|
||||||
Result<void> register_signal_handler(int sig, Function<int> handler);
|
Result<void> register_signal_handler(int sig, void (*handler)(int));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Run the event loop until it is asked to quit.
|
* @brief Run the event loop until it is asked to quit.
|
||||||
@ -76,8 +76,8 @@ namespace os
|
|||||||
void quit(int status = 0);
|
void quit(int status = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HashMap<int, Function<int, int>> m_fd_listeners;
|
HashMap<int, void (*)(int, int)> m_fd_listeners;
|
||||||
HashMap<int, Function<int>> m_signal_handlers;
|
HashMap<int, void (*)(int)> m_signal_handlers;
|
||||||
Vector<struct pollfd> m_pollfds;
|
Vector<struct pollfd> m_pollfds;
|
||||||
|
|
||||||
static void handle_signal(int sig);
|
static void handle_signal(int sig);
|
||||||
|
@ -44,14 +44,15 @@ namespace os
|
|||||||
return *s_the;
|
return *s_the;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> EventLoop::register_fd_listener(int fd, Function<int, int> listener)
|
// FIXME: Support lambdas (by using os::Action). This means that os::Action needs variable parameter support.
|
||||||
|
Result<void> EventLoop::register_fd_listener(int fd, void (*listener)(int, int))
|
||||||
{
|
{
|
||||||
TRY(m_fd_listeners.try_set(fd, move(listener)));
|
TRY(m_fd_listeners.try_set(fd, listener));
|
||||||
TRY(m_pollfds.try_append({ .fd = fd, .events = POLLIN, .revents = 0 }));
|
TRY(m_pollfds.try_append({ .fd = fd, .events = POLLIN, .revents = 0 }));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> EventLoop::register_signal_handler(int sig, Function<int> handler)
|
Result<void> EventLoop::register_signal_handler(int sig, void (*handler)(int))
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sa.sa_handler = EventLoop::handle_signal;
|
sa.sa_handler = EventLoop::handle_signal;
|
||||||
@ -59,7 +60,7 @@ namespace os
|
|||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
check(sigaction(sig, &sa, nullptr) == 0);
|
check(sigaction(sig, &sa, nullptr) == 0);
|
||||||
|
|
||||||
TRY(m_signal_handlers.try_set(sig, move(handler)));
|
TRY(m_signal_handlers.try_set(sig, handler));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ namespace os
|
|||||||
read(m_signal_pipe[0], &sig, sizeof(int));
|
read(m_signal_pipe[0], &sig, sizeof(int));
|
||||||
|
|
||||||
auto handler = m_signal_handlers.try_get(sig);
|
auto handler = m_signal_handlers.try_get(sig);
|
||||||
if (handler.has_value()) { (*handler.value_ptr())(sig); }
|
if (handler.has_value()) { handler.value()(sig); }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (usize i = 0; i < m_fd_listeners.size(); i++)
|
for (usize i = 0; i < m_fd_listeners.size(); i++)
|
||||||
@ -92,7 +93,7 @@ namespace os
|
|||||||
if (pfd.revents)
|
if (pfd.revents)
|
||||||
{
|
{
|
||||||
auto handler = m_fd_listeners.try_get(pfd.fd);
|
auto handler = m_fd_listeners.try_get(pfd.fd);
|
||||||
if (handler.has_value()) (*handler.value_ptr())(pfd.fd, pfd.revents);
|
if (handler.has_value()) handler.value()(pfd.fd, pfd.revents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ static void sigchld_handler(int)
|
|||||||
ui::App::the().set_should_close(true);
|
ui::App::the().set_should_close(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TerminalWidget* s_main = nullptr;
|
||||||
|
|
||||||
Result<void> TerminalWidget::init(char* const* args)
|
Result<void> TerminalWidget::init(char* const* args)
|
||||||
{
|
{
|
||||||
m_font = ui::Font::default_font();
|
m_font = ui::Font::default_font();
|
||||||
@ -60,10 +62,17 @@ Result<void> TerminalWidget::init(char* const* args)
|
|||||||
|
|
||||||
fcntl(m_pty, F_SETFL, O_NONBLOCK);
|
fcntl(m_pty, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
os::EventLoop::the().register_fd_listener(m_pty, [this](int, int) { this->process(); });
|
// FIXME: Find a better solution for this. What if the caller needs several TerminalWidgets in one app? We can't
|
||||||
|
// just use a singleton, can we?
|
||||||
|
os::EventLoop::the().register_fd_listener(m_pty, [](int, int) {
|
||||||
|
check(s_main);
|
||||||
|
s_main->process();
|
||||||
|
});
|
||||||
|
|
||||||
m_child_pid = child;
|
m_child_pid = child;
|
||||||
|
|
||||||
|
s_main = this;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user