Alvin
Alvin

Reputation: 13

EventQueues and Mutex

I'm building an embedded system in qt/Linux with several finite state machines. Each FSM has its own event queue and a thread function running continuously. The FSMs may post events to each other.

Apparently the event queue should be locked and unlocked when accessing. Should I place the mutex in the FSM, EventQueue or make it global variables passing to the FSM?

Here is the pseudo code:

    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():
    }

Thanks!

Upvotes: 1

Views: 432

Answers (2)

Teimpz
Teimpz

Reputation: 935

I think the easyest solution is to mutexlock your your queue.

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
    }
};

If a variable is read/written from more then one thread, it is important that every read or write instruction is locked while the read/write is in progress.

You don't need to lock each command queue when one of them is accessed. I would place the mutex in the EventQueue

edit: as pointed out in the comments, it's a lot safer to use a MutexLocker to lock your mutex. This way you are sure it will be released when the function scope ends.

Upvotes: 2

basav
basav

Reputation: 1495

Follow the Single Responsibility principle in SOLID design methodology..If the class FSM uses the eventQueue, and EventQueue internally manages it's queue of events, then, it's EventQueue's responsibility to handle it's own internal queue usage.The FSM need not be bothered about internals of EventQueue..

Upvotes: 1

Related Questions