2012-07-06 19 views
7

Tôi hy vọng rằng ai đó có thể giúp tôi giải quyết vấn đề này, hoặc ít nhất là chỉ ra lỗi của con đường của tôi ...Tăng Statechart - Chuyển tiếp địa phương

Như một minh hoạ đơn giản về vấn đề của tôi xem xét một phần một ứng dụng mà bạn có thể nhập trạng thái hoạt động của Chế độ chức năng. Bốn chế độ phụ sau đó khả dụng tùy thuộc vào phím chức năng F1-F4 mà người dùng nhấn. Theo mặc định, chế độ F1 được nhập. Sơ đồ nhà nước bắt đầu giảm giá như sau:

Diagram 1

Người dùng có thể nhấn F1-F4 bất cứ lúc nào để chuyển sang chế độ tương ứng. Thêm những hiệu ứng chuyển tiếp đến trạng thái bên trong dẫn đến những điều sau đây:

Diagram 2

Rõ ràng đây là (a) một mớ hỗn độn, và (b) có rất nhiều hiệu ứng chuyển tiếp để xác định. Nếu tại một số điểm tôi muốn thêm một F5Mode sau đó ... tốt, bạn sẽ có được hình ảnh. Để tránh điều này tôi muốn làm như sau:

Diagram 3

Boost Statechart cho phép tôi để xác định quá trình chuyển đổi từ FunctionMode với bất kỳ trạng thái bên trong, nhưng kết quả không phải là điều tôi mong đợi. Kết quả thực tế như sau:

Diagram 4

I.e. nhấn F1-F4 để chuyển đổi chế độ khiến trạng thái FunctionMode bên ngoài bị thoát và được nhập lại cùng với kích hoạt hành động thoát và nhập không mong muốn.

Cách quay lại năm 2006, this thread giữa tác giả thư viện và người dùng dường như mô tả cùng một vấn đề. Tôi nghĩ rằng tác giả đề nghị làm những điều sau đây là một công việc xung quanh:

Diagram 5

Tuy nhiên, đó công việc xung quanh không có vẻ rất hấp dẫn với tôi: Nó đã được thêm vào một cấp tiểu bang thêm được biên dịch, mã đã trở nên ít có thể đọc được, lịch sử sâu sẽ phải được sử dụng để trở về bất kỳ trạng thái phụ chế độ chức năng nào và đối tượng trạng thái trung gian là không cần thiết bị hủy và xây dựng lại.

Vì vậy ... tôi đang gặp vấn đề ở đâu? Hoặc các lựa chọn thay thế là gì? Tôi đã có một cái nhìn ngắn tại Boost Meta State Machine (msm) nhưng từ những gì tôi đã nhìn thấy cho đến nay tôi rất thích giao diện của Statechart.

Tôi ngạc nhiên khi nhiều người dùng khác không gặp phải vấn đề tương tự ... điều này khiến tôi nghĩ rằng có lẽ cách tiếp cận của tôi hoàn toàn sai!

Trả lời

1

Bạn đã xem số in-state reaction được giải thích trong statechart tutorial chưa? Nó dường như đang làm những gì bạn đang tìm kiếm.

Vì bạn đang yêu cầu lựa chọn thay thế, trong giai đoạn này tôi đang đánh giá các triển khai thống kê C++ Harel statechart khác nhau. Tôi đã xem Boost statechart và Boost MSM. Tôi đã viết mã với cả hai. Họ làm tổn thương não yếu ớt của tôi :-)

Sau đó, tôi tìm thấy Machine Objects (Macho), rất đơn giản và nhỏ, và tôi thích nó. Nó hỗ trợ các máy trạng thái phân cấp, các thao tác vào/ra, lịch sử, các snapshot của máy trạng thái, các bảo vệ, các chuyển đổi nội bộ, sự kiện trì hoãn, lưu trữ cục bộ (với tùy chọn persistence), vì vậy với tôi nó là một thực thi statelart Harel thỏa mãn.

Mã này thực hiện các phần FunctionMode của đồ trạng thái với Macho:

#include "Macho.hpp" 

#include <exception> 
#include <iostream> 
using namespace std; 

namespace FunctionMode { 

struct FunctionMode; 
struct F1Mode; 
struct F2Mode; 

// The Top state, containing all the others. 
TOPSTATE(Top) { 
    STATE(Top) 
    // All the events of the state machine are just virtual functions. 

    // Here we throw to mean that no inner state has implemented the event 
    // handler and we consider that an error. This is optional, we could 
    // just have an empty body or log the error. 
    virtual void evF1() { throw std::exception(); } 
    virtual void evF2() { throw std::exception(); } 
    // evF3 and so on... 
private: 
    void init() { setState<FunctionMode>(); } // initial transition 
}; 

SUBSTATE(FunctionMode, Top) { 
    STATE(FunctionMode) 
    virtual void evF1() { setState<F1Mode>(); } 
    virtual void evF2() { setState<F2Mode>(); } 
    // evF3, ... 
private: 
    void entry() { cout << "FunctionMode::entry" << endl; } 
    void exit() { cout << "FunctionMode::exit" << endl; } 
    void init() { setState<F1Mode>(); } // initial transition 
}; 

SUBSTATE(F1Mode, FunctionMode) { 
    STATE(F1Mode) 
    virtual void evF1() {} // make the event an internal transition (by swallowing it) 
private: 
    void entry() { cout << "F1Mode::entry" << endl; } 
    void exit() { cout << "F1Mode::exit" << endl; } 
}; 

SUBSTATE(F2Mode, FunctionMode) { 
    STATE(F2Mode) 
    virtual void evF2() {} // make the event an internal transition (by swallowing it) 
private: 
    void entry() { cout << "F2Mode::entry" << endl; } 
    void exit() { cout << "F2Mode::exit" << endl; } 
}; 

} // namespace FunctionMode 

int main() { 

    Macho::Machine<FunctionMode::Top> sm; 
    // Now the machine is already in F1Mode. 

    // Macho has 2 methods for synchronous event dispatching: 
    // First method: 
    sm->evF1(); // <= this one will be swallowed by F1Mode::evF1() 
    // Second method: 
    sm.dispatch(Event(&FunctionMode::Top::evF2)); 

    return 0; 
} 

Chạy nó, đầu ra là:

FunctionMode::entry 
F1Mode::entry 
F1Mode::exit 
F2Mode::entry 
F2Mode::exit 
FunctionMode::exit 

cho thấy rằng các hiệu ứng chuyển tiếp nội bộ.

Theo tôi, sạch sẽ, dễ dàng và mã nhỏ gọn :-)

[EDIT1] Phiên bản đầu tiên của mã không thực hiện quá trình chuyển đổi ban đầu FunctionMode ->F1Mode. Bây giờ nó.

+0

Rất cám ơn vì điều đó và xin lỗi vì sự chậm trễ trong phản hồi, có vẻ như tôi chưa bật thông báo qua email. Thật không may, phản ứng trong nhà nước có cùng một vấn đề - gọi Transit <> từ trạng thái bên ngoài để thay đổi trạng thái bên trong vẫn làm cho trạng thái bên ngoài được thoát ra và được nhập lại. Tuy nhiên, thay thế được đề xuất của bạn trông khá gọn gàng với tôi, vì vậy cảm ơn vì điều đó! – Grant

+0

@Grant: cảm ơn và tôi rất vui vì bạn thích :-) –

Các vấn đề liên quan