RTXI 1.3
include/rt.h
Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Weill Cornell Medical College
00003 
00004  This program is free software: you can redistribute it and/or modify
00005  it under the terms of the GNU General Public License as published by
00006  the Free Software Foundation, either version 3 of the License, or
00007  (at your option) any later version.
00008 
00009  This program is distributed in the hope that it will be useful,
00010  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  GNU General Public License for more details.
00013 
00014  You should have received a copy of the GNU General Public License
00015  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017  */
00018 
00019 #ifndef RT_H
00020 #define RT_H
00021 
00022 #include <fifo.h>
00023 #include <mutex.h>
00024 #include <pthread.h>
00025 #include <semaphore.h>
00026 #include <settings.h>
00027 
00029 
00033 namespace RT {
00034 
00035     namespace OS {
00036 
00037         typedef void * Task;
00038 
00039         int initiate(void);
00040         void shutdown(void);
00041 
00042         int createTask(Task *,void *(*)(void *),void *,int =0);
00043         void deleteTask(Task);
00044 
00045         int setPeriod(Task,long long);
00046         void sleepTimestep(Task);
00047 
00048         bool isRealtime(void);
00049 
00057         long long getTime(void);
00058 
00059     } // namespace OS
00060 
00067     class Event {
00068 
00069         friend class System;
00070 
00071     public:
00072 
00073         Event(void);
00074         virtual ~Event(void);
00075 
00081         virtual int callback(void)=0;
00082 
00083     private:
00084 
00085         void execute(void);
00086         void wait(void);
00087 
00088         int retval;
00089         sem_t signal;
00090 
00091     }; // class Event
00092 
00093     template<typename T>
00094     class List {
00095 
00096     public:
00097 
00098         class Node;
00099 
00100         class iterator {
00101 
00102         public:
00103 
00104             iterator(void)
00105                 : current(0) {};
00106             iterator(T *x)
00107                 : current(static_cast<Node *>(x)) {};
00108             iterator(const iterator &x)
00109                 : current(x.current) {};
00110 
00111             bool operator==(const iterator &x) const {
00112                 return current == x.current;
00113             };
00114             bool operator!=(const iterator &x) const {
00115                 return current != x.current;
00116             };
00117 
00118             T &operator*(void) const {
00119                 return *static_cast<T *>(current);
00120             };
00121             T *operator->(void) const {
00122                 return static_cast<T *>(current);
00123             };
00124 
00125             iterator &operator++(void) {
00126                 current = current->next;
00127                 return *this;
00128             };
00129             iterator operator++(int) {
00130                 typename RT::List<T>::iterator tmp = *this;
00131                 current = current->next;
00132                 return tmp;
00133             };
00134             iterator &operator--(void) {
00135                 current = current->prev;
00136                 return *this;
00137             };
00138             iterator operator--(int) {
00139                 typename RT::List<T>::iterator tmp = *this;
00140                 current = current->prev;
00141                 return tmp;
00142             };
00143 
00144 
00145         private:
00146 
00147             Node *current;
00148 
00149         }; // class iterator
00150 
00151         class const_iterator {
00152 
00153         public:
00154 
00155             const_iterator(void)
00156                 : current(0) {};
00157             const_iterator(const T *x)
00158                 : current(static_cast<const Node *>(x)) {};
00159             const_iterator(const const_iterator &x)
00160                 : current(x.current) {};
00161 
00162             bool operator==(const const_iterator &x) const {
00163                 return current == x.current;
00164             };
00165             bool operator!=(const const_iterator &x) const {
00166                 return current != x.current;
00167             };
00168 
00169             const T &operator*(void) const {
00170                 return *static_cast<const T *>(current);
00171             };
00172             const T *operator->(void) const {
00173                 return static_cast<const T *>(current);
00174             };
00175 
00176             const_iterator &operator++(void) {
00177                 current = current->next;
00178                 return *this;
00179             };
00180             const_iterator operator++(int) {
00181                 typename RT::List<T>::const_iterator tmp = *this;
00182                 current = current->next;
00183                 return tmp;
00184             };
00185             const_iterator &operator--(void) {
00186                 current = current->prev;
00187                 return *this;
00188             };
00189             const_iterator operator--(int) {
00190                 typename RT::List<T>::const_iterator tmp = *this;
00191                 current = current->prev;
00192                 return tmp;
00193             };
00194 
00195 
00196         private:
00197 
00198             const Node *current;
00199 
00200         }; // class const_iterator
00201 
00202         class Node {
00203 
00204             friend class List<T>;
00205             friend class List<T>::iterator;
00206             friend class List<T>::const_iterator;
00207 
00208         public:
00209 
00210             Node(void)
00211                 : next(0), prev(0) {};
00212             virtual ~Node(void) {};
00213 
00214             bool operator==(const Node &x) const {
00215                 return next == x.next && prev == x.prev;
00216             };
00217 
00218         private:
00219 
00220             Node *next, *prev;
00221 
00222         }; // class Node
00223 
00224         List(void)
00225             : count(0), head(&tail), tail() {};
00226         virtual ~List(void) {
00227 #ifdef DEBUG
00228             if(tail.next)
00229                 ERROR_MSG("RT::List::~List : end of list overwritten\n");
00230 #endif
00231         };
00232 
00233         size_t size(void) const {
00234             return count;
00235         };
00236         bool empty(void) const {
00237             return count==0;
00238         };
00239 
00240         iterator begin(void) {
00241             return iterator(static_cast<T *>(head));
00242         };
00243         iterator end(void) {
00244             return iterator(static_cast<T *>(&tail));
00245         };
00246 
00247         const_iterator begin(void) const {
00248             return const_iterator(static_cast<const T *>(head));
00249         };
00250         const_iterator end(void) const {
00251             return const_iterator(static_cast<const T *>(&tail));
00252         };
00253 
00254         void insert(iterator,T &);
00255         void insertRT(iterator position,T &node) {
00256             Node *object = static_cast<Node *>(&node);
00257 
00258             object->next = &(*position);
00259             object->prev = object->next->prev;
00260             if(object->next == head)
00261                 head = object;
00262             else
00263                 position->prev->next = object;
00264             position->prev = object;
00265             count++;
00266         };
00267 
00268         void remove(T &);
00269         void removeRT(T &node) {
00270             Node *object = static_cast<Node *>(&node);
00271 
00272             if(object == &tail)
00273                 return;
00274             if(object == head)
00275                 head = object->next;
00276             else if(object->prev)
00277                 object->prev->next = object->next;
00278             object->next->prev = object->prev;
00279             count--;
00280         };
00281 
00282     private:
00283 
00284         class InsertListNodeEvent : public RT::Event {
00285 
00286         public:
00287 
00288             InsertListNodeEvent(List<T> *l,iterator i,T *n)
00289                 : list(l), iter(i), node(n) {};
00290             int callback(void) {
00291                 list->insertRT(iter,*node);
00292                 return 0;
00293             };
00294 
00295         private:
00296 
00297             List<T> *list;
00298             typename List<T>::iterator iter;
00299             T *node;
00300 
00301         }; // class InsertListNodeEvent;
00302 
00303         class RemoveListNodeEvent : public RT::Event {
00304 
00305         public:
00306 
00307             RemoveListNodeEvent(List<T> *l,T *n)
00308                 : list(l), node(n) {};
00309             int callback(void) {
00310                 list->removeRT(*node);
00311                 return 0;
00312             };
00313 
00314         private:
00315 
00316             List<T> *list;
00317             T *node;
00318 
00319         }; // class RemoveListNodeEvnet;
00320 
00321         size_t count;
00322         Node *head, tail;
00323 
00324     }; // class List
00325 
00326     class Device;
00327     class Thread;
00328 
00333     class System {
00334 
00335         friend class Device;
00336         friend class Thread;
00337 
00338     public:
00339 
00346         static System *getInstance(void);
00347 
00353         long long getPeriod(void) const { return period; };
00360         int setPeriod(long long period);
00361 
00371         void foreachDevice(void (*callback)(Device *,void *),void *param);
00381         void foreachThread(void (*callback)(Thread *,void *),void *param);
00382 
00392         int postEvent(Event *event,bool blocking =true);
00393 
00394     private:
00395 
00396         /******************************************************************
00397          * The constructors, destructor, and assignment operator are made *
00398          *   private to control instantiation of the class.               *
00399          ******************************************************************/
00400 
00401         System(void);
00402         ~System(void);
00403         System(const System &) : eventFifo(0) {};
00404         System &operator=(const System &) { return *getInstance(); };
00405 
00406         class SetPeriodEvent : public RT::Event {
00407 
00408         public:
00409 
00410             SetPeriodEvent(long long);
00411             ~SetPeriodEvent(void);
00412 
00413             int callback(void);
00414 
00415         private:
00416 
00417             long long period;
00418 
00419         }; // class SetPeriodEvent
00420 
00421 
00422         static System *instance;
00423 
00424         Mutex deviceMutex;
00425         void insertDevice(Device *);
00426         void removeDevice(Device *);
00427 
00428         Mutex threadMutex;
00429         void insertThread(Thread *);
00430         void removeThread(Thread *);
00431 
00432         static void *bounce(void *);
00433         void execute(void);
00434 
00435         bool finished;
00436         pthread_t thread;
00437         RT::OS::Task task;
00438         long long period;
00439 
00440         List<RT::Device> deviceList;
00441         List<RT::Thread> threadList;
00442 
00443         Fifo eventFifo;
00444 
00445     }; // class System
00446 
00452     class Device : public List<Device>::Node {
00453 
00454     public:
00455 
00456         Device(void);
00457         virtual ~Device(void);
00458 
00470         /**********************************************************
00471          * read & write must not be pure virtual because they can *
00472          *    be called during construction and destruction.      *
00473          **********************************************************/
00474 
00475         virtual void read(void) {};
00476         virtual void write(void) {};
00477 
00478         inline bool getActive(void) const { return active; };
00479         void setActive(bool);
00480 
00481     private:
00482 
00483         bool active;
00484 
00485     }; // class Device
00486 
00492     class Thread : public List<Thread>::Node {
00493 
00494     public:
00495 
00496         typedef unsigned long Priority;
00497 
00498         static const Priority MinimumPriority = 0;
00499         static const Priority MaximumPriority = 100;
00500         static const Priority DefaultPriority = MaximumPriority/2;
00501 
00502         Thread(Priority p =DefaultPriority);
00503         virtual ~Thread(void);
00504 
00512         Priority getPriority(void) const { return priority; };
00513 
00520         /**********************************************************
00521          * execute must not be pure virtual because it can be     *
00522          *   called during construction and destruction.          *
00523          **********************************************************/
00524 
00525         virtual void execute(void) {};
00526 
00527         inline bool getActive(void) const { return active; };
00528         void setActive(bool);
00529 
00530     private:
00531 
00532         bool active;
00533         Priority priority;
00534 
00535     }; // class Thread
00536 
00537     template<typename T>
00538     void List<T>::insert(iterator position,T &node) {
00539         InsertListNodeEvent event(this,position,&node);
00540         RT::System::getInstance()->postEvent(&event);
00541     }
00542 
00543     template<typename T>
00544     void List<T>::remove(T &node) {
00545         RemoveListNodeEvent event(this,&node);
00546         RT::System::getInstance()->postEvent(&event);
00547     }
00548 
00549 } // namespace RT
00550 
00551 #endif // RT_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines