- Removed the SoundChans bitfield from AActor, since it seems there are race

conditions I don't fully understand where it simply doesn't work.


SVN r1367 (trunk)
This commit is contained in:
Randy Heit 2009-01-25 01:52:38 +00:00
parent b6528a604e
commit 6ebbc920fb
5 changed files with 52 additions and 45 deletions

View file

@ -1,4 +1,6 @@
January 24, 2009 January 24, 2009
- Removed the SoundChans bitfield from AActor, since it seems there are race
conditions I don't fully understand where it simply doesn't work.
- Removed BaseTime initialization from sdl/i_system.cpp as per Chris's - Removed BaseTime initialization from sdl/i_system.cpp as per Chris's
recommendation. recommendation.

View file

@ -679,7 +679,6 @@ public:
TObjPtr<AActor> LastLookActor; // Actor last looked for (if TIDtoHate != 0) TObjPtr<AActor> LastLookActor; // Actor last looked for (if TIDtoHate != 0)
fixed_t SpawnPoint[3]; // For nightmare respawn fixed_t SpawnPoint[3]; // For nightmare respawn
WORD SpawnAngle; WORD SpawnAngle;
BYTE SoundChans; // Bitfield indicating which sound channels are playing.
int skillrespawncount; int skillrespawncount;
TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers
TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks) TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks)

View file

@ -135,7 +135,7 @@ public:
int Amount; // Amount of item this instance has int Amount; // Amount of item this instance has
int MaxAmount; // Max amount of item this instance can have int MaxAmount; // Max amount of item this instance can have
int RespawnTics; // Tics from pickup time to respawn time int RespawnTics; // Tics from pickup time to respawn time
FTextureID Icon; // Icon to show on status bar or HUD FTextureID Icon; // Icon to show on status bar or HUD
int DropTime; // Countdown after dropping int DropTime; // Countdown after dropping
const PClass *SpawnPointClass; // For respawning like Heretic's mace const PClass *SpawnPointClass; // For respawning like Heretic's mace

View file

@ -196,7 +196,8 @@ AInventory *AWeapon::CreateCopy (AActor *other)
// //
// A weapon that's tossed out should contain no ammo, so you can't cheat // A weapon that's tossed out should contain no ammo, so you can't cheat
// by dropping it and then picking it back up. // by dropping it and then picking it back up.
//======================= //
//===========================================================================
AInventory *AWeapon::CreateTossable () AInventory *AWeapon::CreateTossable ()
{ {

View file

@ -100,6 +100,7 @@ extern float S_GetMusicVolume (const char *music);
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit); static bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit);
static bool S_IsChannelUsed(AActor *actor, int channel, int *seen);
static void S_ActivatePlayList(bool goBack); static void S_ActivatePlayList(bool goBack);
static void CalcPosVel(FSoundChan *chan, FVector3 *pos, FVector3 *vel); static void CalcPosVel(FSoundChan *chan, FVector3 *pos, FVector3 *vel);
static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, const FPolyObj *poly, static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, const FPolyObj *poly,
@ -572,10 +573,6 @@ FISoundChannel *S_GetChannel(void *syschan)
void S_ReturnChannel(FSoundChan *chan) void S_ReturnChannel(FSoundChan *chan)
{ {
if (chan->SourceType == SOURCE_Actor && chan->Actor != NULL)
{
chan->Actor->SoundChans &= ~(1 << chan->EntChannel);
}
S_UnlinkChannel(chan); S_UnlinkChannel(chan);
memset(chan, 0, sizeof(*chan)); memset(chan, 0, sizeof(*chan));
S_LinkChannel(chan, &FreeChannels); S_LinkChannel(chan, &FreeChannels);
@ -950,20 +947,20 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
basepriority = 0; basepriority = 0;
} }
int seen = 0;
if (actor != NULL && channel == CHAN_AUTO) if (actor != NULL && channel == CHAN_AUTO)
{ // Select a channel that isn't already playing something. {
BYTE mask = actor->SoundChans; // Select a channel that isn't already playing something.
// Try channel 0 first, then travel from channel 7 down. // Try channel 0 first, then travel from channel 7 down.
if ((mask & 1) == 0) if (!S_IsChannelUsed(actor, 0, &seen))
{ {
channel = 0; channel = 0;
} }
else else
{ {
for (channel = 7; channel > 0; --channel, mask <<= 1) for (channel = 7; channel > 0; --channel)
{ {
if ((mask & 0x80) == 0) if (!S_IsChannelUsed(actor, channel, &seen))
{ {
break; break;
} }
@ -976,7 +973,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
} }
// If this actor is already playing something on the selected channel, stop it. // If this actor is already playing something on the selected channel, stop it.
if (type != SOURCE_None && ((actor == NULL && channel != CHAN_AUTO) || (actor != NULL && actor->SoundChans & (1 << channel)))) if (type != SOURCE_None && ((actor == NULL && channel != CHAN_AUTO) || (actor != NULL && S_IsChannelUsed(actor, channel, &seen))))
{ {
for (chan = Channels; chan != NULL; chan = chan->NextChan) for (chan = Channels; chan != NULL; chan = chan->NextChan)
{ {
@ -1068,7 +1065,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
chan->SourceType = type; chan->SourceType = type;
switch (type) switch (type)
{ {
case SOURCE_Actor: chan->Actor = actor; actor->SoundChans |= 1 << channel; break; case SOURCE_Actor: chan->Actor = actor; break;
case SOURCE_Sector: chan->Sector = sec; break; case SOURCE_Sector: chan->Sector = sec; break;
case SOURCE_Polyobj: chan->Poly = poly; break; case SOURCE_Polyobj: chan->Poly = poly; break;
case SOURCE_Unattached: chan->Point[0] = pt->X; chan->Point[1] = pt->Y; chan->Point[2] = pt->Z; break; case SOURCE_Unattached: chan->Point[0] = pt->X; chan->Point[1] = pt->Y; chan->Point[2] = pt->Z; break;
@ -1139,17 +1136,10 @@ void S_RestartSound(FSoundChan *chan)
ochan = (FSoundChan*)GSnd->StartSound(sfx->data, chan->Volume, chan->Pitch, startflags, chan); ochan = (FSoundChan*)GSnd->StartSound(sfx->data, chan->Volume, chan->Pitch, startflags, chan);
} }
assert(ochan == NULL || ochan == chan); assert(ochan == NULL || ochan == chan);
if (ochan != NULL) if (ochan == NULL)
{ {
// When called from the savegame loader, the actor's SoundChans chan->ChanFlags = oldflags;
// flags will be cleared. During normal gameplay, they should still
// be set.
if (ochan->SourceType == SOURCE_Actor)
{
if (ochan->Actor != NULL) ochan->Actor->SoundChans |= 1 << ochan->EntChannel;
}
} }
else chan->ChanFlags = oldflags;
} }
//========================================================================== //==========================================================================
@ -1390,17 +1380,13 @@ void S_StopSound (int channel)
void S_StopSound (AActor *actor, int channel) void S_StopSound (AActor *actor, int channel)
{ {
// No need to search every channel if we know it's not playing anything. for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
if (actor != NULL && actor->SoundChans & (1 << channel))
{ {
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) if (chan->SourceType == SOURCE_Actor &&
chan->Actor == actor &&
(chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE)))
{ {
if (chan->SourceType == SOURCE_Actor && S_StopChannel(chan);
chan->Actor == actor &&
(chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE)))
{
S_StopChannel(chan);
}
} }
} }
} }
@ -1502,11 +1488,6 @@ void S_RelinkSound (AActor *from, AActor *to)
} }
} }
} }
if (to != NULL)
{
to->SoundChans = from->SoundChans;
}
from->SoundChans = 0;
} }
//========================================================================== //==========================================================================
@ -1567,6 +1548,36 @@ bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id)
return false; return false;
} }
//==========================================================================
//
// S_IsChannelUsed
//
// Returns true if the channel is in use. Also fills in a bitmask of
// channels seen while scanning for this one, to make searching for unused
// channels faster. Initialize seen to 0 for the first call.
//
//==========================================================================
bool S_IsChannelUsed(AActor *actor, int channel, int *seen)
{
if (*seen & (1 << channel))
{
return true;
}
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
{
if (chan->SourceType == SOURCE_Actor && chan->Actor == actor)
{
*seen |= 1 << chan->EntChannel;
if (chan->EntChannel == channel)
{
return true;
}
}
}
return false;
}
//========================================================================== //==========================================================================
// //
// S_IsActorPlayingSomething // S_IsActorPlayingSomething
@ -1575,11 +1586,6 @@ bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id)
bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id)
{ {
if (actor->SoundChans == 0)
{
return false;
}
if (i_compatflags & COMPATF_MAGICSILENCE) if (i_compatflags & COMPATF_MAGICSILENCE)
{ {
channel = 0; channel = 0;
@ -1933,9 +1939,8 @@ void S_StopChannel(FSoundChan *chan)
chan->ChanFlags |= CHAN_FORGETTABLE; chan->ChanFlags |= CHAN_FORGETTABLE;
} }
if (chan->SourceType == SOURCE_Actor && chan->Actor != NULL) if (chan->SourceType == SOURCE_Actor)
{ {
chan->Actor->SoundChans &= ~(1 << chan->EntChannel);
chan->Actor = NULL; chan->Actor = NULL;
} }