2017-02-22 8 views
0

私は同時に複数のクライアントからの接続を許可するサーバーを作成しています。新しい接続ごとに新しいスレッドを作成します。クライアントはこのスレッドでサーバーと通信します。クライアントがサーバから切断されたときに、スレッドのメモリをサーバプロセスに割り振り解除する必要があります。C++スレッドが末尾で自分自身を削除する

問題は「スレッド自体を削除しようとする」ときです。

私の問題を説明するために少しコードを書いています。クラスCは新しい接続を表します。私はすべての接続に対してこのクラスの新しいオブジェクトを動的に作成します。機能のアクションは、問題を説明するために自発的に簡素化されています。

#include <thread> 
#include <iostream> 
#include <mutex> 
#include <chrono> 

using namespace std; 

mutex m; 

class C { 
    thread *t; 

    static void action(int n, C* obj) { 
    for (int i = 0; i < 10; i++) { 
     m.lock(); 
     cout << "i:" << i << ", n:" << n << endl; 
     m.unlock(); 
    } 
    delete(obj); 
    } 

    public: 
    C() : t(nullptr) {} 

    ~C() { 
     delete(t); // Work if I comment this line 
    } 

    void launch() { 
     static int i = 0; 
     t = new thread(action, i++, this); 
    } 

}; 

int main() { 
    C *c1 = new C(); 
    c1->launch(); 

    this_thread::sleep_for(chrono::seconds(5)); 
    return 0; 
} 

私の英語のために申し訳ありませんが、私はそれを学んでいます。

+0

なぜポインタを使用していますか?あなたは、あなたからのクリーンアップを必要としない自動オブジェクトでこれをすべて行うことができます。 – NathanOliver

+0

@LightnessRacesinOrbitこれは* C++ではなく、C#です。オリーブ:デモンストレーションされたコードでは、 'new'やポインタの必要はありません。 'namespace std;を使用しないでください。'、 'std'はあまりにも多くのシンボルを含んでいます。 – Yakk

+0

新しい接続ごとに新しいスレッドを作成するのではなく、スレッド_pool_を使用することを検討してください。あなたが使用できる良いスレッドプールの実装があるかどうかを知るには十分なC++を知りませんが、単純な考え方です:_tasks_のブロックキューがあります(この場合、各タスクは待機中のクライアントを表すオブジェクトですサーブしてください)、キューからタスクを永久にループしようとするループがいくつかあります。スレッドがタスクを獲得すると、スレッドはタスクを実行する(すなわち、それはクライアントに役立ちます)、死ぬのではなく、次のタスクを待つために戻ってきます。 –

答えて

2

std::threadを破壊する前に、t->join()に「参加」する必要があります。

this documentationを参照してください。

*thisは、関連するスレッド(joinable() == true)を有する場合、std::terminate()が呼び出されます。

もっと致命的なことですが、スレッド自体の中からすべてをやろうとしています。あなたはそれを行うことはできません。

例外
std::system_errorエラーが発生した場合。

エラー条件
resource_deadlock_would_occurthis->get_id() == std::this_thread::get_id()場合(デッドロックが検出された)

ところで、あなたはその動的な割り当てを失う必要があります。あなたはそれを必要としません。

+0

スレッドを削除する直前にスレッドに参加しようとすると、プログラムは例外 "std :: system_error"をスローします。 – olive007

+0

@ olive007: 'action'を詳しく見てみましょう。スレッド自体を削除しようとしているようです。どうして?あなたは 'resource_deadlock_would_occur'エラー状態になります。私はあなたのデザインを再訪すべきだと思います! –

+0

年それをやろうとしています。私は自分自身からスレッドを削除します。なぜなら、もし私がそれをしなければ、メモリリークと私のサーバはメモリを使いすぎてしまうからです。 – olive007

1

スレッドのデストラクタをjoinableと呼び出すことは、プログラムの終了として指定されます。 joinedまたはdetachedのいずれかである必要があります。

例外が発生したかのようにまた、あなたがそれらのRAIIヘルパーを使用して、ミューテックスのためlock_guardsする必要がありますが、正しくサイドノートとしてなど

ロックを解除しません:接続ごとに1つのスレッドを使用することが最善ではありませんあなたが同時接続の数が少ないと思わない限り、リソースの使用。

関連する問題