2016-01-11 135 views
1

我正在用幾個有限狀態機在qt/Linux中構建一個嵌入式系統。每個FSM都有自己的事件隊列和一個連續運行的線程函數。 FSM可能會向彼此發佈事件。EventQueues和互斥體

顯然事件隊列在訪問時應該被鎖定和解鎖。 我應該將互斥鎖放入FSM,EventQueue還是將全局變量傳遞給FSM?

下面是僞代碼:

class EventQueue { 

     int queue[100]; 
     int head; 
     int tail; 

     void postEvent(int event) { 
      // place the event to circular buffer 
      // checking of head/tail neglected 
      queue[tail++] = event; 
     } 

     int getNextEvent() { 
      // checking of head/tail neglected 
      return queue[head++]; 
     } 

     bool isEmpty() { 
      return false; // or true if the queue is not empty 
     } 
    }; 

    class FSM { 
     EventQueue queue; 
     FSM * other; 
     pthread_t thread; 

     void start() { 
      int t = pthread_create(&thread, NULL, FSM::run, NULL); 

     } 

     // thread function 
     void * run(void *) { 

      while (true) { 

       if (!queue.isEmpty()) { 
        int e = queue.getNextEvent(); 
        dispatch(e);  // should be perform by state class actually 
       } 
      } 
     } 

     virtual void dispatch(int event) = 0; 
    }; 

    class FSM_A : FSM { 

     void dispatch(int event) { 

      other->postEvent(1234); // send event to other state machine 
      usleep(100); 
     } 
    }; 

    class FSM_B : FSM { 

     void dispatch(int event) { 

      other->postEvent(4567); // send event to other state machine 
      usleep(200); 
     } 
    }; 

    void main() { 
     FSM_A fsmA; 
     FSM_B fsmB; 

     fsmA.other = &fsmB; 
     fsmB.other = &fsmA; 

     fsmA.start(): 
     fsmB.start(): 
    } 

謝謝!

回答

2

我認爲最簡單的解決方案是互斥你的隊列。

class EventQueue { 

    int queue[100]; 
    int head; 
    int tail; 
    Mutex mutex; // std::mutex or QMutex or whatever you prefer. 

    void postEvent(int event) { 
     MutexLocker(mutex); // f.e. QMutextLocker or std::lock_guard 
     // place the event to circular buffer 
     // checking of head/tail neglected 
     queue[tail++] = event; 
    } 

    int getNextEvent() { 
     MutexLocker(mutex); 
     // checking of head/tail neglected 
     return queue[head++]; 
    } 

    bool isEmpty() { 
     // No lock is needed if no variables are read. 
     return false; // or true if the queue is not empty 
    } 
}; 

如果一個變量讀/從一個以上的線程寫的,它是非常重要的,而讀/寫過程中每一個讀或寫指令被鎖定。

當訪問其中一個命令隊列時,不需要鎖定每個命令隊列。我會將這個互斥鎖放入EventQueue

edit:正如在註釋中指出的那樣,使用MutexLocker鎖定互斥鎖更安全。這樣你就可以確定當函數作用域結束時它會被釋放。

+0

'bool isEmpty(){mutex.lock();返回false; mutex.unlock(); }和你的互斥鎖永遠不會解鎖!返回後無法訪問。 – Evgeny

+0

您應該改用QMutexLocker。 – Evgeny

+0

好趕上哈哈。確實使用mutexlocker來避免這些booboos – Teimpz

1

按照methodology..If類FSM使用EventQueue中,並EventQueue的內部管理它的事件隊列SOLID設計單一職責原則,那麼,它的EventQueue負責處理它自己的內部隊列usage.The FSM不需要關心EventQueue內部的問題。

+0

據此,互斥量應該在事件隊列中,所以FSMs不必爲此煩惱...... –

+0

因此而改變:) – basav