Make and use a semaphore class

master
Chris Robinson 2018-11-27 13:41:30 -08:00
parent 3f745be1dc
commit f26083e9ed
8 changed files with 59 additions and 30 deletions

View File

@ -2528,7 +2528,6 @@ static ALvoid InitContext(ALCcontext *Context)
Context->DopplerVelocity = 1.0f;
Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
alsem_init(&Context->EventSem, 0);
Context->ExtensionList = alExtList;
@ -2642,8 +2641,6 @@ ALCcontext_struct::~ALCcontext_struct()
}
TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s");
alsem_destroy(&EventSem);
ll_ringbuffer_free(AsyncEvents);
AsyncEvents = nullptr;

View File

@ -111,7 +111,7 @@ struct ALCcontext_struct {
std::atomic<ALeffectslotArray*> ActiveAuxSlots{nullptr};
std::thread EventThread;
alsem_t EventSem;
al::semaphore EventSem;
ll_ringbuffer *AsyncEvents{nullptr};
std::atomic<ALbitfieldSOFT> EnabledEvts{0u};
std::mutex EventCbLock;

View File

@ -313,7 +313,7 @@ void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
strcpy(evt.u.user.msg+strpos, " state changed to AL_STOPPED");
if(ll_ringbuffer_write(context->AsyncEvents, &evt, 1) == 1)
alsem_post(&context->EventSem);
context->EventSem.post();
}
@ -441,7 +441,7 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force)
props->State = NULL;
if(LIKELY(ll_ringbuffer_write(context->AsyncEvents, &evt, 1) != 0))
alsem_post(&context->EventSem);
context->EventSem.post();
else
{
/* If writing the event failed, the queue was probably full.
@ -1857,7 +1857,7 @@ void aluHandleDisconnect(ALCdevice *device, const char *msg, ...)
ALbitfieldSOFT enabledevt = ctx->EnabledEvts.load(std::memory_order_acquire);
if((enabledevt&EventType_Disconnected) &&
ll_ringbuffer_write(ctx->AsyncEvents, &evt, 1) == 1)
alsem_post(&ctx->EventSem);
ctx->EventSem.post();
std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire),
[ctx](ALvoice *voice) -> void

View File

@ -204,7 +204,7 @@ static void SendAsyncEvent(ALCcontext *context, ALuint enumtype, ALenum type,
evt.u.user.param = param;
strcpy(evt.u.user.msg, msg);
if(ll_ringbuffer_write(context->AsyncEvents, &evt, 1) == 1)
alsem_post(&context->EventSem);
context->EventSem.post();
}

View File

@ -705,7 +705,7 @@ void SendStateChangeEvent(ALCcontext *context, ALuint id, ALenum state)
* it through the async queue to ensure proper ordering.
*/
if(ll_ringbuffer_write(context->AsyncEvents, &evt, 1) == 1)
alsem_post(&context->EventSem);
context->EventSem.post();
}

View File

@ -23,7 +23,7 @@ static int EventThread(ALCcontext *context)
AsyncEvent evt;
if(ll_ringbuffer_read(context->AsyncEvents, &evt, 1) == 0)
{
alsem_wait(&context->EventSem);
context->EventSem.wait();
continue;
}
@ -66,7 +66,7 @@ void StopEventThrd(ALCcontext *ctx)
static constexpr AsyncEvent kill_evt = ASYNC_EVENT(EventType_KillThread);
while(ll_ringbuffer_write(ctx->AsyncEvents, &kill_evt, 1) == 0)
std::this_thread::yield();
alsem_post(&ctx->EventSem);
ctx->EventSem.post();
if(ctx->EventThread.joinable())
ctx->EventThread.join();
}

View File

@ -22,25 +22,7 @@
#include "threads.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifndef UNUSED
#if defined(__cplusplus)
#define UNUSED(x)
#elif defined(__GNUC__)
#define UNUSED(x) UNUSED_##x __attribute__((unused))
#elif defined(__LCLINT__)
#define UNUSED(x) /*@unused@*/ x
#else
#define UNUSED(x) x
#endif
#endif
#define THREAD_STACK_SIZE (2*1024*1024) /* 2MB */
#include <system_error>
#ifdef _WIN32
@ -116,6 +98,7 @@ int alsem_trywait(alsem_t *sem)
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
@ -210,3 +193,32 @@ int alsem_trywait(alsem_t *sem)
#endif /* __APPLE__ */
#endif
namespace al {
semaphore::semaphore(unsigned int initial)
{
if(alsem_init(&mSem, initial) != althrd_success)
throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again));
}
semaphore::~semaphore()
{ alsem_destroy(&mSem); }
void semaphore::post()
{
if(alsem_post(&mSem) != althrd_success)
throw std::system_error(std::make_error_code(std::errc::value_too_large));
}
void semaphore::wait() noexcept
{
while(alsem_wait(&mSem) == -2) {
}
}
int semaphore::trywait() noexcept
{ return alsem_wait(&mSem) == althrd_success; }
} // namespace al

View File

@ -63,6 +63,26 @@ int alsem_trywait(alsem_t *sem);
#ifdef __cplusplus
} // extern "C"
namespace al {
class semaphore {
alsem_t mSem;
public:
semaphore(unsigned int initial=0);
semaphore(const semaphore&) = delete;
~semaphore();
semaphore& operator=(const semaphore&) = delete;
void post();
void wait() noexcept;
int trywait() noexcept;
};
} // namespace al
#endif
#endif /* AL_THREADS_H */