質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

2434閲覧

優先度の処理について

aoshanghai

総合スコア24

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2015/03/05 17:18

編集2015/03/05 17:20

仕事で、LEDを光らせる処理をC++で書いておりました。
通常は、定期的にLEDをオンオフさせる単純な光り方をさせているのですが、押されたボタンによって、優先度を高くして、ピカピカといった形で激しく光らせないといけません。
優先度は、低、中、高の3つを用意しておりました。
デフォルト状態では、優先度低のLEDの光り方をさせておいて、ボタンが押されると、ボタンに応じて優先度中の光り方や高の光り方で割り込むような形でLEDを光らせます。
優先度中や高の光り方が終わったら、デフォルトの優先度低の光り方に戻ります。
こういう処理をやりたかったのですが、優先度の処理をどうプログラミングするかについて少し悩んでおりました。
結局は、3つのタスクを用意して、優先度低のタスクがいつも動いており、もし優先度中や高のボタンが押されたら、それに該当するタスクが動くような処理をしました。
最終的には3つのタスクの内優先度が最も高い処理結果をLEDに引き渡すような作りにしました。
結果としては問題なく動いているのですが、大学の授業や社会人になってから学んだ本などでは、個人的にはですが、こういった処理の王道的なアルゴリズムといいますか、プログラミングの方法を見かけたことがありません。
なので、こういった優先度の処理に関する定番の方法や、もしくは、参考になる本などがありましたら、ご教示頂きたく質問させて頂いた次第です。
どうぞよろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ご意見を拝見しました。

順序が前後しますが・・・

ここで、一番気になっていることとしては、こういった実装についても
言及している書籍などがあるかどうか、こういった処理の王道的な
アルゴリズムがあるかどうか?、という点です。

無いでしょうね。
ご要求の内容自体は、扱う範囲が小さすぎます。どちらかというと”小手先の実装方法”に過ぎないと思います。
アルゴリズムとかフレームワークといったような共通の考え方があるようには思えないです。

タイトルを「優先度の管理について」としましたが、ご意見を拝見したり
回答を書いている内に、単に優先度の管理の問題、というわけではない
気がしてきました。

優先度云々の話ではなくて、単に「LEDの点灯パターンの切り替えタイミング」じゃないですかね。
「いかなるタイミングでも優先度の高い方の点滅のさせ方をしたい!」というのであれば、また別の話になりますし。

この際に、できれば、状態Cの時の光り方を、最初からやり直すのではなくて、
状態Cが裏で動き続けていたような光り方から再開したいと思っておりました。

例示された例では、最小の単位時間が1秒ですから、タスク内で1秒毎に状態A/B/Cのそれぞれの状態についてON/OFFのどちらになるべきかを更新&保持しておいて(=点灯させたとしたら、いまON/OFFのどちらになるべきかを常に管理しておいて)、実際のLEDの点灯は状態A/B/Cのどれかに応じて現在のON/OFF状態を反映させる、という方法でいかがでしょうか。
あるいは、システムtickカウントを割り算でもすれば、状態A/B/Cそれぞれについて一意に現在のON/OFF状態が計算できそうでもあります。

状態Aの時に、優先度中のボタンが押されたら、状態Bには移りませんが、
状態AでのLEDの光り方が終わったら、状態Bには遷移したいです。

先に示した動作とは矛盾する部分が出てきそうですが、こちらのご要求にピッタリ合わせるなら、つぎのようになろうかと思います。

まず「状態AでのLEDの光り方が終わったら」とありますが、"始まり”と”終わり”を定義しないといけませんね。
おそらくは[ON→OFF]までが始まり~終わりの一連の動作になるのでしょうから、全体としては、

for(;;) {
on_off_time = 点滅周期判定
LED点灯
on_off_time秒待ち
LED消灯
on_off_time秒待ち
}

くらいで十分ではないですか?
これなら、どんなタイミングで状態A/B/Cが変わっても、変なところでLEDの点灯パターンが急に変わることはないと思います。
ただ、状態Cの長い周期の点滅期間に、状態Aが2秒発生し、その後すぐに状態Cに戻ったという場合は状態Aはなかったような点滅になってしまいます。そういうケースにどうなるべきか?については、別途方針を決めないといけませんね。

投稿2015/03/06 06:07

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aoshanghai

2015/03/06 09:53

ご回答ありがとうございます。 大変参考になりました。 確かに仰るとおり、細かい実装テクニックになるかと思います。 こういうレベルだと、基本的に自分がやりやすい方法で実装すれば 十分なのだと思います。 ご意見ありがとうございました。 また、2つの実装方針についても大変参考になりました。 私が実装したのは、前者に近い形になるかと思いますが、 後者のご意見についても参考にさせて頂きます。 また、確かに仰るとおり、記述されたような実装で十分な気が致します。 まだ理解できていない部分も多少ありますが、まずはご意見を拝見しながら 再度実装方法について考えてみたいと思います。 ご教示ありがとうございました。
guest

0

すみません、質問の骨子を読み違えていたようです。
「タスク」「優先度」から、タスクの使い方の話かなーと。

「優先度」は、LEDの点灯パターンに対する優先度ですね。

システム全体の要求仕様が分からないので何とも言えないのですが、そもそもLEDの点灯パターン優先度のために「キュー」を用意する必要はありますか?ご質問からは、そこが読み取れないです。

システムがある状態AにあるからLEDを速く点滅させ、システムが別の状態Bにあるからゆっくり点滅でよい、そういう考え方ではないですか?
あるいは、「緊急事態」みたいな状態を表すフラグがあってその状態のときはLEDを速く点滅させ、
そうでないときはゆっくり点滅でよいとか。
いずれにしても、これらの場合ではキューは必要ないと思います。

要は、システムの中で何かの「状態」が変化したときに、その時の状態を(総合的に)判断して、LEDに対して「速く点滅しろ」「遅く点滅しろ」と指示するのが普通のように思えます。その緊急状態が解消したら、また判断を下してLEDタスクに指示を出す、そういう感じです。

とにかく、要求仕様がわからないので何とも言えません。貴方のいう「優先度」って、何で決まるのでしょうか?最初のほうで「ボタンが押されたら・・・」とありましたけど、ボタンが押されたらLEDが速く(遅く)点滅するというのは結果的にそうなるだけであって、ボタンが押されたらシステム内の「何か」が変化して、その結果としてLEDの点滅パターンが変わるんですよね?

ご質問の内容だけではキューが必要かどうかは判断できないです。ここでいう優先度は、ただの条件判断のような気がします。

投稿2015/03/06 04:12

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aoshanghai

2015/03/06 04:50

ご回答ありがとうございます。 大変勉強になります。 キューが必要かどうかという点ですが、これは、今回の場合は、結局必須ではありませんでした。 当初は、例えば優先度の高いボタンを連続して何回も押した場合に、優先度高のリクエストを 優先度高用のキューに溜めておくべきかと考えていたのですが、 リクエストを溜めておくと、ボタンを連打した際にずっと光り続けるように なるので、結局、リクエストは1つしか受け付けないようにしました。 なので、キューは、必須とは言えないです。 単なる変数でも良かったかと思います。 ところで、状態遷移を使えば良いのではないか?、というご意見に なるかと思います。 状態遷移を使った場合について考えたのですが、 優先度高:状態A 優先度中:状態B 優先度低:状態C として考えた場合、デフォルトの状態だと、状態Cにあると思います。 状態Cで、仮に on 5sec off 5sec という光らせ方をループさせていたとします。 ここで、優先度高のボタンが押されてて、状態Aに切り替わったとします。 状態Aの光り方が on 1sec off 1sec on 1sec off 1sec としたとします。 この場合、状態Aの光り方が4secで終わるので、その後、もとの状態Cに戻って欲しいです。 この際に、できれば、状態Cの時の光り方を、最初からやり直すのではなくて、 状態Cが裏で動き続けていたような光り方から再開したいと思っておりました。 その方が、優先度高の光か方が、割り込んで処理されたように見えて より自然な見え方になると思いますので。 また、優先度Bの光り方が on 2sec off 2sec on 2sec off 2sec だとします。 状態Aの時に、優先度中のボタンが押されたら、状態Bには移りませんが、 状態AでのLEDの光り方が終わったら、状態Bには遷移したいです。 なぜなら、状態Bの光る時間の方が長いので。 説明が分かりにくくて申し訳ございませんが、概ねこのような処理を考えておりました。 ここで、一番気になっていることとしては、こういった実装についても 言及している書籍などがあるかどうか、こういった処理の王道的な アルゴリズムがあるかどうか?、という点です。 タイトルを「優先度の管理について」としましたが、ご意見を拝見したり 回答を書いている内に、単に優先度の管理の問題、というわけではない 気がしてきました。 また、こういった基本レベルは自分で考えるべき、といった話しにもなりそう ですが、そういう結論でも構いませんので、皆様のご意見をお伺いしたく 質問させて頂いた次第です。 お手数をおかけいたしますがよろしくお願い致します。
guest

0

単純な処理だけに、"こうするべき"的な王道は無いように思います。
ですので、以下は「私だったらこうする(方法もある)」という程度に聞き流してください。

LEDの数は1つだけですよね?それなのに、タスクを3つも用意するというのは、ちょっとリソースがもったいないような気がします。

考え方をシンプルにして、「LEDを点滅させるタスク」を1つ用意するということで良いのではないでしょうか?つまり、そのタスクは「LEDを点滅させる」ことに特化したものということです。

そのタスクに対して、「点滅周期を速くしろ(遅くしろ)」というメッセージを送って、そのタスクに点滅間隔を変えさせればよいのではないでしょうか。
私なら、点滅周期を変えるくらいなら、メッセージ送信のような方法を取らず、単純に変数書き換え(=タスクはその変数を参照して点滅周期を決めている)くらいで済ましてしまうと思います。

参考になれば幸いです。

投稿2015/03/06 02:00

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aoshanghai

2015/03/06 02:25

大変参考になりました。 ご回答ありがとうございました。 確かにタスクは1つにした方が、リソースの節約になるかと思います。 ところで、お伺いしたいのですが、優先度の処理については、 いかがでしょうか? タスクを1つにして、その中で優先度を管理しないといけないかと思いますが、 優先度の管理について、もしお勧めの方法など何かありましたら ご教示頂けると大変助かります。 以前試した方法としては、優先度毎にリクエスト保存用のキューを用意しておいて、 for文で、リクエストが入っているキューについて、優先度の分(最大高中低の3つ)を 回して処理をしておりました。 ここで処理された結果の中から、一番優先度の高い処理結果を、LEDに反映させておりました。 # こうしておくことで、LEDが優先度の高い光り方をした後に、自動的に、デフォルトの # 優先度の低い光り方に戻れるので。しかも、戻った際に、優先度の低い処理パターンが裏で # ずっと動いているような見え方になるかと思います。 気になる点としては、優先度の管理は、プログラムとしては比較的良く行う類だと 思いますが、これといった王道的な方法が紹介されてある文献を見かけたことがないことです。 仰るとおり、比較的単純な処理にはなるかと思いますので、本などで 紹介されるほどの内容ではない(誰でもすぐに作れるレベル)ということ なのかもしれませんが、意外と悩みながら実装した経緯があるので、 皆様のご意見をお伺いしたいと思った次第です。 お手数をおかけいたしますがよろしくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問