Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.net  
   

Die mobilen Seiten von c++.net:
https://m.c-plusplus.net

  
C++ Forum :: Spiele-/Grafikprogrammierung ::  SDL_Mixer threading     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
PadMad
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.09.2013
Beiträge: 53
Beitrag PadMad Mitglied 11:52:09 05.03.2018   Titel:   SDL_Mixer threading            Zitieren

Heyho!

Ich habe ein kleines Problem mit SDL_Mixer und threading. Ich habe einen Abschnitt "init" in meinem Spiel, wo ich Sounds und Musik lade mithilfe von "SDL_LoadWAV". Klappt auch alles. Dann in einem der folgenden Abschnittent werden einige der Sounds gespielt mithilfe von "Mix_PlayChannel". Klappt auch alles.

Im Abschnitt "prepareLevel" soll einmalig ein neuer Thread gestartet werden, der parallel neue Sounds und andere Ressorcen laden soll. Das klappt auch alles. Allerdings hängt die ganze Anwendung kurz, bis "Mix_LoadWAV" fertig ist. Es ist auch definitiv diese Funktion, die die Applikation stoppt, weil ich die mal testweise rausgenommen habe und das parallel Laden dann flüssig geklappt hat und es kein Stoppen gab. Daher gibt es jetzt zwei Möglichkeiten:

1. Entweder beeinflusst "Mix_LoadWAV" den internen sample stream von SDL_Mixer, weil sich irgendwelche Ressorcen geteilt werden, die threading unmöglich machen.

2. Oder, da threading noch recht neu für mich ist, mache ich da irgendetwas falsch.

Hatte einer von euch schon einmal dieses Problem oder erkennt irgendeinen Fehler im Threading?

main.cpp:

Code:
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
int main(int argc, char * argv[])
{
  int result = 0;
  GameInstance game = new Game();
  LEMoonInstance engine = new LEMoon();
  MemoryOrganizer memoryOrganizer = new cMemoryOrganizer();
  memoryOrganizer->registerEngine(engine);
  result = engine->init("Solar Light");
  engine->setBackgroundColor(0, 0, 0);
 
  if(!result)
    {result = engine->initImage();}
 
  // game loop
 
  while(engine->pollEvent() || !result)
  {
    engine->beginFrame();
 
    // choose game state
 
    switch(game->getGameState())
    {
      case noState:
      {} break;
      case initPoster:
      {
        game->stageInitPoster(engine, memoryOrganizer);
      } break;
      case init:
      {
        game->stageInit(engine, memoryOrganizer);
      } break;
      case initInteraction:
      {
        game->stageInitInteraction(engine, memoryOrganizer);
      } break;
      case displayLogo:
      {
        game->stageDisplayLogo(engine, memoryOrganizer);
      } break;
      case displayMenuLoading:
      {
        game->stageDisplayMenuLoading(engine);
      } break;
      case menu:
      {
        game->stageMenu(engine);
      } break;
      case playButton:
      {
        game->stagePlayButton(engine);
      } break;
      case prepareLevel:
      {
        game->stagePrepareLevel(engine, memoryOrganizer);
 
        if(!game->t1Locked())
        {
          thread proc01(&Game::level1LoadProlog, game, engine, memoryOrganizer);
          game->lockT1(LE_TRUE);
          proc01.join();
        }
      } break;
      case controlsButton:
      {
        game->stageControlsButton(engine);
      } break;
      case credits:
      {
        game->stageCredits(engine);
      } break;
      case prolog:
      {
        game->stageProlog(engine);
 
        if(!game->t2Locked())
        {
          thread proc01(&Game::level1LoadIntroFlight, game, engine, memoryOrganizer);
          game->lockT2(LE_TRUE);
          game->lockT1(LE_FALSE);
          proc01.join();
        }
      } break;
      case prologVideo:
      {
        game->stagePrologVideo(engine);
      } break;
      case introFlight:
      {
        game->stageIntroFlight(engine);
 
        if(!game->t1Locked())
        {
          thread proc01(&Game::level1LoadAsteroidFlight, game, engine, memoryOrganizer);
          game->lockT1(LE_TRUE);
          game->lockT2(LE_FALSE);
          proc01.join();
        }
      } break;
      case asteroidFlight:
      {
        game->stageAsteroidFlight(engine);
 
        if(!game->t2Locked())
        {
          thread proc01(&Game::level1LoadSatelliteLevel, game, engine, memoryOrganizer);
          game->lockT2(LE_TRUE);
          game->lockT1(LE_FALSE);
          proc01.join();
        }
      } break;
      case satelliteReached:
      {
        game->stageSatelliteReached(engine);
      } break;
      case satellite:
      {
        game->stageSatellite(engine);
 
        if(!game->t1Locked())
        {
          thread proc01(&Game::memoryLevel1ComputerQuiz, game, engine, memoryOrganizer);
          game->lockT1(LE_TRUE);
          game->lockT2(LE_FALSE);
          proc01.join();
        }
      } break;
      case computerQuiz:
      {
        game->stageComputerQuiz(engine);
 
        if(!game->t2Locked())
        {
          thread proc01(&Game::level1LoadBrokenStationLevel, game, engine, memoryOrganizer);
          game->lockT2(LE_TRUE);
          game->lockT1(LE_FALSE);
          proc01.join();
        }
      } break;
      case satelliteQuiz:
      {
        game->stageSatelliteQuiz(engine);
      } break;
      case leaveSatellite:
      {
        game->stageLeaveSatellite(engine);
      } break;
      case stationDestroyed:
      {
        game->stageBrokenStation(engine);
      } break;
      case quit:
      {
        result = 1;
      } break;
    };
 
    #ifdef BUILD_DESKTOP
      if(engine->keyEvent(SDL_KEYDOWN, SDLK_ESCAPE))
      {
        if(game->getGameState() == menu)
          {result = 1;}
        else
        {
          if(game->getGameState() >= prolog)
          {
            game->level1Reset(engine);
            game->prepareMenuLoading(engine);
            game->setGameState(displayMenuLoading);
          }
        }
      }
    #endif
 
    if(game->getSkipFlag())
      {game->setSkipFlag(LE_FALSE);}
 
    if(engine->drawFrame())
      {result = 1;}
 
    engine->endFrame();
  }
 
  engine->delay(1000);
 
  delete memoryOrganizer;
  delete game;
  delete engine;
  return 0;
}


Game::level1LoadProlog:

Code:
void Game::level1LoadProlog(LEMoonInstance engine, MemoryOrganizer memoryOrganizer)
{
  this->memoryLevel1PrologPrio1(engine, memoryOrganizer);
  this->memoryLevel1PrologPrio2(engine, memoryOrganizer);
}


Game::memoryLevel1PrologPrio1:

Code:
void Game::memoryLevel1PrologPrio1(LEMoonInstance engine, MemoryOrganizer memoryOrganizer)
{
  memoryOrganizer->create(MEMORY_LVL1_PROLOG_PRIO_1);
  this->loadSkipWindow(engine, memoryOrganizer);
  memoryOrganizer->complete(MEMORY_LVL1_PROLOG_PRIO_1, LE_TRUE);
}


Game::memoryLevel1PrologPrio2:

Code:
1
2
3
4
5
6
7
8
9
10
11
12
void Game::memoryLevel1PrologPrio2(LEMoonInstance engine, MemoryOrganizer memoryOrganizer)
{
  memoryOrganizer->create(MEMORY_LVL1_PROLOG_PRIO_2);
 
  loadSun(engine, memoryOrganizer);
  loadSpaceStation(engine, memoryOrganizer);
  loadPrologTE(engine, memoryOrganizer);
  loadPrologMusic(engine, memoryOrganizer);
  loadPrologText(engine, memoryOrganizer);
 
  memoryOrganizer->complete(MEMORY_LVL1_PROLOG_PRIO_2, LE_TRUE);
}


loadPrologMusic:

Code:
void loadPrologMusic(LEMoonInstance engine, MemoryOrganizer memoryOrganizer)
{
  engine->soundCreate(MUSIC_PROLOG);
  engine->soundLoadWAV(MUSIC_PROLOG, FILE_MUSIC_PROLOG);
 
  memoryOrganizer->recordLoadedObject(MEMORY_LVL1_PROLOG_PRIO_2, LE_SOUND, MUSIC_PROLOG);
}


LEMoon::soundCreate:

Code:
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
int LEMoon::soundCreate(uint32_t id)
{
  #ifdef LE_MUTEX
    this->mtxSound.mtxAdd.lock();
  #endif
 
  int result = LE_NO_ERROR;
  LESound * pNew = this->soundGet(id);
 
  if(pNew == nullptr)
  {
    if(this->pSoundHead == nullptr)
    {
      this->pSoundHead = new LESound;
      this->pSoundHead->pLeft = this->pSoundHead;
      this->pSoundHead->pRight = this->pSoundHead;
    }
 
    pNew = new LESound;
    pNew->pLeft = this->pSoundHead->pLeft;
    pNew->pRight = this->pSoundHead;
    this->pSoundHead->pLeft->pRight = pNew;
    this->pSoundHead->pLeft = pNew;
    pNew->id = id;
    pNew->lock = LE_FALSE;
    pNew->pSample = nullptr;
  }
  else
  {
    #ifdef LE_DEBUG
      this->printErrorDialog(LE_SOUND_EXIST, "LEMoon::soundCreate()\n\n");
    #endif
 
    result = LE_SOUND_EXIST;
  }
 
  #ifdef LE_MUTEX
    this->mtxSound.mtxAdd.unlock();
  #endif
 
  return result;
}


LEMoon::soundLoadWAV:

Code:
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
int LEMoon::soundLoadWAV(uint32_t id, const char * pFile)
{
  int result = LE_NO_ERROR;
  LESound * pSound = this->soundGet(id);
 
  #ifdef LE_DEBUG
    char * pErrorString = new char[256 + 1];
  #endif
 
  if(pSound != nullptr)
  {
    if(pSound->pSample == nullptr)
    {
      pSound->pSample = Mix_LoadWAV(pFile);
 
      if(pSound->pSample == nullptr)
      {
        #ifdef LE_DEBUG
          sprintf(pErrorString, "LEMoon::soundLoadWAV()\n\nPath: %s\n\n", pFile);
          this->printErrorDialog(LE_LOAD_WAV, pErrorString);
        #endif
 
        result = LE_LOAD_WAV;
      }
    }
  }
  else
  {
    #ifdef LE_DEBUG
      this->printErrorDialog(LE_SOUND_NOEXIST, "LEMoon::soundLoadWAV()\n\n");
    #endif
 
    result = LE_SOUND_NOEXIST;
  }
 
  #ifdef LE_DEBUG
    delete [] pErrorString;
  #endif
 
  return result;
}


LEMoon::soundGet

Code:
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
LESound * LEMoon::soundGet(uint32_t id)
{
  LESound * pRet = nullptr;
  LESound * pCurrent = nullptr;
 
  if(this->pSoundHead != nullptr)
  {
    if(this->memory.pLastSound != nullptr && this->memory.pLastSound->id == id)
      {pRet = this->memory.pLastSound;}
    else
    {
      pCurrent = this->pSoundHead->pRight;
 
      while(pCurrent != this->pSoundHead)
      {
        if(pCurrent->id == id)
        {
          pRet = pCurrent;
          this->memory.pLastSound = pCurrent;
          break;
        }
 
        pCurrent = pCurrent->pRight;
      }
    }
  }
 
  return pRet;
}


LEMoon::soundPlay:

Code:
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
int LEMoon::soundPlay(uint32_t id, int loops)
{
  int result = LE_NO_ERROR;
  LESound * pSound = this->soundGet(id);
 
  if(pSound != nullptr)
  {
    if(!(pSound->lock))
    {
      if(Mix_PlayChannel(-1, pSound->pSample, loops) == -1)
      {
        #ifdef LE_DEBUG
          this->printErrorDialog(LE_PLAY_CHANNEL, "LEMoon::soundPlay()\n\n");
        #endif
 
        result = LE_PLAY_CHANNEL;
      }
    }
  }
  else
  {
    #ifdef LE_DEBUG
      this->printErrorDialog(LE_SOUND_NOEXIST, "LEMoon::soundPlay()\n\n");
    #endif
 
    result = LE_SOUND_NOEXIST;
  }
 
  return result;
}


Blockieren sich vielleicht die Mutex irgendwie? Ich würde nicht verstehen warum? Ich hoffe, dass die samples so ausreichen, da das ja doch ein sehr großes Projekt ist.

Gruß,
Patrick
rapso
Moderator

Benutzerprofil
Anmeldungsdatum: 17.06.2002
Beiträge: 8807
Beitrag rapso Moderator 18:09:06 05.03.2018   Titel:              Zitieren

ist SDL ueberhaupt threadsafe?

_________________
follow me|
-Mod im Spiele-/Grafikprogrammierung
PadMad
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.09.2013
Beiträge: 53
Beitrag PadMad Mitglied 18:18:04 05.03.2018   Titel:              Zitieren

Scheint es tatsächlich zu sein, da ich rendern und neue Texturen zur selben Zeit erstellen kann. Ich habe auch kein Problem beim threading, wenn es um SDL_TTF und SDL_image geht.
C++ Forum :: Spiele-/Grafikprogrammierung ::  SDL_Mixer threading   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.net ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.