Kaynağa Gözat

faux.sched: Fixed periodic event + tests

Serj Kalichev 3 yıl önce
ebeveyn
işleme
bfeec1d587

+ 3 - 3
faux/sched.h

@@ -10,7 +10,7 @@
 #include <faux/time.h>
 
 #define FAUX_SCHED_NOW NULL
-#define FAUX_SCHED_CYCLES_INFINITE (-1)
+#define FAUX_SCHED_INFINITE (unsigned int)(-1l)
 
 typedef enum {
 	FAUX_SCHED_PERIODIC = BOOL_TRUE,
@@ -33,10 +33,10 @@ int faux_sched_once_delayed(faux_sched_t *sched,
 	const struct timespec *interval, int ev_id, void *data);
 int faux_sched_periodic(
 	faux_sched_t *sched, const struct timespec *time, int ev_id, void *data,
-	const struct timespec *period, int cycle_num);
+	const struct timespec *period, unsigned int cycle_num);
 int faux_sched_periodic_delayed(
 	faux_sched_t *sched, int ev_id, void *data,
-	const struct timespec *period, int cycle_num);
+	const struct timespec *period, unsigned int cycle_num);
 int faux_sched_next_interval(faux_sched_t *sched, struct timespec *interval);
 void faux_sched_empty(faux_sched_t *sched);
 int faux_sched_pop(faux_sched_t *sched, int *ev_id, void **data);

+ 20 - 19
faux/sched/ev.c

@@ -3,6 +3,7 @@
  */
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <assert.h>
 
@@ -91,7 +92,7 @@ faux_ev_t *faux_ev_new(const struct timespec *time, int ev_id, void *data)
 	ev->id = ev_id;
 	ev->data = data;
 	ev->periodic = FAUX_SCHED_ONCE; // Not periodic by default
-	ev->cycles_num = 0;
+	ev->cycle_num = 0;
 	faux_nsec_to_timespec(&ev->period, 0l);
 	faux_ev_reschedule(ev, time);
 
@@ -119,20 +120,20 @@ void faux_ev_free(void *ptr)
  *
  * @param [in] ev Allocated and initialized ev object.
  * @param [in] period Period of periodic event.
- * @param [in] cycles_num Number of cycles. FAUX_SHED_CYCLES_INFINITE - infinite.
+ * @param [in] cycle_num Number of cycles. FAUX_SHED_INFINITE - infinite.
  * @return 0 - success, < 0 on error.
  */
 int faux_ev_periodic(faux_ev_t *ev,
-	const struct timespec *period, int cycles_num)
+	const struct timespec *period, unsigned int cycle_num)
 {
 	assert(ev);
 	assert(period);
-	// When cycles_num == 0 then periodic has no meaning
-	if (!ev || !period || cycles_num == 0)
+	// When cycle_num == 0 then periodic has no meaning
+	if (!ev || !period || cycle_num == 0)
 		return -1;
 
 	ev->periodic = FAUX_SCHED_PERIODIC;
-	ev->cycles_num = cycles_num;
+	ev->cycle_num = cycle_num;
 	ev->period = *period;
 
 	return 0;
@@ -159,22 +160,22 @@ faux_sched_periodic_t faux_ev_is_periodic(faux_ev_t *ev)
  * On every completed cycle the internal cycles counter must be decremented.
  *
  * @param [in] ev Allocated and initialized ev object.
- * @param [out] new_cycles_num Returns new number of cycles. Can be NULL.
+ * @param [out] new_cycle_num Returns new number of cycles. Can be NULL.
  * @return FAUX_SCHED_PERIODIC - periodic, FAUX_SCHED_ONCE - non-periodic.
  */
-int faux_ev_dec_cycles(faux_ev_t *ev, int *new_cycles_num)
+int faux_ev_dec_cycles(faux_ev_t *ev, unsigned int *new_cycle_num)
 {
 	assert(ev);
 	if (!ev)
 		return -1;
-	if (ev->periodic != FAUX_SCHED_PERIODIC)
+	if (!faux_ev_is_periodic(ev))
 		return -1; // Non-periodic event
-	if ((ev->cycles_num != FAUX_SCHED_CYCLES_INFINITE) &&
-		(ev->cycles_num > 0))
-		ev->cycles_num--;
+	if ((ev->cycle_num != FAUX_SCHED_INFINITE) &&
+		(ev->cycle_num > 0))
+		ev->cycle_num--;
 
-	if (new_cycles_num)
-		*new_cycles_num = ev->cycles_num;
+	if (new_cycle_num)
+		*new_cycle_num = ev->cycle_num;
 
 	return 0;
 }
@@ -207,7 +208,7 @@ int faux_ev_reschedule(faux_ev_t *ev, const struct timespec *new_time)
  *
  * New scheduled time is calculated as "now" + "period".
  * Function decrements number of cycles. If number of cycles is
- * FAUX_SCHED_CYCLES_INFINITE then number of cycles will not be decremented.
+ * FAUX_SCHED_INFINITE then number of cycles will not be decremented.
  *
  * @param [in] ev Allocated and initialized ev object.
  * @return 0 - success, < 0 on error.
@@ -219,15 +220,15 @@ int faux_ev_reschedule_period(faux_ev_t *ev)
 	assert(ev);
 	if (!ev)
 		return -1;
-	if (ev->periodic != FAUX_SCHED_PERIODIC)
-		return -1;
-	if (0 == ev->cycles_num)
+	if (!faux_ev_is_periodic(ev))
 		return -1;
+	if (ev->cycle_num <= 1)
+		return -1; // We don't need to reschedule if last cycle left
 
 	faux_timespec_sum(&new_time, &ev->time, &ev->period);
 	faux_ev_reschedule(ev, &new_time);
 
-	if (ev->cycles_num != FAUX_SCHED_CYCLES_INFINITE)
+	if (ev->cycle_num != FAUX_SCHED_INFINITE)
 		faux_ev_dec_cycles(ev, NULL);
 
 	return 0;

+ 3 - 3
faux/sched/private.h

@@ -7,7 +7,7 @@
 struct faux_ev_s {
 	struct timespec time; // Planned time of event
 	struct timespec period; // Period for periodic event
-	int cycles_num; // Number of cycles for periodic event
+	unsigned int cycle_num; // Number of cycles for periodic event
 	faux_sched_periodic_t periodic; // Periodic flag
 	int id; // Type of event
 	void *data; // Arbitrary data linked to event
@@ -28,8 +28,8 @@ faux_ev_t *faux_ev_new(const struct timespec *time, int ev_id, void *data);
 void faux_ev_free(void *ptr);
 
 int faux_ev_periodic(faux_ev_t *ev,
-	const struct timespec *interval, int cycles_num);
-int faux_ev_dec_cycles(faux_ev_t *ev, int *new_cycles_num);
+	const struct timespec *interval, unsigned int cycle_num);
+int faux_ev_dec_cycles(faux_ev_t *ev, unsigned int *new_cycle_num);
 int faux_ev_reschedule(faux_ev_t *ev, const struct timespec *new_time);
 int faux_ev_reschedule_period(faux_ev_t *ev);
 int faux_ev_time_left(faux_ev_t *ev, struct timespec *left);

+ 6 - 6
faux/sched/sched.c

@@ -96,12 +96,12 @@ static int _sched_ev(faux_sched_t *sched, faux_ev_t *ev)
  * @param [in] data Pointer to arbitrary data linked to event.
  * @param [in] periodic Periodic flag.
  * @param [in] period Periodic interval.
- * @param [in] cycles_num Number of cycles (FAUX_SCHED_CYCLES_INFINITE for infinite).
+ * @param [in] cycle_num Number of cycles (FAUX_SCHED_INFINITE for infinite).
  * @return 0 - success, < 0 on error.
  */
 static int _sched(faux_sched_t *sched, const struct timespec *time,
 	int ev_id, void *data, faux_sched_periodic_t periodic,
-	const struct timespec *period, int cycles_num)
+	const struct timespec *period, unsigned int cycle_num)
 {
 	faux_ev_t *ev = NULL;
 
@@ -110,7 +110,7 @@ static int _sched(faux_sched_t *sched, const struct timespec *time,
 	if (!ev)
 		return -1;
 	if (FAUX_SCHED_PERIODIC == periodic)
-		faux_ev_periodic(ev, period, cycles_num);
+		faux_ev_periodic(ev, period, cycle_num);
 
 	if (_sched_ev(sched, ev) < 0) { // Something went wrong
 		faux_ev_free(ev);
@@ -179,10 +179,10 @@ int faux_sched_once_delayed(faux_sched_t *sched,
  */
 int faux_sched_periodic(
 	faux_sched_t *sched, const struct timespec *time, int ev_id, void *data,
-	const struct timespec *period, int cycle_num)
+	const struct timespec *period, unsigned int cycle_num)
 {
 	return _sched(sched, time, ev_id, data,
-		FAUX_SCHED_ONCE, period, cycle_num);
+		FAUX_SCHED_PERIODIC, period, cycle_num);
 }
 
 
@@ -197,7 +197,7 @@ int faux_sched_periodic(
  */
 int faux_sched_periodic_delayed(
 	faux_sched_t *sched, int ev_id, void *data,
-	const struct timespec *period, int cycle_num)
+	const struct timespec *period, unsigned int cycle_num)
 {
 	struct timespec now = {};
 	struct timespec plan = {};

+ 139 - 11
faux/sched/testc_sched.c

@@ -7,7 +7,7 @@
 #include "faux/time.h"
 #include "faux/sched.h"
 
-int testc_faux_sched(void)
+int testc_faux_sched_once(void)
 {
 	faux_sched_t *sched = NULL;
 	long long int nsec = 500000000l;
@@ -28,8 +28,20 @@ int testc_faux_sched(void)
 	if (!sched)
 		return -1;
 
-	// Wait and get event
+	// Schedule event
 	faux_sched_once(sched, &t, id, str);
+	// Don't wait so pop must return -1
+	if (faux_sched_pop(sched, &e_id, &e_str) == 0)
+		return -1;
+	// Get next event interval. It must be greater than 0 and greater
+	// than full interval (half of second)
+	if (faux_sched_next_interval(sched, &twait) < 0)
+		return -1;
+	if (faux_timespec_cmp(&twait, &(struct timespec){0, 0}) <= 0)
+		return -1;
+	if (faux_timespec_cmp(&twait, &pol_s) >= 0)
+		return -1;
+	// Wait and get event
 	nanosleep(&pol_s, NULL); // wait
 	if (faux_sched_pop(sched, &e_id, &e_str) < 0)
 		return -1;
@@ -38,20 +50,136 @@ int testc_faux_sched(void)
 	if (e_str != str)
 		return -1;
 
+	// Schedule event delayed
+	faux_sched_once(sched, &pol_s, id, str);
+	// Wait and get event
+	nanosleep(&pol_s, NULL); // wait
+	e_id = 0;
+	e_str = NULL;
+	if (faux_sched_pop(sched, &e_id, &e_str) < 0)
+		return -1;
+	if (e_id != id)
+		return -1;
+	if (e_str != str)
+		return -1;
+
+	faux_sched_free(sched);
+
+	return 0;
+}
+
+
+int testc_faux_sched_periodic(void)
+{
+	faux_sched_t *sched = NULL;
+	long long int nsec = 500000000l;
+	struct timespec pol_s = {}; // One half of second
+	struct timespec now = {};
+	struct timespec t = {};
+	int id = 78;
+	char *str = "test";
+	int e_id = 0;
+	void *e_str = NULL;
+
+	faux_nsec_to_timespec(&pol_s, nsec);
+	faux_timespec_now(&now);
+	faux_timespec_sum(&t, &now, &pol_s);
+
+	sched = faux_sched_new();
+	if (!sched)
+		return -1;
+
+	// Schedule event
+	faux_sched_periodic_delayed(sched, id, str, &pol_s, 2);
 	// Don't wait so pop must return -1
-	faux_timespec_sum(&t, &t, &pol_s);
-	faux_sched_once(sched, &t, id, str);
-	// Don't wait. Pop must return -1
-	if (faux_sched_pop(sched, &e_id, &e_str) == 0)
+	if (faux_sched_pop(sched, &e_id, &e_str) == 0) {
+		printf("faux_shed_pop: Immediately event\n");
 		return -1;
-	// Get next event interval. It must be greater than 0 and greater
-	// than full interval (half of second)
-	if (faux_sched_next_interval(sched, &twait) < 0)
+	}
+	// Wait and get one event
+	nanosleep(&pol_s, NULL); // wait
+	if (faux_sched_pop(sched, &e_id, &e_str) < 0) {
+		printf("faux_shed_pop: Can't get 1/2 event\n");
 		return -1;
-	if (faux_timespec_cmp(&twait, &(struct timespec){0, 0}) <= 0)
+	}
+	if (e_id != id)
 		return -1;
-	if (faux_timespec_cmp(&twait, &pol_s) >= 0)
+	if (e_str != str)
+		return -1;
+	if (faux_sched_pop(sched, &e_id, &e_str) == 0) { // another event?
+		printf("faux_shed_pop: Two events at once\n");
+		return -1;
+	}
+	nanosleep(&pol_s, NULL); // wait next time
+	if (faux_sched_pop(sched, &e_id, &e_str) < 0) {
+		printf("faux_shed_pop: Can't get 2/2 event\n");
+		return -1;
+	}
+	nanosleep(&pol_s, NULL); // wait third time
+	if (faux_sched_pop(sched, &e_id, &e_str) == 0) { // no events any more
+		printf("faux_shed_pop: The 3/2 event\n");
+		return -1;
+	}
+
+	faux_sched_free(sched);
+
+	return 0;
+}
+
+
+int testc_faux_sched_infinite(void)
+{
+	faux_sched_t *sched = NULL;
+	long long int nsec = 500000000l;
+	struct timespec pol_s = {}; // One half of second
+	struct timespec now = {};
+	struct timespec t = {};
+	int id = 78;
+	char *str = "test";
+	int e_id = 0;
+	void *e_str = NULL;
+
+	faux_nsec_to_timespec(&pol_s, nsec);
+	faux_timespec_now(&now);
+	faux_timespec_sum(&t, &now, &pol_s);
+
+	sched = faux_sched_new();
+	if (!sched)
+		return -1;
+
+	// Schedule event
+	faux_sched_periodic_delayed(sched, id, str, &pol_s,
+		FAUX_SCHED_INFINITE);
+	// Don't wait so pop must return -1
+	if (faux_sched_pop(sched, &e_id, &e_str) == 0) {
+		printf("faux_shed_pop: Immediately event\n");
+		return -1;
+	}
+	// Wait and get one event
+	nanosleep(&pol_s, NULL); // wait
+	if (faux_sched_pop(sched, &e_id, &e_str) < 0) {
+		printf("faux_shed_pop: Can't get 1 event\n");
+		return -1;
+	}
+	if (e_id != id)
+		return -1;
+	if (e_str != str)
+		return -1;
+	if (faux_sched_pop(sched, &e_id, &e_str) == 0) { // another event?
+		printf("faux_shed_pop: Two events at once\n");
+		return -1;
+	}
+	nanosleep(&pol_s, NULL); // wait next time
+	if (faux_sched_pop(sched, &e_id, &e_str) < 0) {
+		printf("faux_shed_pop: Can't get 2 event\n");
+		return -1;
+	}
+	faux_sched_empty(sched); // Empty the list
+	nanosleep(&pol_s, NULL); // wait third time
+	if (faux_sched_pop(sched, &e_id, &e_str) == 0) {
+		printf("faux_shed_pop: Event after empty operation\n");
 		return -1;
+	}
 
 	faux_sched_free(sched);
 

+ 3 - 1
faux/testc_module/testc_module.c

@@ -27,7 +27,9 @@ const char *testc_module[][2] = {
 	{"testc_faux_timespec_now", "Timespec now and before now functions"},
 
 	// sched
-	{"testc_faux_sched", "Scheduling of events"},
+	{"testc_faux_sched_once", "Schedule once event. Simple and delayed ones."},
+	{"testc_faux_sched_periodic", "Schedule periodic event."},
+	{"testc_faux_sched_infinite", "Schedule infinite number of events."},
 
 	// log
 	{"testc_faux_log_facility_id", "Converts syslog facility string to id"},