copied everything over from 2012 and removed all of the actual robot code except the drivetrain stuff
git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4078 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/aos/atom_code/async_action/AsyncAction.h b/aos/atom_code/async_action/AsyncAction.h
new file mode 100644
index 0000000..31be206
--- /dev/null
+++ b/aos/atom_code/async_action/AsyncAction.h
@@ -0,0 +1,155 @@
+#ifndef _AOS_ASYNC_ACTION_H_
+#define _AOS_ASYNC_ACTION_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include <string>
+#include <map>
+#include <type_traits>
+
+#include "aos/aos_core.h"
+#include "aos/common/type_traits.h"
+
+class AsyncActionTest;
+
+namespace aos {
+ // S is status type T is parameter type
+
+ template<class S> struct async_action_status {
+ S status;
+ uint8_t done_status; // 1 = valid status, 2 = done
+ uint16_t count;
+ pid_t pid;
+ aos_resource_entity *resource_entity;
+ };
+ template<class T> struct async_action_start {
+ T args;
+ uint16_t count;
+ aos_resource_entity *parent;
+ };
+
+ class AsyncActionRunner;
+ class ResourceAction_t;
+
+ class AsyncActionStatics {
+ friend class ResourceAction_t; // a testing AsyncAction that has to mess with resource stuff
+ protected:
+ class stopexception : public std::exception {
+ virtual const char* what() const throw() {
+ return "This exception indicates that the AsyncAction was stopped. This message should never show up anywhere.";
+ }
+ public:
+ stopexception() : std::exception() {}
+ };
+ class resourceexception : public std::exception {
+ virtual const char* what() const throw() {
+ return "This exception indicates that the AsyncAction was stopped due to resource contention. This message should never show up anywhere.";
+ }
+ public:
+ resourceexception() : std::exception() {}
+ };
+
+ // 1 = stop current DoAction
+ // 2 = stop corrent DoAction because of resource issues
+ // 4 = SIGINT pending (nicely close everything down first)
+ static volatile uint8_t interrupt;
+ static const int STOP_SIGNAL;
+ static aos_resource_entity *resource_entity;
+
+ // throw any exceptions indicated by signals
+ static inline void CheckStop(){
+ if(interrupt & (0x01 | 0x04)) {
+ throw stopexception();
+ fprintf(stderr, "the code should never ever get here (%s: %d)\n", __FILE__, __LINE__);
+ }else if(interrupt & 0x02) {
+ throw resourceexception();
+ fprintf(stderr, "the code should never ever get here (%s: %d)\n", __FILE__, __LINE__);
+ }
+ }
+ };
+
+ // S and T have to be structs
+ // T is sTart and S is status
+ // public functions (except for constructor) should be called on this AsyncAction
+ // in processes other than the one Run ing this AsyncAction
+ // vice versa for protected ones
+ template<class T, class S> class AsyncAction : public AsyncActionStatics {
+ static_assert(shm_ok<async_action_start<T>>::value,
+ "T must go through shared memory");
+ static_assert(shm_ok<async_action_status<S>>::value,
+ "S must go through shared memory");
+ friend class AsyncActionRunner;
+ friend class ::AsyncActionTest;
+ public:
+ AsyncAction(const std::string name);
+
+ // returns what the count will be throughout this run
+ // return of 0 indicates error (didn't start)
+ uint16_t Start(T &args);
+
+ // -1 for count means use the static one
+ // aka !IsRunning()
+ bool IsDone(int32_t count = -1);
+ // returns which one it joined
+ uint16_t Join(int32_t count = -1);
+ // return is whether there is an actual status or just garbage
+ bool GetStatus(S &status_out, int32_t count = -1) __attribute__ ((warn_unused_result));
+ // waits for a new good status
+ bool GetNextStatus(S &status_out, int32_t count = -1) __attribute__ ((warn_unused_result));
+
+ void Stop(int32_t count = -1);
+ protected:
+ // starts infinite loop that waits for Starts
+ // returns 0 for success, negative for error
+ // gets called by generated code
+ int Run(uint8_t priority);
+
+ virtual void DoAction(T &args);
+ // should only be called from DoAction
+ void PostStatus(S &status_in);
+ void RequestResource(uint16_t resource);
+ // returns whether succeeded
+ bool TryRequestResource(uint16_t resource);
+ void ReleaseResource(uint16_t resource);
+
+ // called at the beginning and end of Run
+ virtual void OnStart() {}
+ virtual void OnEnd() {}
+
+ // this should be the only sleep (or variant thereof) that gets called
+ void Sleep(double seconds);
+ private:
+ aos_queue *status_queue, *start_queue;
+
+ uint16_t local_count;
+ S local_status;
+ uint8_t local_done_status;
+ pid_t local_pid;
+
+ template<int (*O)(aos_resource_entity *, aos_resource *)> bool ResourceOp(uint16_t resource);
+ std::map<uint16_t, uint8_t> resources;
+
+ // for read_msg_index
+ int done_index, status_index;
+ uint16_t next_status_count; // uses it to figure out when to reset status_index
+
+ // return the default if appropriate
+ inline uint16_t GetCount(int32_t in){
+ if(in < 0)
+ return local_count;
+ else
+ return (uint16_t)in;
+ }
+
+ static void sig_action(int, siginfo_t *, void *);
+ };
+
+} // namespace aos
+
+#include "AsyncAction.cpp.inc" // to make the template stuff work
+
+#endif