librfn
An ad-hoc utility library
fibredemo.c
Go to the documentation of this file.
1 /*
2  * fibredemo.c
3  *
4  * Part of librfn (a general utility library from redfelineninja.org.uk)
5  *
6  * Copyright (C) 2013 Daniel Thompson <daniel@redfelineninja.org.uk>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published
10  * by the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  */
13 
14 #include <assert.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include "librfn.h"
19 
20 
21 typedef union {
25  } id;
26 
27  /* all the remaining event structures must commence with enum
28  * update_event_id to ensure we never clobber the event id.
29  */
30 
31  struct {
32  enum update_event_id id;
33  unsigned int minutes;
34  unsigned int seconds;
35  } time;
36 
37  struct {
38  enum update_event_id id;
39  int status;
40  } exit;
42 
44 {
45  fibre_eventq_t *evtq = containerof(fibre, fibre_eventq_t, fibre);
46 
47  PT_BEGIN_FIBRE(fibre);
48 
49  while (true) {
50  update_event_t *evt;
51 
52  /* wait until we receive an event to act upon */
53  PT_WAIT_UNTIL(NULL != (evt = fibre_eventq_receive(evtq)));
54 
55  /* react to the event */
56  switch(evt->id) {
57  case UPDATE_EVENT_TIME:
58  printf("\r%02d:%02d", evt->time.minutes,
59  evt->time.seconds);
60  fflush(stdout);
61  break;
62  case UPDATE_EVENT_EXIT:
63  printf("\n\nTime is up\n");
64  exit(evt->exit.status);
65  break;
66  default:
67  assert(0);
68  break;
69  }
70 
71  /* the eventq is zero-copy so we must let it know when we
72  * have finished with the event.
73  */
74  fibre_eventq_release(evtq, evt);
75  }
76 
77  PT_END();
78 }
79 
82  update_handler, update_eventq, sizeof(update_eventq),
83  sizeof(update_eventq[0]));
84 
85 
86 typedef struct {
87  uint32_t time;
88  unsigned int minutes;
89  unsigned int seconds;
90  unsigned int exit_after_minutes;
91  unsigned int exit_after_seconds;
94 
96 {
97  stopwatch_fibre_t *clock = containerof(fibre, stopwatch_fibre_t, fibre);
98 
99  PT_BEGIN_FIBRE(fibre);
100 
101  /* initialize the duetime from the current time (making this the the
102  * time from which the stopwatch will measure time)
103  */
104  clock->time = time_now();
105 
106  while (true) {
107  update_event_t *evt;
108 
109  /* send the current time to the event handler */
110  if (NULL != (evt = fibre_eventq_claim(&updater))) {
111  evt->id = UPDATE_EVENT_TIME;
112  evt->time.minutes = clock->minutes;
113  evt->time.seconds = clock->seconds;
114  (void) fibre_eventq_send(&updater, evt);
115  }
116  /* "error handling" usually comes from errors being logged as
117  * scheduler "taints"
118  */
119 
120  /* has the stopwatch expired? */
121  if ((clock->exit_after_minutes || clock->exit_after_seconds) &&
122  clock->exit_after_minutes <= clock->minutes &&
123  clock->exit_after_seconds <= clock->seconds &&
124  NULL != (evt = fibre_eventq_claim(&updater))) {
125  evt->id = UPDATE_EVENT_EXIT;
126  evt->exit.status = 0;
127  (void) fibre_eventq_send(&updater, evt);
128  }
129 
130  /* increment the duetime by a second and wait for the duetime
131  * to expire.
132  */
133  clock->time += 1000000;
135 
136  /* update the recorded time */
137  clock->seconds += 1;
138  if (clock->seconds >= 60) {
139  clock->seconds = 0;
140  clock->minutes += 1;
141  }
142  }
143 
144  PT_END();
145 }
146 
149 };
150 
151 int main(int argc, char *argv[])
152 {
153  switch(argc) {
154  int n;
155  case 0:
156  case 1:
157  // do nothing
158  break;
159  default:
160  fprintf(stderr, "Too many arguments - "
161  "all except '%s' will be ignored\n", argv[1]);
162  /* no break */
163  case 2:
164  n = sscanf(argv[1], "%d:%d",
165  &stopwatch.exit_after_minutes,
166  &stopwatch.exit_after_seconds);
167  switch (n) {
168  case 2:
169  // do nothing
170  break;
171  case 1:
172  stopwatch.exit_after_seconds =
173  stopwatch.exit_after_minutes;
174  stopwatch.exit_after_minutes = 0;
175  break;
176  case 0:
177  fprintf(stderr, "Cannot extract meaningful time "
178  "from '%s'\n", argv[1]);
179  break;
180  }
181  break;
182  }
183 
184  fibre_run(&stopwatch.fibre);
185  fibre_run(&updater.fibre);
186 
188 
189  return 0;
190 }
#define containerof(ptr, type, member)
Definition: util.h:35
enum update_event_t::update_event_id id
#define FIBRE_VAR_INIT(fn)
Static initializer for a fibre descriptor.
Definition: fibre.h:75
fibre_t fibre
Definition: fibre.h:87
void * fibre_eventq_claim(fibre_eventq_t *evtq)
Request memory resources to send an event to a fibre.
Definition: fibre.c:226
#define PT_WAIT_UNTIL(c)
Definition: protothreads.h:116
void fibre_scheduler_main_loop(void)
Definition: fibre_default.c:17
struct update_event_t::@5 exit
int main(int argc, char *argv[])
Definition: fibredemo.c:151
bool fibre_eventq_send(fibre_eventq_t *evtq, void *evtp)
Send an event to a fibre.
Definition: fibre.c:234
#define PT_END()
Definition: protothreads.h:100
void fibre_eventq_release(fibre_eventq_t *evtq, void *evtp)
Release a message previously received by a fibre.
Definition: fibre.c:250
void * fibre_eventq_receive(fibre_eventq_t *evtq)
Recevied a message previously send to the fibre.
Definition: fibre.c:245
unsigned int minutes
Definition: fibredemo.c:33
int update_handler(fibre_t *fibre)
Definition: fibredemo.c:43
fibre_eventq_t updater
Definition: fibredemo.c:81
unsigned int seconds
Definition: fibredemo.c:34
stopwatch_fibre_t stopwatch
Definition: fibredemo.c:147
#define FIBRE_EVENTQ_VAR_INIT(fn, basep, base_len, msg_len)
Static initializer for a fibre and eventq descriptor.
Definition: fibre.h:94
uint32_t time_now(void)
update_event_t update_eventq[8]
Definition: fibredemo.c:80
int stopwatch_fibre(fibre_t *fibre)
Definition: fibredemo.c:95
unsigned int minutes
Definition: fibredemo.c:88
Fibre and eventq descriptor.
Definition: fibre.h:86
unsigned int exit_after_seconds
Definition: fibredemo.c:91
#define PT_BEGIN_FIBRE(f)
Fibre aware alternative to PT_BEGIN().
Definition: fibre.h:103
Fibre descriptor.
Definition: fibre.h:64
void fibre_run(fibre_t *f)
Definition: fibre.c:173
bool fibre_timeout(uint32_t duetime)
Definition: fibre.c:208
struct update_event_t::@4 time
uint32_t time
Definition: fibredemo.c:87
unsigned int seconds
Definition: fibredemo.c:89
unsigned int exit_after_minutes
Definition: fibredemo.c:90