Skip to content

Commit

Permalink
Merge pull request #128 from linuxdoesitbetter/main
Browse files Browse the repository at this point in the history
Created a new subdirectory for the development of an event loop and a…
  • Loading branch information
gansm committed Jun 5, 2023
2 parents 3dbdeee + 11215d4 commit dc9dd6d
Show file tree
Hide file tree
Showing 13 changed files with 1,115 additions and 0 deletions.
27 changes: 27 additions & 0 deletions final/eventloop/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.18)

project(eventloop)

add_executable(
eventloop
monitor.h
monitor.cpp
timer_monitor.h
timer_monitor.cpp
signal_monitor.h
signal_monitor.cpp
io_monitor.h
io_monitor.cpp
eventloop.h
eventloop.cpp
main.cpp )

#target_compile_options(eventloop PUBLIC -std=c++14 -Wall -Wextra -Wpedantic -Werror )
target_compile_options(eventloop PUBLIC -std=c++14 -Wall -Wextra -Weffc++ -pedantic -pedantic-errors -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimport -Winit-self -Winvalid-pch -Wlong-long -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -fstack-protector -Wstrict-aliasing -Wstrict-aliasing=3 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings -Wsign-promo -Woverloaded-virtual -Wstrict-null-sentinel -fext-numeric-literals -Wreorder -Wnoexcept -Wnarrowing -Wliteral-suffix -Wctor-dtor-privacy -ftree-loop-distribute-patterns -Wmemset-transposed-args -Wno-format-nonliteral )

target_link_libraries(
eventloop
rt
c )

install(TARGETS eventloop RUNTIME DESTINATION bin)
16 changes: 16 additions & 0 deletions final/eventloop/eventloop-class-diagram.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@


┌───────────┐
│ EventLoop │
└─────┬─────┘
: 1 ┌───────────────┐
: ┌───┤ SignalMonitor │
: * │ └───────────────┘
┌────┴────┐ │ ┌──────────────┐
│ Monitor │◄───┼───┤ TimerMonitor │
└─────────┘ │ └──────────────┘
│ ┌───────────┐
└───┤ IoMonitor │
└───────────┘


116 changes: 116 additions & 0 deletions final/eventloop/eventloop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/***********************************************************************
* eventloop.cpp - Implements the event loop *
* *
* This file is part of the FINAL CUT widget toolkit *
* *
* Copyright 2023 Andreas Noe *
* *
* FINAL CUT is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* FINAL CUT is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* <http://www.gnu.org/licenses/>. *
***********************************************************************/

#include <unistd.h>

#include <iostream>

#include "eventloop.h"

// public methods of EventLoop
//----------------------------------------------------------------------
auto EventLoop::run() -> int
{
running = true;

while ( running )
{
nfds_t fd_count = 0;
monitors_changed = false;

for (Monitor* monitor : monitors)
{
if ( monitor->isActive() )
{
fds[fd_count] = { monitor->getFd(), monitor->getEvents(), 0 };
lookup_table[fd_count] = monitor;
fd_count++;
}

if ( fd_count >= MAX_MONITORS )
break;
}

int poll_result{};

while ( true )
{
poll_result = poll(fds, fd_count, -1);

if ( poll_result != -1 || errno != EINTR )
break;
}

if ( poll_result == -1 )
{
std::cerr << "Arghh! " << errno << std::endl;
continue;
}

if ( poll_result <= 0 )
continue;

nfds_t processed_fds{0};

for (nfds_t index{0}; index < fd_count; index++)
{
pollfd& current_fd = fds[index];

if ( current_fd.revents != 0
&& (current_fd.revents & current_fd.events) )
{
lookup_table[index]->trigger(current_fd.revents);

if ( monitors_changed
|| int(++processed_fds) == poll_result
|| ! running )
{
break;
}
}
}
}

return 0;
}

//----------------------------------------------------------------------
void EventLoop::leave()
{
running = false;
}


// private methods of EventLoop
//----------------------------------------------------------------------
void EventLoop::addMonitor (Monitor* monitor)
{
monitors.push_back(monitor);
monitors_changed = true;
}

//----------------------------------------------------------------------
void EventLoop::removeMonitor (Monitor* monitor)
{
monitors.remove(monitor);
monitors_changed = true;
}
68 changes: 68 additions & 0 deletions final/eventloop/eventloop.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/***********************************************************************
* eventloop.h - Implements the event loop *
* *
* This file is part of the FINAL CUT widget toolkit *
* *
* Copyright 2023 Andreas Noe *
* *
* FINAL CUT is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* FINAL CUT is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* <http://www.gnu.org/licenses/>. *
***********************************************************************/

/* Standalone class
* ════════════════
*
* ▕▔▔▔▔▔▔▔▔▔▔▔▏
* ▕ EventLoop ▏
* ▕▁▁▁▁▁▁▁▁▁▁▁▏
*/

#ifndef EVENTLOOP_H
#define EVENTLOOP_H

#include <list>
#include <poll.h>

#include "monitor.h"

class EventLoop
{
public:
// Constructor
EventLoop() = default;

// Methods
auto run() -> int;
void leave();

private:
// Constants
static constexpr nfds_t MAX_MONITORS{50};

// Methods
void addMonitor (Monitor*);
void removeMonitor (Monitor*);

// Data members
bool running{false};
bool monitors_changed{false};
std::list<Monitor*> monitors{};
struct pollfd fds[MAX_MONITORS]{};
Monitor* lookup_table[MAX_MONITORS]{};

// Friend classes
friend class Monitor;
};

#endif // EVENTLOOP_H
46 changes: 46 additions & 0 deletions final/eventloop/io_monitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/***********************************************************************
* io_monitor.cpp - I/O monitoring object *
* *
* This file is part of the FINAL CUT widget toolkit *
* *
* Copyright 2023 Andreas Noe *
* *
* FINAL CUT is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* FINAL CUT is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* <http://www.gnu.org/licenses/>. *
***********************************************************************/

#include <utility>

#include "io_monitor.h"

// constructors and destructor
//----------------------------------------------------------------------
IoMonitor::IoMonitor (EventLoop* eloop)
: Monitor(eloop)
{ }

//----------------------------------------------------------------------
IoMonitor::~IoMonitor() noexcept = default; // destructor


// public methods of IoMonitor
//----------------------------------------------------------------------
void IoMonitor::init ( int file_descriptor, short ev
, handler_t hdl, void* uc )
{
fd = file_descriptor;
events = ev;
handler = std::move(hdl);
user_context = uc;
}
53 changes: 53 additions & 0 deletions final/eventloop/io_monitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/***********************************************************************
* io_monitor.h - I/O monitoring object *
* *
* This file is part of the FINAL CUT widget toolkit *
* *
* Copyright 2023 Andreas Noe *
* *
* FINAL CUT is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* FINAL CUT is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* <http://www.gnu.org/licenses/>. *
***********************************************************************/

/* Inheritance diagram
* ═══════════════════
*
* ▕▔▔▔▔▔▔▔▔▔▏
* ▕ Monitor ▏
* ▕▁▁▁▁▁▁▁▁▁▏
* ▲
* │
* ▕▔▔▔▔▔▔▔▔▔▔▔▏
* ▕ IoMonitor ▏
* ▕▁▁▁▁▁▁▁▁▁▁▁▏
*/

#ifndef IO_MONITOR_H
#define IO_MONITOR_H

#include "monitor.h"

class IoMonitor final : public Monitor
{
public:
// Constructor
IoMonitor() = delete;
explicit IoMonitor (EventLoop*);
~IoMonitor() noexcept override;

// Method
void init (int, short, handler_t, void*);
};

#endif // IO_MONITOR_H
Loading

0 comments on commit dc9dd6d

Please sign in to comment.