-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: refactor lib to be header-only
- Loading branch information
Showing
26 changed files
with
803 additions
and
900 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
add_compile_definitions(USE_KQUEUE) | ||
|
||
add_executable(fibers fibers.cpp) | ||
target_link_libraries(fibers PRIVATE libflux) | ||
target_link_libraries(fibers PRIVATE loom) | ||
|
||
add_executable(monitor monitor.cpp) | ||
target_link_libraries(monitor PRIVATE loom) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,27 @@ | ||
#include <cstdio> | ||
#include <fcntl.h> | ||
#include <iostream> | ||
|
||
#include "tracy/Tracy.hpp" | ||
#include "tracy/TracyC.h" | ||
|
||
#include "flux/backends/darwin.hpp" | ||
#include "flux/thread.hpp" | ||
#include "loom/fiber.hpp" | ||
|
||
using namespace std; | ||
|
||
#ifdef __APPLE__ | ||
#define SOCK_NONBLOCK O_NONBLOCK | ||
#endif | ||
|
||
#define DEFAULT_STACK_SIZE 4096 | ||
|
||
struct Worker : flux::Thread { | ||
explicit Worker(size_t _stack_size) : Thread(_stack_size) {} | ||
void run() override { | ||
int count = 0; | ||
int thing = 0; | ||
while (count < 100) { | ||
count++; | ||
thing = (thing * 7 + count) / 8; | ||
printf("count: %d\n", count); | ||
this->wait(); | ||
FrameMark; | ||
struct Worker : loom::Fiber { | ||
explicit Worker(size_t stack_size) : loom::Fiber(stack_size) {} | ||
void run() { | ||
int thing = 0; | ||
for (int i = 0; i < 100; ++i) { | ||
thing = (thing * 7 + i) / 8; | ||
printf("count: %d\n", i); | ||
this->wait(); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
void *print(void *args) { | ||
int i = 0; | ||
while (i++) { | ||
std::cout << i << ": hello world\n"; | ||
} | ||
} | ||
|
||
int main() { | ||
// // Create a new context and stack to execute foo. Pass the stack pointer to the end, | ||
// // stack grows downwards for most architecture, from highest mem address -> lowest | ||
// Worker worker(DEFAULT_STACK_SIZE); // need to heap allocate | ||
// worker.start(); | ||
// flux::Event fake{flux::Event::Type::NA, 0}; | ||
// | ||
// flux::KqueueReactor reactor; | ||
// reactor.set_timer(1010, 1500, &worker); | ||
// // reactor.subscribe(1010, &worker); | ||
// tracy::SetThreadName("hello"); | ||
// | ||
// while (reactor.active()) { | ||
// reactor.work(); | ||
// FrameMark; | ||
// } | ||
Worker worker(4096); | ||
worker.start(); | ||
loom::Event fake{loom::Event::Type::NA, 0}; | ||
|
||
flux::fiber_t f1; | ||
flux::fiber_init(f1, nullptr, print, nullptr); | ||
while (worker.resume(&fake)) { | ||
cout << "Resuming worker" << endl; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include <iostream> | ||
|
||
int main() { | ||
// Make this example open a file, and read for file changes and print it out! | ||
// Maybe can do a diff also, and then grab the diffs, and print it out | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
cmake_minimum_required(VERSION 3.9) | ||
project(loom) | ||
include(FetchContent) | ||
|
||
set(CMAKE_CXX_STANDARD 20) | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
||
# Boost | ||
find_package(Boost COMPONENTS context REQUIRED) | ||
message(STATUS "Boost include dir: ${Boost_INCLUDE_DIRS}") | ||
|
||
# Tracy | ||
option(TRACY_ENABLE "" ON) | ||
option(TRACY_FIBERS "" ON) # pdf page 38 | ||
|
||
FetchContent_Declare( | ||
tracy | ||
GIT_REPOSITORY https://github.com/wolfpld/tracy.git | ||
GIT_TAG master | ||
GIT_SHALLOW TRUE | ||
GIT_PROGRESS TRUE | ||
) | ||
FetchContent_MakeAvailable(tracy) | ||
|
||
# Quill | ||
FetchContent_Declare( | ||
quill | ||
GIT_REPOSITORY https://github.com/odygrd/quill.git | ||
GIT_TAG master | ||
GIT_SHALLOW TRUE | ||
GIT_PROGRESS TRUE | ||
) | ||
FetchContent_MakeAvailable(quill) | ||
|
||
# sockpp | ||
FetchContent_Declare( | ||
sockpp | ||
GIT_REPOSITORY https://github.com/fpagliughi/sockpp | ||
GIT_TAG master | ||
GIT_SHALLOW TRUE | ||
GIT_PROGRESS TRUE | ||
) | ||
FetchContent_MakeAvailable(sockpp) | ||
message(STATUS "sockpp include dir: ${sockpp_SOURCE_DIR}/include") | ||
|
||
option(USE_EPOLL "" OFF) | ||
option(USE_KQUEUE "" ON) | ||
|
||
if ((NOT USE_EPOLL AND NOT USE_KQUEUE) OR (USE_EPOLL AND USE_KQUEUE)) | ||
message(FATAL_ERROR "Please select one backend: epoll or kqueue") | ||
endif () | ||
|
||
|
||
# add the library | ||
add_library(${PROJECT_NAME} INTERFACE) | ||
target_include_directories(${PROJECT_NAME} INTERFACE include ${Boost_INCLUDE_DIRS}) | ||
if (USE_EPOLL) | ||
message(STATUS "LOOM: Using epoll backend") | ||
target_compile_definitions(${PROJECT_NAME} INTERFACE LOOM_BACKEND_EPOLL) | ||
elseif (USE_KQUEUE) | ||
message(STATUS "LOOM: Using kqueue backend") | ||
target_compile_definitions(${PROJECT_NAME} INTERFACE LOOM_BACKEND_KQUEUE) | ||
endif () | ||
|
||
target_link_libraries(${PROJECT_NAME} INTERFACE ${Boost_LIBRARIES} Tracy::TracyClient quill::quill sockpp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#pragma once | ||
|
||
#include "loom/loom.hpp" | ||
#include "loom/utils.hpp" | ||
|
||
namespace loom { | ||
|
||
Loom::Loom() { | ||
m_kqueue_fd = kqueue(); | ||
FLUX_ASSERT(m_kqueue_fd != -1, "Failed to create kqueue"); | ||
} | ||
|
||
Loom::~Loom() { | ||
if (m_kqueue_fd >= 0) { | ||
close(m_kqueue_fd); | ||
} | ||
} | ||
|
||
void Loom::handle_sock_op(int fd, loom::Operation op) { | ||
#ifndef NDEBUG | ||
FLUX_ASSERT(m_kqueue_fd >= 0, "Kqueue file descriptor is invalid"); | ||
#endif | ||
|
||
if (m_changes.size() == 16) [[unlikely]] { | ||
// `changelist` is full, need to flush the changes to the kernel. | ||
int n = | ||
kevent(m_kqueue_fd, m_changes.data(), m_changes.size(), nullptr, 0, nullptr); | ||
FLUX_ASSERT(n >= 0, "Failed to flush changes to the kernel"); | ||
m_changes.clear(); | ||
} | ||
// EV_ADD attaches descriptor to kq | ||
// EV_CLEAR prevents unnecessary signalling | ||
struct kevent ev1 {}; | ||
struct kevent ev2 {}; | ||
switch (op) { | ||
case Operation::Added: { | ||
// Add RW flags to Operation as well | ||
// Add a new kevent to the vector | ||
EV_SET(&ev1, fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, nullptr); | ||
EV_SET(&ev2, fd, EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, nullptr); | ||
m_changes.push_back(ev1); | ||
m_changes.push_back(ev2); | ||
break; | ||
} | ||
case Operation::Removed: | ||
EV_SET(&ev1, fd, EVFILT_READ, EV_DELETE, 0, 0, nullptr); | ||
EV_SET(&ev2, fd, EVFILT_WRITE, EV_DELETE, 0, 0, nullptr); | ||
break; | ||
case Operation::Modified: [[fallthrough]]; | ||
case Operation::NIL: break; | ||
} | ||
} | ||
|
||
//! This is one epoch of the event loop. Checks all the fds monitored by the event loop | ||
//! and dispatches any events accordingly. | ||
bool Loom::epoch() { | ||
// TODO: 16 can be adjusted based on busy-ness of the event loop. Can even be dynamic | ||
std::array<struct kevent, 16> events{}; | ||
|
||
// changelist: List of events to register with the kernel | ||
// nchanges: Number of events in the changelist | ||
// `m_timeout` must be non-empty if we want to also monitor SPSC queues for example | ||
// `m_timeout` == 0 degrades the performance to a regular poll event loop | ||
int n = kevent(m_kqueue_fd, m_changes.data(), m_changes.size(), events.data(), | ||
events.size(), m_timeout); | ||
|
||
// `kevent` can be interrupted by signals, so we check `errno` global variable. | ||
if (n < 0 || errno == EINTR) | ||
return false; | ||
|
||
for (int i = 0; i < n; ++i) { | ||
if (events[i].flags & EV_ERROR) { | ||
printf("Error event\n"); | ||
} | ||
if (events[i].filter == EVFILT_READ) { | ||
printf("Read event\n"); | ||
this->notify(Event{.type = Event::Type::SocketRead, | ||
.fd = static_cast<int>(events[i].ident)}); | ||
} else if (events[i].filter == EVFILT_WRITE) { | ||
printf("Write event\n"); | ||
this->notify(Event{.type = Event::Type::SocketWriteable, | ||
.fd = static_cast<int>(events[i].ident)}); | ||
} else if (events[i].filter == EVFILT_TIMER) { | ||
printf("Timer event\n"); | ||
this->notify(Event{.type = Event::Type::Timer, | ||
.fd = static_cast<int>(events[i].ident)}); | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
void Loom::set_timer(int id, int timer_period) { | ||
FLUX_ASSERT(m_kqueue_fd >= 0, "Kqueue file descriptor is invalid"); | ||
struct kevent ev {}; | ||
EV_SET(&ev, id, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, timer_period, nullptr); | ||
int n = kevent(m_kqueue_fd, &ev, 1, nullptr, 0, nullptr); | ||
FLUX_ASSERT(n >= 0, "Failed to set timer"); | ||
} | ||
} /* namespace loom */ |
Oops, something went wrong.