Open tichise opened 5 years ago
終了は少し怖いです。スレッドに自分自身を殺すように依頼してから参加することをお勧めします。 ともかく、Threadオブジェクトは2回目の起動を許可しません。これは意図的な設計上の決定です - Threadオブジェクトは正確に1つのスレッドに関連付けられています。新しいスレッドは新しいオブジェクトを必要とします。 あなたは「再開している」と言いますが、実際はそうではありません。まったく同じことをしているのは、まったく新しいスレッドです。すでに使用されているThreadオブジェクトを再利用することはできません。 (他のプロトコルでも同様のことが起こります - たとえば、2番目のTCP接続にソケットを移植的に再利用することはできません。新しい接続には新しいソケットが必要です)。
If you really want to reuse memory, you can destroy a local Thread object and reinitialise it with placement new. If you want to avoid memory fragmentation; you need to provide the memory chance that is going to be used as the stack:
本当にメモリを再利用したい場合は、ローカルのThreadオブジェクトを破棄し、新しい配置で再初期化することができます。メモリの断片化を避けたい場合あなたはスタックとして使用されることになるメモリの機会を提供する必要があります。
uint8_t thread_stack[STACK_SIZE];
main() {
Thread thread(osPriorityNormal, sizeof(thread_stack), thread_stack);
while(true) {
thread.start();
running = false;
thread.join();
thread.~Thread(); // destroy the local thread object
// construct a new thread at emplacement &thread
new (&thread) Thread(osPriorityNormal, sizeof(thread_stack), thread_stack)
}
}
@pan- Good general point on the stack, but I don't think that's a good example for the placement new. If Thread is automatic, you can hopefully do it more neatly by letting the old Thread go out of scope, like my example above. (And if that's not possible, it must be a pretty weird-looking function). Would make sense if you really want the Thread object to be static.
I've been thinking we probably should have something to support static memory reuse/overlays like that. Like SingletonPtr, but multiple users in a union.
Something like std::any's API, but with available possible types declared up-front to define built-in storage size? Getting a bit off-topic though.
pan-スタック上の一般的な良い点ですが、new配置の良い例ではないと思います。 Threadが自動の場合は、上の例のように古いThreadを対象外にすることで、よりきちんとそれを行うことができます。 (それが不可能な場合は、かなり奇妙な機能でなければなりません)。 Threadオブジェクトを本当に静的にしたいのであれば意味があります。
私たちはおそらく静的メモリの再利用/オーバーレイをサポートするための何かがあるべきだと思っていました。 SingletonPtrと似ていますが、複数のユーザーが結合しています。
std :: anyのAPIのようなものですが、組み込みストレージサイズを定義するために利用可能な型が事前に宣言されていますか? 話題を少し外す
Sorry for the bad examples; for sure in a loop it is better to use RAII. But placement new might be useful to reuse a thread object if there's really pressure on memory. In that case, I believe the best would be a move constructor.
Something like std::any's API, but with available possible types declared up-front to define built-in storage size? Getting a bit off-topic though.
std::variant sounds like what you're describing. any is basically glorified void* to an object.
悪い例でごめんね。 確かにループではRAIIを使うのが良いです。 しかし、本当にメモリに負荷がかかる場合は、新しい配置はスレッドオブジェクトを再利用するのに役立ちます。 その場合、私は最良のものが移動コンストラクタになると思います。
std :: anyのAPIのようなものですが、組み込みストレージサイズを定義するために利用可能な型が事前に宣言されていますか? 話題を少し外す
std :: variantはあなたが言っていることのように聞こえます。 anyは基本的にはオブジェクトに対して無効化されています。
std::variant sounds like what you're describing.
Aha, yes, that's what I want! If we have that, then it looks like:
uint8_t thread_stack[STACK_SIZE];
std::variant<std::monostate, rtos::Thread> store;
main() {
while(true) {
Thread &thread = store.emplace<Thread>(osPriorityNormal, sizeof(thread_stack), thread_stack);
thread.start();
running = false;
thread.join();
// If you wanted to manually destroy, but not needed in this example
// store.emplace<std::monostate>();
}
std :: variantはあなたが言っていることのように聞こえます。
ああ、はい、それは私が欲しいものです! それがあれば、それは次のようになります。
https://scrapbox.io/mbed/
関連
https://github.com/ARMmbed/mbed-os/issues/10914