Bagaimana mesin status anak melepaskan kontrol kembali ke mesin status induk?


9

Mesin negara tingkat atas saya memiliki beberapa status dan tepi. Saya akan menyebut ini mesin induk negara.

A ----> B ----> C

Keadaan apa pun di dalam mesin status induk dapat juga menjadi mesin status. Saya akan memanggil anak-anak ini mesin negara.

           ___________
         /            \
A ----> |  B0->B1->B2  | ----> C
         \____________/

Jika mesin induk menyatakan transisi dari A ke B, mesin keadaan B mengambil alih. Setelah B selesai berjalan, bagaimana seharusnya melepaskan kontrol ke mesin status induk dan transisi ke status C? Pola desain mana yang Anda gunakan?

Jika Anda bertanya-tanya, saya memiliki mesin negara anak di dalam mesin negara induk karena proyek persis saya cukup kompleks dan wajar untuk merangkum cara kerja internal negara anak.


Saya menduga bahwa B0, B1, dan B2 harus tahu bahwa mereka adalah komponen dari sesuatu yang dunia luar anggap sebagai satu unit. Jadi mungkin Anda harus memiliki MachineContainerkelas untuk Byang berisi B0, B1, dan B2 dan ketika B2 berakhir, ia melewati kontrol kembali ke wadahnya yang kemudian transisi ke C ... Saya belum pernah mencoba yang seperti ini. Ini masalah yang menarik!
FrustratedWithFormsDesigner

2
Pertanyaan Anda memiliki jawaban yang jelas atau pertanyaan Anda tidak terlalu jelas. Dari sudut pandang orang tua, Anda harus mengimplementasikannya persis seperti Anda akan menerapkan mesin negara yang tidak memiliki mesin negara anak. Kebetulan negara-negara diimplementasikan dengan menggunakan mesin negara anak tetapi itu tidak mempengaruhi orangtua sama sekali. Ini juga tidak boleh mempengaruhi mesin negara anak selain saat keluar mereka hanya menghasilkan acara tingkat orang tua.
Dunk

Jawaban:


5

Setiap mesin negara memiliki semacam pengendali acara dan sarana untuk memicu peristiwa tersebut. Pawang itu mengambil input kondisi dan jenis acara yang ada, memilih status baru, dan secara opsional menjalankan beberapa kode efek samping.

Pada dasarnya, saat dalam keadaan B, event handler utama Anda meneruskan semua kejadian yang tidak dikenali ke Bevent handler dan tetap dalam status B. Ketika Bingin bertransisi ke C, itu memposting acara yang sesuai ke pengendali acara utama.


2

Sudahkah Anda membaca bagian Taoup ini ? Ada beberapa cara berbeda untuk melengkapi ini, tetapi banyak dari mereka bergantung pada bagaimana Anda telah membagi mesin negara Anda. Apakah mereka proses yang terpisah? Utas? Benda?

Cari tahu bagaimana Anda membuatnya, dan lihat apakah ada cara kanonik bagi mereka untuk berkomunikasi. Jika tidak ada, Anda mungkin merancang sistem Anda salah.

Bagi saya, saya akan melihat proses yang terpisah, menghubungkan stdin dan stdout bersama. Mesin status anak kemudian menjadi mandiri, bekerja pada stdin dan menghasilkan pada stdout. Menjadi tugas mesin induk untuk memulai proses anak, menghubungkan pipa, dan kemudian membuang data dan menunggu hasilnya. Semua hal itu sudah dilakukan dalam semua bahasa modern, jadi seharusnya mudah dilakukan.


1

Pisahkan kedua mesin negara dan gunakan pesan yang lewat di antara mereka. Dengan demikian, mesin negara 1 akan melanjutkan dari ABC, di mana di negara B ia memeriksa hasil saat ini dari mesin negara 2. Jika output telah berubah, maka mesin negara 1 dapat menjelaskannya dan mesin negara 2 tidak perlu memiliki kesadaran tentang bagaimana mesin negara 1 sebenarnya bekerja. Sesuatu seperti:

typedef struct StateMachine {
  void(*Update)(); // function to update the state machine
  int Data;        // generic temp holder to survive state contexts
  int State;       // current state of our state machine
  int *Message;    // pointer to a shared integer for message passing
};

int main(void) {
  int Message = 0;
  /* NewStateMachine would malloc the struct, pass in the int reference
   * and function pointer as well as add it to a circularly linked list */
  NewStateMachine(&Message, MainLoop);
  NewStateMachine(&Message, MinorLoop);
  StateMachine *Current = StateMachine_CLL.First;

  for(;;) {
    Current->Update(Current); /* Update the current state machine */
    Current = Current->Next;  /* And the advance to the next one */
  }
}

void MainLoop(StateMachine *this) {
  switch(this.State) {
  case 0:
    CloseCoolantTank(1); /* safe to call if valve already closed */
    CloseCoolantTank(2); /* safe to call if valve already closed */
    this.State = 1;
    break;
  case 1:
    /* we have a message, do something */
    if(*this.Message) this.State = 2;          
    /* otherwise stall at this state until we get a message */
    else this.State = 1;          
    break;
  case 2:
    if(*this.Message == 1) this.State = 3;      /* warm */
    else if(*this.Message == 2) this.State = 4; /* hot! */
    else this.State = 0;                        /* cooled down, shut off valves */
    this.Message = 0;                           /* clear the message */
    break;
  case 3:
    OpenCoolantTank(1); /* opens the valve, safe to call if already open */
    this.State = 2;     /* recheck for new message */
    break;
  case 4:
    OpenCoolantTank(2); /* opens the valve, safe to call if already open */
    this.State = 3;     /* also open coolant tank 1 for extra cooling */
    break;
  }
}

/* Monitor temperature and send messages on overheat */
void MinorLoop(StateMachine *this) {
  switch(this.State) {
  case 0:
    this.Data = ReadADCValue();
    this.State = 1;
    break;
  case 1:
    if(this.Data > 150) *this.Message = 2;
    else if(this.Data > 100) *this.Message = 1;
    this.State = 0;
    break;
  }
}

1

Solusinya tergantung pada 1) apakah sub-state A dapat dilihat oleh sub-state B. 2) Apakah AB dan C berasal dari orang tua biasa. Jika mereka memiliki orang tua yang sama dan visibilitasnya bersifat universal, Anda seharusnya tidak mengalami terlalu banyak kesulitan untuk berpindah dari sub negara B ke sub negara A.

Jika Anda telah mengisolasi mereka melalui ruang nama dan / atau A, B dan C tidak memiliki orang tua yang sama, maka cara terbaik Anda adalah memiliki driver perubahan keadaan eksternal untuk mesin A, B dan C. Ini bisa dilakukan melalui event handler. Cukup memiliki pengamat di A yang dapat mendengarkan acara yang diangkat dalam B dan transisi ke negara bagian sendiri berdasarkan acara tersebut.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.