a implementation of template class that is used for create event-driven task thread.

Revision:
1:7d11951c1fc0
Parent:
0:1f4516e81c1b
--- a/Actor.h	Wed May 20 08:11:04 2015 +0000
+++ b/Actor.h	Thu May 28 00:48:27 2015 +0000
@@ -1,46 +1,86 @@
 #ifndef ACTOR_H
 #define ACTOR_H
 
-#include <cstdarg>
 #include <map>
 #include "mbed.h"
 #include "rtos.h"
 
-#define MAX_MAIL_NUM    255
-#define STACK_SIZE      1024 * 4
+#define MAX_MAIL_NUM    16
+#define STACK_SIZE      1024 * 1
 #define START_THREAD    -1
 
-typedef void (*Routine)(void const *argument);
 typedef uint32_t MessageID;
 
 struct MailPacket {
-    uint32_t messageId;
+    MessageID messageId;
     void *packet;
 };
 
 typedef Mail<MailPacket, MAX_MAIL_NUM> MailBox;
-typedef std::map<MessageID, void(*)(void *)> JobList;
 
+template <typename T>
 class Actor
 {
+protected:
+    typedef void (T::*Action)(void *);
+    typedef std::map<MessageID, Action> ActionMap;
+
+    Thread thread;
+    ActionMap actions;
+    MailBox mbox;
+
 public:
-    Actor();
-    virtual ~Actor();
+    Actor(
+        osPriority priority = osPriorityNormal,
+        uint32_t stack_size = STACK_SIZE) :
+            thread(&Actor::threadKicker, this, priority, stack_size)
+    {
+        thread.signal_set(START_THREAD);
+    }
 
-    virtual void subscribe(MessageID msg, void(*task)(void *));
+    virtual ~Actor(){};
+
+    virtual void subscribe(MessageID msg, Action act) {
+        actions[msg] = act;
+    }
 
-    virtual void unsubscribe(MessageID msg);
-
-    static void sendMail(Actor *dest, MessageID msg, void *pkt);
+    virtual void unsubscribe(MessageID msg) {
+        actions.erase(msg);
+    }
+    
+    virtual void putMail(MessageID msg, void *pkt) {
+        MailPacket *mail = mbox.alloc();
+        mail->messageId  = msg;
+        mail->packet     = pkt;
+        mbox.put(mail);
+    }
 
 protected:
-    virtual void threadMain();
-
-    static void threadKicker(void const *p);
+    virtual void threadMain() {
+        osEvent event;
+        while(true) {
+            event = mbox.get();
+            if (event.status == osEventMail) {
+                MailPacket *mail = (MailPacket*)event.value.p;
+                MessageID msg = mail->messageId;
+                void *pkt     = mail->packet;
+                if (actions[msg] != NULL) {
+                    (reinterpret_cast<T*>(this)->*actions[msg])(pkt);
+                }
+                mbox.free(mail);
+            }
+        }
+    }
 
-    Thread thread;
-    MailBox mbox;
-    JobList joblist;
+    static void threadKicker(void const *actor) {
+        Actor *instance = (Actor*)actor;
+        instance->threadMain();
+    }
 };
 
+template <typename T>
+void sendMail(T *dest, MessageID msg, void *pkt) {
+    dest->putMail(msg, pkt);
+}
+
 #endif