IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Threads & Processus C++ Discussion :

Classes partagées entre deux threads, et erreur sur select()


Sujet :

Threads & Processus C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Par défaut Classes partagées entre deux threads, et erreur sur select()
    Bonjour !

    Alors voici la premiere classe qui est partagée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
     
    #ifndef SELECTOR_H
    #define SELECTOR_H
     
     
    #if defined __MINGW32__
        #include <winsock2.h>
    #elif defined __GNUC__
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <unistd.h>
        #define INVALID_SOCKET -1
        #define SOCKET_ERROR -1
    #endif
    #include <map>
    #include <vector>
    #include <iostream>
     
    #include "SessionsCollection.h"
     
    class ServerSocket;
    class Selector
    {
        public:
     
            static const int NO_ACTIVITY = 0;
     
            /** Default constructor */
            Selector(ServerSocket* ss, SessionsCollection* sc)
            {
                server = ss;
                sessions = sc;
                online = false;
                _maxfd = 0;
            };
            /** Default destructor */
            ~Selector() {};
            int Select()
            {
                int r = (online) ? ((_maxfd == 0) ? NO_ACTIVITY : select(_maxfd, &recvfs, NULL, NULL, NULL)) : -1;
                return r;
            }
            bool Ready(int sock)
            {
                bool r = (FD_ISSET(sock, &recvfs) == 0) ? false : true;
                std::cout << "ready? " << sock << ((r) ? "yes":"no")<<std::endl;
                return r;
            }
            void Add(int sock)
            {
                FD_SET(sock, &recvfs);
                _maxfd = sock+1;
                std::cout << "Added " << sock << " to recvfs"<<std::endl;
            }
            void Delete(int sock)
            {
                todelete.push_back(sock);
            }
            void Mod(int oldsock, int newsock)
            {
                FD_CLR(oldsock, &recvfs);
                _maxfd = 0;
                FD_SET(newsock, &recvfs);
                for(auto itr = sessions->AllSessions().begin(); itr != sessions->AllSessions().end(); ++itr)
                {
                    if(itr->first > _maxfd)
                    {
                        _maxfd = itr->first;
                    }
                }
            }
            void Flush()
            {
                int sock;
                for(auto itr = todelete.begin(); itr != todelete.end(); ++itr)
                {
                    sock = *itr;
                    FD_CLR(sock, &recvfs);
                    _maxfd = 0;
                    for(auto itr = sessions->AllSessions().begin(); itr != sessions->AllSessions().end(); ++itr)
                    {
                        if(itr->first > _maxfd)
                        {
                            _maxfd = itr->first;
                        }
                    }
                    sessions->DeleteSession(sock);
                }
                todelete.clear();
            }
     
            Session* operator[] (int sock)
            {
                return ((sessions->AllSessions().find(sock) != sessions->AllSessions().end()) ? sessions->AllSessions()[sock] : NULL);
            }
            inline ServerSocket* Server() { return server; }
            void PutOnline(bool o) { online = o; }
        private:
     
            ServerSocket* server;
            SessionsCollection* sessions;
            std::vector<int> todelete;
     
            fd_set recvfs;
            int _maxfd;
            bool online;
    };
     
    #endif // SELECTOR_H
    Voici la deuxieme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    #ifndef SESSIONSF_H
    #define SESSIONSF_H
     
    #include <map>
    #include <iostream>
     
    #include "../Tools/Session.h"
     
    class Selector;
    class SessionsCollection
    {
        public:
            /** Default constructor */
            SessionsCollection()
            {
            };
            /** Default destructor */
            ~SessionsCollection() {};
     
            void CreateSession(const std::string& ip, const int sock, Selector* slt)
            {
                _sessions[sock] = new Session(ip, sock, slt);
                std::cout << "we have now " << _sessions.size() << " clients"<<std::endl;
            }
            void DeleteSession(int sock)
            {
     
                delete _sessions[sock];
                _sessions.erase(_sessions.find(sock));
     
            }
            inline map<int, Session*>& AllSessions() { return _sessions; }
            inline const int Count() { return _sessions.size(); }
     
            void Mod(int oldsock, int newsock)
            {
     
                Session* buf = _sessions[oldsock];
                buf->newSock(newsock);
                _sessions.erase(_sessions.find(oldsock));
                _sessions[newsock] = buf;
            }
            Session* operator[] (int sock)
            {
                return ((_sessions.find(sock) != _sessions.end()) ? _sessions[sock] : NULL);
            }
        private:
     
            std::map<int, Session*> _sessions;
    };
     
    #endif // SESSIONS_H

    Elles sont donc partagée entre le main(), qui accepte les connexions entrantes, et un thread qui sert exclusivement à la réception des données.


    La premiere classe est utilisée pour les macros FD*, ainsi que la fonction select.
    La deuxieme est une collections de mes sessions, et permet d'en ajouter/supprimer/modifier.

    Ces deux classes sont protegée par un mutex, pour eviter les conflits:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifndef SHARED_H_INCLUDED
    #define SHARED_H_INCLUDED
     
    #include <pthread.h>
     
    static pthread_mutex_t SharedMutex = PTHREAD_MUTEX_INITIALIZER;
     
    void LockSharedMutex();
    void UnlockSharedMutex();
     
    #endif // SHARED_H_INCLUDED

    Passons au boucles, voici la boucle dans le main, qui sert à accepter mes connexions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        while(!shutdown)
        {
            Incoming = acceptor->Accept();
            if(Incoming.Error == 0)
            {
                LockSharedMutex();
                sessions->CreateSession(Incoming.IP, Incoming.Socket, selector);
                selector->Add(Incoming.Socket);
                UnlockSharedMutex();
            }
        }
    Ca marche bien, il y a des cout dans CreateSession() & Add(). Aucun probleme.

    Dans le thread, j'ai ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
        while(!shutdown)
        {
            LockSharedMutex();
            std::cout << "thread: locked mutex" << std::endl;
            if(Selectr->Select() < 0 || Collection->Count() == 0)
            {
                int e = WSAGetLastError();
                if (e != 0)
                {
                    std::cout << "WSA Error: " << e << std::endl;
                    UnlockSharedMutex();
                    exit(0);
                }
                std::cout << "thread: UNLOCKED MUTEX !" << std::endl;
                UnlockSharedMutex();
                continue;
            }
            std::cout << "has activicty, loopin on clientz" << std::endl;
            for(auto itr = Collection->AllSessions().begin(); itr != Collection->AllSessions().end(); ++itr)
            {
                Target = itr->second;
                std::cout << "loop over client (sock=" << itr->first << " /// " << Target->GetSocket() << std::endl;
                /* code très long :D */
            }
            Selectr->Flush();
            UnlockSharedMutex();
            std::cout << "thread: UNLOCKED MUTEX !" << std::endl;
        }

    Voici un apercu du probleme :


    Le select ne marche donc pas juste apres l'ajout d'un socket dans le descripteur de fichiers.

    Une idée ?

    merci, nico.

  2. #2
    Membre très actif
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Par défaut
    Hum.
    Je viens de trouver le probleme. Il fallait initialiser la liste recvfs...

    J'ai à la place l'erreur 10022. timeout ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme d'interblocage entre deux Thread
    Par brahimouledriah dans le forum Concurrence et multi-thread
    Réponses: 1
    Dernier message: 08/11/2007, 09h20
  2. synchronisation entre deux threads
    Par chabfive dans le forum Concurrence et multi-thread
    Réponses: 9
    Dernier message: 03/11/2006, 12h17
  3. Opération mathématique entre deux Threads
    Par rvzip64 dans le forum Langage
    Réponses: 11
    Dernier message: 13/06/2005, 11h58
  4. Communication entre deux Threads
    Par rvzip64 dans le forum Langage
    Réponses: 13
    Dernier message: 28/01/2005, 09h14
  5. TList partagée entre deux process.
    Par swirtel dans le forum C++Builder
    Réponses: 2
    Dernier message: 10/01/2005, 11h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo