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