- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1
Feature: carrow_asap & related functions #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -34,6 +34,9 @@ static struct sigaction old_action; | |
| static unsigned int _openmax; | ||
| static struct evbag **_evbags; | ||
| static volatile unsigned int _evbagscount; | ||
| static unsigned int _asapsmax; | ||
| static struct asapbag **_asapbags; | ||
| static volatile unsigned int _asapbagscount; | ||
| static int _epollfd = -1; | ||
|  | ||
|  | ||
|  | @@ -44,6 +47,12 @@ struct evbag { | |
| }; | ||
|  | ||
|  | ||
| struct asapbag { | ||
| carrow_asapfunc func; | ||
| void *params; | ||
| }; | ||
|  | ||
|  | ||
| #define EVBAG_HAS(fd) (_evbags[fd] != NULL) | ||
| #define EVBAG_ISNULL(fd) (_evbags[fd] == NULL) | ||
|  | ||
|  | @@ -169,8 +178,73 @@ evbags_deinit() { | |
| } | ||
|  | ||
|  | ||
| static int | ||
| asapbags_init() { | ||
| _asapbagscount = 0; | ||
| _asapbags = calloc(_asapsmax, sizeof(struct asapbag*)); | ||
| if (_asapbags == NULL) { | ||
| errno = ENOMEM; | ||
| return -1; | ||
| } | ||
|  | ||
| memset(_asapbags, 0, sizeof(struct asapbag*) * _asapsmax); | ||
| return 0; | ||
| } | ||
|  | ||
|  | ||
| static void | ||
| asapbags_deinit() { | ||
| for (int i = 0; i < _asapsmax; i++) { | ||
| if (_asapbags[i] != NULL) { | ||
| free(_asapbags[i]); | ||
| _asapbags[i] = NULL; | ||
| } | ||
| } | ||
|  | ||
| free(_asapbags); | ||
| _asapbags = NULL; | ||
| } | ||
|  | ||
|  | ||
| static void | ||
| asap_trigger() { | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ues  | ||
| for(int i = 0; i < _asapbagscount; i++) { | ||
| struct asapbag *bag = _asapbags[i]; | ||
| bag->func(bag->params); | ||
| } | ||
| _asapbagscount = 0; | ||
| } | ||
|  | ||
|  | ||
| int | ||
| carrow_init(unsigned int openmax) { | ||
| carrow_asap_register(carrow_asapfunc func, void *params) { | ||
| if (_asapsmax == 0) { | ||
| return -1; | ||
| } | ||
|  | ||
| if (_asapbagscount >= _asapsmax) { | ||
| return -1; | ||
| } | ||
| struct asapbag *bag = _asapbags[_asapbagscount]; | ||
|  | ||
| if (bag == NULL) { | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Always happening situation.  | ||
| bag = malloc(sizeof(struct asapbag)); | ||
| if (bag == NULL) { | ||
| errno = ENOMEM; | ||
| return -1; | ||
| } | ||
| _asapbags[_asapbagscount] = bag; | ||
| } | ||
|  | ||
| bag->func = func; | ||
| bag->params = params; | ||
| _asapbagscount++; | ||
| return 0; | ||
| } | ||
|  | ||
|  | ||
| int | ||
| carrow_init(unsigned int openmax, unsigned int asapsmax) { | ||
| if (_epollfd != -1) { | ||
| return -1; | ||
| } | ||
|  | @@ -191,6 +265,14 @@ carrow_init(unsigned int openmax) { | |
| return -1; | ||
| } | ||
|  | ||
| _asapsmax = asapsmax; | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Get or set it by two accessors: int
carrow_asapmax_get();
void
carrow_asapmax_set(int count); | ||
| if (_asapsmax > 0) { | ||
| if (asapbags_init()) { | ||
| evbags_deinit(); | ||
| return -1; | ||
| } | ||
| } | ||
|  | ||
| _epollfd = epoll_create1(0); | ||
| if (_epollfd < 0) { | ||
| return -1; | ||
|  | @@ -314,6 +396,10 @@ carrow_evloop(volatile int *status) { | |
|  | ||
| evloop: | ||
| while (_evbagscount && ((status == NULL) || (*status > EXIT_FAILURE))) { | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check  | ||
| if (_asapbagscount > 0) { | ||
| asap_trigger(); | ||
| } | ||
|  | ||
| errno = 0; | ||
| nfds = epoll_wait(_epollfd, events, _openmax, -1); | ||
| if (nfds < 0) { | ||
|  | @@ -351,5 +437,10 @@ carrow_deinit() { | |
| close(_epollfd); | ||
| _epollfd = -1; | ||
| evbags_deinit(); | ||
|  | ||
| if (_asapsmax > 0) { | ||
| asapbags_deinit(); | ||
| } | ||
|  | ||
| errno = 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -124,10 +124,14 @@ struct carrow_generic_coro { | |
| typedef void (*carrow_generic_corofunc) (void *coro, void *state); | ||
|  | ||
|  | ||
| /* A function pointer type representing a carrow asap function */ | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not define it. | ||
| typedef void (*carrow_asapfunc) (void *params); | ||
|  | ||
|  | ||
| /* A function that initializes the event loop with the given maximum number | ||
| of file descriptors. */ | ||
| int | ||
| carrow_init(unsigned int openmax); | ||
| carrow_init(unsigned int openmax, unsigned int asapsmax); | ||
|  | ||
|  | ||
| /* A function that frees the memory allocated for the _evbags array. */ | ||
|  | @@ -165,6 +169,10 @@ int | |
| carrow_evloop_unregister(int fd); | ||
|  | ||
|  | ||
| int | ||
| carrow_asap_register(carrow_asapfunc func, void *params); | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The signature must be similar to carrow_evloop_register. | ||
|  | ||
|  | ||
| /* A function that runs the event loop until the _evbagscount is zero or | ||
| the status is set to a value less than or equal to EXIT_FAILURE. | ||
| It waits for events on the epoll instance and triggers thecorresponding | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -100,10 +100,10 @@ CARROW_NAME(evloop_unregister) (int fd) { | |
|  | ||
| int | ||
| CARROW_NAME(forever) (CARROW_NAME(corofunc) f, CARROW_ENTITY *state, | ||
| volatile int *status) { | ||
| volatile int *status, unsigned int asapsmax) { | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 
 | ||
| int ret = EXIT_SUCCESS; | ||
|  | ||
| carrow_init(0); | ||
| carrow_init(0, asapsmax); | ||
| CARROW_NAME(coro_create_and_run) (f, state); | ||
| if (carrow_evloop(status)) { | ||
| ret = EXIT_FAILURE; | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -65,5 +65,5 @@ main() { | |
| .counter = 0 | ||
| }; | ||
|  | ||
| return foo_forever(fooA, &state, NULL); | ||
| return foo_forever(fooA, &state, NULL, 0); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| // Copyright 2023 Vahid Mardani | ||
| /* | ||
| * This file is part of Carrow. | ||
| * Carrow is free software: you can redistribute it and/or modify it under | ||
| * the terms of the GNU General Public License as published by the Free | ||
| * Software Foundation, either version 3 of the License, or (at your option) | ||
| * any later version. | ||
| * | ||
| * Carrow 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 General Public License for more | ||
| * details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License along | ||
| * with Carrow. If not, see <https://www.gnu.org/licenses/>. | ||
| * | ||
| * Author: Vahid Mardani <[email protected]> | ||
| */ | ||
| #include <sys/timerfd.h> | ||
| #include <stdlib.h> | ||
| #include <unistd.h> | ||
|  | ||
| #include <clog.h> | ||
|  | ||
| #include "carrow.h" | ||
|  | ||
|  | ||
| typedef struct timer { | ||
| unsigned int interval; | ||
| unsigned long value; | ||
| const char *title; | ||
| } timer; | ||
|  | ||
|  | ||
| #undef CARROW_ENTITY | ||
| #define CARROW_ENTITY timer | ||
| #include "carrow_generic.h" | ||
| #include "carrow_generic.c" | ||
|  | ||
|  | ||
| static int | ||
| maketimer(unsigned int interval) { | ||
| int fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); | ||
| if (fd == -1) { | ||
| return -1; | ||
| } | ||
|  | ||
| struct timespec sec1 = {interval, 0}; | ||
| struct itimerspec spec = {sec1, sec1}; | ||
| if (timerfd_settime(fd, 0, &spec, NULL) == -1) { | ||
| return -1; | ||
| } | ||
| return fd; | ||
| } | ||
|  | ||
|  | ||
| static void | ||
| timer_asapfunc(int value) { | ||
| INFO("called from asapfunction value: %d", value); | ||
| } | ||
|  | ||
|  | ||
| static void | ||
| timerA(struct timer_coro *self, struct timer *state) { | ||
| CORO_START; | ||
| unsigned long tmp; | ||
| ssize_t bytes; | ||
|  | ||
| self->fd = maketimer(state->interval); | ||
| if (self->fd == -1) { | ||
| CORO_REJECT("maketimer"); | ||
| } | ||
|  | ||
| while (true) { | ||
| CORO_WAIT(self->fd, CIN); | ||
| bytes = read(self->fd, &tmp, sizeof(tmp)); | ||
| state->value += tmp; | ||
| INFO("%s, fd: %d, value: %lu", state->title, self->fd, state->value); | ||
|  | ||
| if (state->value % 5 == 0) { | ||
| INFO("registering to asap"); | ||
| carrow_asap_register((carrow_asapfunc)timer_asapfunc, | ||
| (void *) state->value); | ||
| } | ||
| } | ||
|  | ||
| CORO_FINALLY; | ||
| if (self->fd != -1) { | ||
| timer_evloop_unregister(self->fd); | ||
| close(self->fd); | ||
| } | ||
| CORO_END; | ||
| } | ||
|  | ||
|  | ||
| int | ||
| main() { | ||
| clog_verbosity = CLOG_DEBUG; | ||
|  | ||
| if (carrow_handleinterrupts()) { | ||
| return EXIT_FAILURE; | ||
| } | ||
|  | ||
| struct timer state1 = { | ||
| .title = "Foo", | ||
| .interval = 1, | ||
| .value = 0, | ||
| }; | ||
| struct timer state2 = { | ||
| .title = "Bar", | ||
| .interval = 3, | ||
| .value = 0, | ||
| }; | ||
| if (carrow_init(0, 10)) { | ||
| ERROR("unable to init carrow"); | ||
| return EXIT_FAILURE; | ||
| } | ||
|  | ||
| INFO("CARROW INIT"); | ||
| timer_coro_create_and_run(timerA, &state1); | ||
| //timer_coro_create_and_run(timerA, &state2); | ||
| carrow_evloop(NULL); | ||
| carrow_deinit(); | ||
|  | ||
| return EXIT_SUCCESS; | ||
| } | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
struct evbaginstead. We need to schedule coroutines to run as soon as possible.