blob: 31be206f7a533124b28460ec35c7e55647009f2d [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef _AOS_ASYNC_ACTION_H_
2#define _AOS_ASYNC_ACTION_H_
3
4#include <stdint.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8#include <signal.h>
9
10#include <string>
11#include <map>
12#include <type_traits>
13
14#include "aos/aos_core.h"
15#include "aos/common/type_traits.h"
16
17class AsyncActionTest;
18
19namespace aos {
20 // S is status type T is parameter type
21
22 template<class S> struct async_action_status {
23 S status;
24 uint8_t done_status; // 1 = valid status, 2 = done
25 uint16_t count;
26 pid_t pid;
27 aos_resource_entity *resource_entity;
28 };
29 template<class T> struct async_action_start {
30 T args;
31 uint16_t count;
32 aos_resource_entity *parent;
33 };
34
35 class AsyncActionRunner;
36 class ResourceAction_t;
37
38 class AsyncActionStatics {
39 friend class ResourceAction_t; // a testing AsyncAction that has to mess with resource stuff
40 protected:
41 class stopexception : public std::exception {
42 virtual const char* what() const throw() {
43 return "This exception indicates that the AsyncAction was stopped. This message should never show up anywhere.";
44 }
45 public:
46 stopexception() : std::exception() {}
47 };
48 class resourceexception : public std::exception {
49 virtual const char* what() const throw() {
50 return "This exception indicates that the AsyncAction was stopped due to resource contention. This message should never show up anywhere.";
51 }
52 public:
53 resourceexception() : std::exception() {}
54 };
55
56 // 1 = stop current DoAction
57 // 2 = stop corrent DoAction because of resource issues
58 // 4 = SIGINT pending (nicely close everything down first)
59 static volatile uint8_t interrupt;
60 static const int STOP_SIGNAL;
61 static aos_resource_entity *resource_entity;
62
63 // throw any exceptions indicated by signals
64 static inline void CheckStop(){
65 if(interrupt & (0x01 | 0x04)) {
66 throw stopexception();
67 fprintf(stderr, "the code should never ever get here (%s: %d)\n", __FILE__, __LINE__);
68 }else if(interrupt & 0x02) {
69 throw resourceexception();
70 fprintf(stderr, "the code should never ever get here (%s: %d)\n", __FILE__, __LINE__);
71 }
72 }
73 };
74
75 // S and T have to be structs
76 // T is sTart and S is status
77 // public functions (except for constructor) should be called on this AsyncAction
78 // in processes other than the one Run ing this AsyncAction
79 // vice versa for protected ones
80 template<class T, class S> class AsyncAction : public AsyncActionStatics {
81 static_assert(shm_ok<async_action_start<T>>::value,
82 "T must go through shared memory");
83 static_assert(shm_ok<async_action_status<S>>::value,
84 "S must go through shared memory");
85 friend class AsyncActionRunner;
86 friend class ::AsyncActionTest;
87 public:
88 AsyncAction(const std::string name);
89
90 // returns what the count will be throughout this run
91 // return of 0 indicates error (didn't start)
92 uint16_t Start(T &args);
93
94 // -1 for count means use the static one
95 // aka !IsRunning()
96 bool IsDone(int32_t count = -1);
97 // returns which one it joined
98 uint16_t Join(int32_t count = -1);
99 // return is whether there is an actual status or just garbage
100 bool GetStatus(S &status_out, int32_t count = -1) __attribute__ ((warn_unused_result));
101 // waits for a new good status
102 bool GetNextStatus(S &status_out, int32_t count = -1) __attribute__ ((warn_unused_result));
103
104 void Stop(int32_t count = -1);
105 protected:
106 // starts infinite loop that waits for Starts
107 // returns 0 for success, negative for error
108 // gets called by generated code
109 int Run(uint8_t priority);
110
111 virtual void DoAction(T &args);
112 // should only be called from DoAction
113 void PostStatus(S &status_in);
114 void RequestResource(uint16_t resource);
115 // returns whether succeeded
116 bool TryRequestResource(uint16_t resource);
117 void ReleaseResource(uint16_t resource);
118
119 // called at the beginning and end of Run
120 virtual void OnStart() {}
121 virtual void OnEnd() {}
122
123 // this should be the only sleep (or variant thereof) that gets called
124 void Sleep(double seconds);
125 private:
126 aos_queue *status_queue, *start_queue;
127
128 uint16_t local_count;
129 S local_status;
130 uint8_t local_done_status;
131 pid_t local_pid;
132
133 template<int (*O)(aos_resource_entity *, aos_resource *)> bool ResourceOp(uint16_t resource);
134 std::map<uint16_t, uint8_t> resources;
135
136 // for read_msg_index
137 int done_index, status_index;
138 uint16_t next_status_count; // uses it to figure out when to reset status_index
139
140 // return the default if appropriate
141 inline uint16_t GetCount(int32_t in){
142 if(in < 0)
143 return local_count;
144 else
145 return (uint16_t)in;
146 }
147
148 static void sig_action(int, siginfo_t *, void *);
149 };
150
151} // namespace aos
152
153#include "AsyncAction.cpp.inc" // to make the template stuff work
154
155#endif