コード例 #1
0
ファイル: ServerAgent.cpp プロジェクト: Philbywhizz/pioneer
HTTPServerAgent::~HTTPServerAgent()
{
	// flush the queue
	SDL_LockMutex(m_requestQueueLock);
	while (m_requestQueue.size() > 0)
		m_requestQueue.pop();
	SDL_UnlockMutex(m_requestQueueLock);

	// signal the thread. empty queue will cause it to exit
	SDL_CondBroadcast(m_requestQueueCond);

	// first thing the queue does is check the queue, so we must
	// not shut down until its done that. it will release the queue
	// lock before it dies, so try to take it
	SDL_LockMutex(m_requestQueueLock);

	// we have the lock, so we know the thread won't doing anything
	// else. we can clean up now
	SDL_DestroyMutex(m_responseQueueLock);
	SDL_DestroyMutex(m_requestQueueLock);
	SDL_DestroyCond(m_requestQueueCond);

	curl_slist_free_all(m_curlHeaders);

	curl_easy_cleanup(m_curl);
}
コード例 #2
0
ThreadPool::~ThreadPool() {
	waitAll();

	// this is the hint for all available threads to break
	SDL_mutexP(mutex); // lock to be sure that every thread is outside that region, we could get crashes otherwise
	nextAction = NULL;
	quitting = true;
	SDL_CondBroadcast(awakeThread);
	for(std::set<ThreadPoolItem*>::iterator i = availableThreads.begin(); i != availableThreads.end(); ++i) {
		SDL_mutexV(mutex);
		SDL_WaitThread((*i)->thread, NULL);
		SDL_mutexP(mutex);
		SDL_DestroyCond((*i)->finishedSignal);
		SDL_DestroyCond((*i)->readyForNewWork);
		delete *i;
	}
	availableThreads.clear();
	SDL_mutexV(mutex);
	
	SDL_DestroyMutex(startMutex);
	SDL_DestroyCond(threadStartedWork);
	SDL_DestroyCond(threadStatusChanged);
	SDL_DestroyCond(awakeThread);
	SDL_DestroyMutex(mutex);
}
コード例 #3
0
ファイル: thread_sdl.c プロジェクト: CyberSys/darkplaces
int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
{
#ifdef THREADDEBUG
	Sys_PrintfToTerminal("%p cond broadcast %s:%i\n"   , cond, filename, fileline);
#endif
	return SDL_CondBroadcast((SDL_cond *)cond);
}
コード例 #4
0
ファイル: JobQueue.cpp プロジェクト: Loki999/pioneer
JobQueue::~JobQueue()
{
	// flag shutdown. protected by the queue lock for convenience in GetJob
	SDL_LockMutex(m_queueLock);
	m_shutdown = true;
	SDL_UnlockMutex(m_queueLock);

	// broadcast to any waiting runners that they should try (and fail) to get
	// a new job right now
	SDL_CondBroadcast(m_queueWaitCond);

	const uint32_t numThreads = m_runners.size();
	// delete the runners. this will tear down their underlying threads
	for (std::vector<JobRunner*>::iterator i = m_runners.begin(); i != m_runners.end(); ++i)
		delete (*i);

	// delete any remaining jobs
	for (std::deque<Job*>::iterator i = m_queue.begin(); i != m_queue.end(); ++i)
		delete (*i);
	for (uint32_t threadIdx=0; threadIdx<numThreads; threadIdx++) {
		for (std::deque<Job*>::iterator i = m_finished[threadIdx].begin(); i != m_finished[threadIdx].end(); ++i) {
			delete (*i);
		}
	}

	// only us left now, we can clean up and get out of here
	for (uint32_t threadIdx=0; threadIdx<numThreads; threadIdx++) {
		SDL_DestroyMutex(m_finishedLock[threadIdx]);
	}
	SDL_DestroyCond(m_queueWaitCond);
	SDL_DestroyMutex(m_queueLock);
}
コード例 #5
0
ファイル: Event.cpp プロジェクト: zeebok/SDL_Threadpool
void Event::trigger(void)
{
    SDL_LockMutex(mut);
    triggered = true;
    SDL_CondBroadcast(cond);
    SDL_UnlockMutex(mut);
}
コード例 #6
0
ファイル: ServerAgent.cpp プロジェクト: Philbywhizz/pioneer
void HTTPServerAgent::Call(const std::string &method, const Json::Value &data, SuccessCallback onSuccess, FailCallback onFail, void *userdata)
{
	SDL_LockMutex(m_requestQueueLock);
	m_requestQueue.push(Request(method, data, onSuccess, onFail, userdata));
	SDL_UnlockMutex(m_requestQueueLock);

	SDL_CondBroadcast(m_requestQueueCond);
}
コード例 #7
0
ファイル: thread.cpp プロジェクト: ArtBears/wesnoth
bool condition::notify_all()
{
	if(SDL_CondBroadcast(cond_) < 0) {
		ERR_G << "SDL_CondBroadcast: " << SDL_GetError() << std::endl;
		return false;
	}
	return true;
}
コード例 #8
0
ファイル: thread.cpp プロジェクト: kimsama/frogatto
bool condition::notify_all()
{
	if(SDL_CondBroadcast(cond_) < 0) {
		std::cerr << "SDL_CondBroadcast: " << SDL_GetError() << "\n";
		return false;
	}
	return true;
}
コード例 #9
0
ファイル: eventthread.cpp プロジェクト: AngryPowman/mkxp
void SyncPoint::Util::unlock(bool multi)
{
	locked.clear();

	if (multi)
		SDL_CondBroadcast(cond);
	else
		SDL_CondSignal(cond);
}
コード例 #10
0
ファイル: sdl2_mutex.c プロジェクト: Moon4u/mruby-sdl2
static mrb_value
mrb_sdl2_cond_broadcast(mrb_state *mrb, mrb_value self)
{
  mrb_sdl2_cond_data_t *data =
    (mrb_sdl2_cond_data_t*)mrb_data_get_ptr(mrb, self, &mrb_sdl2_cond_data_type);
  if (NULL == data->cond) {
    return mrb_nil_value();
  }
  if (0 > SDL_CondBroadcast(data->cond)) {
    mruby_sdl2_raise_error(mrb);
  }
  return self;
}
コード例 #11
0
ファイル: mt.cpp プロジェクト: sopyer/Infinity
    static int SDLCALL threadpoolThread(void* poolPtr)
    {
        threadpool_t*   pool = (threadpool_t*)poolPtr;
        task_t          task;

        for(;;)
        {
            /* Lock must be taken to wait on conditional variable */
            SDL_LockMutex(pool->lock);

            /* Wait on condition variable, check for spurious wakeups.
               When returning from pthread_cond_wait(), we own the lock. */
            while((pool->count == 0) && (!pool->shutdown))
            {
                SDL_CondWait(pool->notify, pool->lock);
            }

            if(pool->shutdown)
            {
                break;
            }

            /* Grab our task */
            task.function = pool->queue[pool->head].function;
            task.argument = pool->queue[pool->head].argument;
            task.event    = pool->queue[pool->head].event;

            pool->head += 1;
            pool->head = (pool->head == pool->queue_size) ? 0 : pool->head;
            pool->count -= 1;

            /* Unlock */
            SDL_UnlockMutex(pool->lock);

            (*(task.function))(task.argument);

            if (task.event)
            {
                SDL_LockMutex(task.event->mutex);
                task.event->signaled = true;
                SDL_CondBroadcast(task.event->cond);
                SDL_UnlockMutex(task.event->mutex);
            }
        }

        pool->started--;

        SDL_UnlockMutex(pool->lock);

        return 0;
    }
コード例 #12
0
ファイル: sync_sdl.c プロジェクト: crazii/mameplus
void osd_event_set(osd_event *event)
{
	LOG(("osd_event_set"));
	SDL_mutexP(event->mutex);
	if (event->signalled == FALSE)
	{
		event->signalled = TRUE;
		if (event->autoreset)
			SDL_CondSignal(event->cond);
		else
			SDL_CondBroadcast(event->cond);
	}
	SDL_mutexV(event->mutex);
}
コード例 #13
0
ファイル: physics.cpp プロジェクト: KazzyMac/RollCageX
int physics_loop (void *d)
{
	printlog(1, "Starting physics loop");

	Uint32 simtime = SDL_GetTicks(); //set simulated time to realtime
	Uint32 realtime; //real time (with possible delay since last update)
	Uint32 stepsize_ms = internal.stepsize*1000+0.0001;

	while (runlevel == running)
	{
		//technically, collision detection doesn't need this, but this is easier
		SDL_mutexP(ode_mutex);

		Car::Physics_Step(); //control, antigrav...
		Body::Physics_Step(); //drag (air/liquid "friction")

		dSpaceCollide (space, 0, &Geom::Collision_Callback);
		dWorldQuickStep (world, internal.stepsize);
		dJointGroupEmpty (contactgroup);

		Collision_Feedback::Physics_Step(); //forces from collisions
		Joint::Physics_Step(); //joint forces
		Geom::Physics_Step(); //sensor/radar handling
		camera.Physics_Step(); //move camera to wanted postion

		//done with ode
		SDL_mutexV(ode_mutex);
		
		Graphic_List_Update(); //make copy of position/rotation for rendering

		//broadcast to wake up sleeping threads
		if (internal.sync_events || internal.sync_graphics)
		{
			SDL_mutexP(sync_mutex);
			SDL_CondBroadcast (sync_cond);
			SDL_mutexV(sync_mutex);
		}

		simtime += stepsize_ms;
		realtime = SDL_GetTicks();
		if (simtime > realtime)
			SDL_Delay (simtime - realtime);
		else
			++stepsize_warnings;
	}
	return 0;
}
コード例 #14
0
ファイル: work_queue.hpp プロジェクト: ahockersten/liero
	~WorkQueue()
	{
		{
			LockMutex m(queueMutex);

			queueAlive = false;
			SDL_CondBroadcast(queueCond);
		}

		for (int i = 0; i < 8; ++i)
		{
			int status;
			if (threads[i])
				SDL_WaitThread(threads[i], &status);
		}

		SDL_DestroyMutex(queueMutex);
		SDL_DestroyCond(queueCond);
	}
コード例 #15
0
/* Nescessary logic:
 * 1) All threads must pass unblocked
 * 2) Current handler must always pass unblocked
 * 3) Threads must be excluded when irq routine is running
 * 4) No more than one handler routine should execute at a time
 */
int set_irq_level(int level)
{
    SDL_LockMutex(sim_irq_mtx);

    int oldlevel = interrupt_level;

    if (status_reg == 0 && level == 0 && oldlevel != 0)
    {
        /* Not in a handler and "interrupts" are going from disabled to
         * enabled; signal any pending handlers still waiting */
        if (handlers_pending > 0)
            SDL_CondBroadcast(sim_thread_cond);
    }

    interrupt_level = level; /* save new level */

    SDL_UnlockMutex(sim_irq_mtx);
    return oldlevel;
}
コード例 #16
0
ファイル: async.c プロジェクト: mpapierski/SDL_async
void Async_Free()
{
	int i;
	// Stop all threads
	G_is_running = 0;
	// Notify all threads
	SDL_CondBroadcast(G_queue_cond);
	// Wait for threads
	for (i = 0; i < G_thread_count; i++)
	{
		if (G_threads[i])
		{
			SDL_WaitThread(G_threads[i], NULL);
		}
	}
	free(G_threads);
	SDL_DestroyCond(G_queue_cond);
	SDL_DestroyMutex(G_queue_guard);
}
コード例 #17
0
ファイル: JobQueue.cpp プロジェクト: Ikesters/pioneer
AsyncJobQueue::~AsyncJobQueue()
{
	// flag shutdown. protected by the queue lock for convenience in GetJob
	SDL_LockMutex(m_queueLock);
	m_shutdown = true;
	SDL_UnlockMutex(m_queueLock);

	// broadcast to any waiting runners that they should try (and fail) to get
	// a new job right now
	SDL_CondBroadcast(m_queueWaitCond);

	// Flag each job runner that we're being destroyed (with lock so no one
	// else is running one of our functions). Both the flag and the mutex
	// must be owned by the runner, because we may not exist when it's
	// checked.
	for (std::vector<JobRunner*>::iterator i = m_runners.begin(); i != m_runners.end(); ++i) {
		SDL_LockMutex((*i)->GetQueueDestroyingLock());
		(*i)->SetQueueDestroyed();
		SDL_UnlockMutex((*i)->GetQueueDestroyingLock());
	}

	const uint32_t numThreads = m_runners.size();
	// delete the runners. this will tear down their underlying threads
	for (std::vector<JobRunner*>::iterator i = m_runners.begin(); i != m_runners.end(); ++i)
		delete (*i);

	// delete any remaining jobs
	for (std::deque<Job*>::iterator i = m_queue.begin(); i != m_queue.end(); ++i)
		delete (*i);
	for (uint32_t threadIdx=0; threadIdx<numThreads; threadIdx++) {
		for (std::deque<Job*>::iterator i = m_finished[threadIdx].begin(); i != m_finished[threadIdx].end(); ++i) {
			delete (*i);
		}
	}

	// only us left now, we can clean up and get out of here
	for (uint32_t threadIdx=0; threadIdx<numThreads; threadIdx++) {
		SDL_DestroyMutex(m_finishedLock[threadIdx]);
	}
	SDL_DestroyCond(m_queueWaitCond);
	SDL_DestroyMutex(m_queueLock);
}
コード例 #18
0
ファイル: sdl.cpp プロジェクト: havlenapetr/Scummvm
void OSystem_SDL::deinitThreadedMixer() {
	// Kill thread?? _soundThread

	if (_soundThreadIsRunning) {
		// Signal the producer thread to end, and wait for it to actually finish.
		_soundThreadShouldQuit = true;
		SDL_CondBroadcast(_soundCond);
		SDL_WaitThread(_soundThread, NULL);

		// Kill the mutex & cond variables.
		// Attention: AT this point, the mixer callback must not be running
		// anymore, else we will crash!
		SDL_DestroyMutex(_soundMutex);
		SDL_DestroyCond(_soundCond);

		_soundThreadIsRunning = false;

		free(_soundBuffers[0]);
		free(_soundBuffers[1]);
	}
}
コード例 #19
0
ファイル: bxbgprocess.cpp プロジェクト: flyingtime/boxee
void BXBGProcess::Resume()
{
  if (!m_bPaused) return;

  Lock();
  std::map<int, BXBGJob*>::iterator it = m_inProgressMap.begin();
  for (;it != m_inProgressMap.end(); it++) {
	  BXBGJob *pJob = it->second;
	  if (pJob) {
		  pJob->Resume();
	  }
  }
  Unlock();

  // Lock the pause mutex
  SDL_LockMutex(m_pPauseLock);
  // Update the pause protected variable
  m_bPaused = false;
  // Signal the condition variable so that the threads would resume working
  SDL_CondBroadcast(m_pPauseCond);
  // Unlock the mutex back
  SDL_UnlockMutex(m_pPauseLock);
}
コード例 #20
0
ファイル: new_update.c プロジェクト: MerkeX/Eternal-Lands
static void wait_for_threads(download_files_thread_data_t *data, Uint32* error)
{
	Sint32 result;
	Uint32 i;

	CHECK_AND_LOCK_MUTEX(data->mutex);

	if (*error == 0)
	{
		data->running = 2;
	}
	else
	{
		data->running = 0;
	}

	CHECK_AND_UNLOCK_MUTEX(data->mutex);

	for (i = 0; i < UPDATE_DOWNLOAD_THREAD_COUNT; i++)
	{
		SDL_CondBroadcast(data->condition);
		SDL_WaitThread(data->threads[i], &result);

		if (*error == 0)
		{
			*error = result;
		}
	}

	SDL_DestroyMutex(data->mutex);
	SDL_DestroyCond(data->condition);

	while (queue_pop(data->files) != 0);

	queue_destroy(data->files);
}
コード例 #21
0
ファイル: mt.cpp プロジェクト: sopyer/Infinity
    void fini()
    {
        if (SDL_LockMutex(pool.lock) != 0)
        {
            return;
        }

        do
        {
            /* Already shutting down */
            if(pool.shutdown)
            {
                break;
            }

            pool.shutdown = 1;

            /* Wake up all worker threads */
            if (SDL_CondBroadcast(pool.notify) != 0 ||
                SDL_UnlockMutex(pool.lock) != 0)
            {
                break;
            }

            /* Join all worker thread */
            for(int i = 0; i < pool.thread_count; i++)
            {
                SDL_WaitThread(pool.threads[i], NULL);
            }
        }
        while(0);

        SDL_UnlockMutex(pool.lock);
    
        releaseMTResources();
    }
コード例 #22
0
ファイル: taskmanager.c プロジェクト: laochailan/taisei
static void taskmgr_finalize_and_wait(TaskManager *mgr, bool abort) {
	log_debug(
		"%08lx [%p] waiting for %u tasks (abort = %i)",
		SDL_ThreadID(),
		(void*)mgr,
		taskmgr_remaining(mgr),
		abort
	);

	assert(mgr->running);
	assert(!mgr->aborted);

	SDL_LockMutex(mgr->mutex);
	mgr->running = false;
	mgr->aborted = abort;
	SDL_CondBroadcast(mgr->cond);
	SDL_UnlockMutex(mgr->mutex);

	for(uint i = 0; i < mgr->numthreads; ++i) {
		SDL_WaitThread(mgr->threads[i], NULL);
	}

	taskmgr_free(mgr);
}
コード例 #23
0
ファイル: threads.cpp プロジェクト: PaulForey/lovepd
	void Conditional::broadcast()
	{
		SDL_CondBroadcast(cond);
	}
コード例 #24
0
ファイル: mt.c プロジェクト: yoanlcq/FATE
void fe_mt_cond_broadcast(fe_mt_cond *cond) { SDL_CondBroadcast(*cond); }
コード例 #25
0
ファイル: music_openal.c プロジェクト: ekrumme/naev
/**
 * @brief The music thread.
 *
 *    @param unused Unused.
 */
static int music_thread( void* unused )
{
   (void)unused;

   int ret;
   int active; /* active buffer */
   ALint state;
   ALuint removed[2];
   ALenum value;
   music_state_t cur_state;
   ALfloat gain;
   int fadein_start = 0;
   uint32_t fade, fade_timer = 0;

   while (1) {

      /* Handle states. */
      musicLock();

      /* Handle new command. */
      switch (music_command) {
         case MUSIC_CMD_KILL:
            if (music_state != MUSIC_STATE_IDLE)
               music_state = MUSIC_STATE_STOPPING;
            else {
               music_state = MUSIC_STATE_DEAD;
            }
            /* Does not clear command. */
            break;

         case MUSIC_CMD_STOP:
            /* Notify of stopped. */
            if (music_state == MUSIC_STATE_IDLE)
               SDL_CondBroadcast( music_state_cond );
            else
               music_state = MUSIC_STATE_STOPPING;
            break;

         case MUSIC_CMD_PLAY:
            /* Set appropriate state. */
            if (music_state == MUSIC_STATE_PAUSING)
               music_state = MUSIC_STATE_RESUMING;
            else if (music_state == MUSIC_STATE_FADEIN)
               fade_timer = SDL_GetTicks() - MUSIC_FADEIN_DELAY;
            else
               music_state = MUSIC_STATE_LOADING;
            /* Disable fadein. */
            fadein_start = 0;
            /* Clear command. */
            music_command = MUSIC_CMD_NONE;
            SDL_CondBroadcast( music_state_cond );
            break;

         case MUSIC_CMD_FADEOUT:
            /* Notify of stopped. */
            if (music_state != MUSIC_STATE_IDLE) {
               music_state = MUSIC_STATE_FADEOUT;
               /* Set timer. */
               fade_timer = SDL_GetTicks();
            }
            /* Clear command. */
            music_command = MUSIC_CMD_NONE;
            SDL_CondBroadcast( music_state_cond );
            break;

         case MUSIC_CMD_FADEIN:
            if ((music_state == MUSIC_STATE_FADEIN) ||
                  (music_state == MUSIC_STATE_PLAYING))
               SDL_CondBroadcast( music_state_cond );
            else {
               music_state = MUSIC_STATE_LOADING;
               /* Set timer. */
               fade_timer = SDL_GetTicks();
               fadein_start = 1;
            }
            /* Clear command. */
            music_command = MUSIC_CMD_NONE;
            break;

         case MUSIC_CMD_PAUSE:
            if (music_state == MUSIC_STATE_PAUSED)
               SDL_CondBroadcast( music_state_cond );
            else if ((music_state == MUSIC_STATE_PLAYING) ||
                  (music_state == MUSIC_STATE_FADEIN))
               music_state = MUSIC_STATE_PAUSING;
            music_command = MUSIC_CMD_NONE;
            break;

         case MUSIC_CMD_NONE:
            break;
      }
      cur_state = music_state;
      musicUnlock();

      /*
       * Main processing loop.
       */
      switch (cur_state) {
         /*
          * Basically send a message that thread is up and running.
          */
         case MUSIC_STATE_STARTUP:
            musicLock();
            music_state = MUSIC_STATE_IDLE;
            SDL_CondBroadcast( music_state_cond );
            musicUnlock();
            break;

         /*
          * We died.
          */
         case MUSIC_STATE_DEAD:
            return 0;
            break;

         /*
          * Delays at the end.
          */
         case MUSIC_STATE_PAUSED:
         case MUSIC_STATE_IDLE:
            break;

         /*
          * Resumes the paused song.
          */
         case MUSIC_STATE_RESUMING:
            soundLock();
            alSourcePlay( music_source );
            alSourcef( music_source, AL_GAIN, music_vol );
            /* Check for errors. */
            al_checkErr();
            soundUnlock();

            musicLock();
            music_state = MUSIC_STATE_PLAYING;
            SDL_CondBroadcast( music_state_cond );
            musicUnlock();
            break;

         /*
          * Pause the song.
          */
         case MUSIC_STATE_PAUSING:
            soundLock();
            alSourcePause( music_source );
            /* Check for errors. */
            al_checkErr();
            soundUnlock();

            musicLock();
            music_state = MUSIC_STATE_PAUSED;
            SDL_CondBroadcast( music_state_cond );
            musicUnlock();
            break;

         /*
          * Stop song setting to IDLE.
          */
         case MUSIC_STATE_STOPPING:
            soundLock();

            /* Stop and remove buffers. */
            alSourceStop( music_source );
            alGetSourcei( music_source, AL_BUFFERS_PROCESSED, &value );
            if (value > 0)
               alSourceUnqueueBuffers( music_source, value, removed );
            /* Clear timer. */
            fade_timer = 0;

            /* Reset volume. */
            alSourcef( music_source, AL_GAIN, music_vol );

            soundUnlock();

            musicLock();
            music_state = MUSIC_STATE_IDLE;
            SDL_CondBroadcast( music_state_cond );
            if (!music_forced)
               music_rechoose();
            musicUnlock();
            break;

         /*
          * Load the song.
          */
         case MUSIC_STATE_LOADING:

            /* Load buffer and start playing. */
            active = 0; /* load first buffer */
            ret = stream_loadBuffer( music_buffer[active] );
            soundLock();
            alSourceQueueBuffers( music_source, 1, &music_buffer[active] );
            /* Special case NULL file or error. */
            if (ret < 0) {
               soundUnlock();
               /* Force state to stopped. */
               musicLock();
               music_state = MUSIC_STATE_IDLE;
               SDL_CondBroadcast( music_state_cond );
               if (!music_forced)
                  music_rechoose();
               musicUnlock();
               break;
            }
            /* Force volume level. */
            alSourcef( music_source, AL_GAIN, (fadein_start) ? 0. : music_vol );

            /* Start playing. */
            alSourcePlay( music_source );

            /* Check for errors. */
            al_checkErr();

            soundUnlock();
            /* Special case of a very short song. */
            if (ret > 1) {
               active = -1;

               musicLock();
               if (fadein_start)
                  music_state = MUSIC_STATE_FADEIN;
               else
                  music_state = MUSIC_STATE_PLAYING;
               SDL_CondBroadcast( music_state_cond );
               musicUnlock();
               break;
            }

            /* Load second buffer. */
            active = 1;
            ret = stream_loadBuffer( music_buffer[active] );
            if (ret < 0) {
               active = -1;
            }
            else {
               soundLock();
               alSourceQueueBuffers( music_source, 1, &music_buffer[active] );
               /* Check for errors. */
               al_checkErr();
               soundUnlock();
               active = 1 - active;
            }

            musicLock();
            if (fadein_start)
               music_state = MUSIC_STATE_FADEIN;
            else
               music_state = MUSIC_STATE_PLAYING;
            SDL_CondBroadcast( music_state_cond );
            musicUnlock();
            break;

         /*
          * Fades in the music.
          */
         case MUSIC_STATE_FADEOUT:
         case MUSIC_STATE_FADEIN:
            /* See if must still fade. */
            fade = SDL_GetTicks() - fade_timer;
            if (cur_state == MUSIC_STATE_FADEIN) {

               if (fade < MUSIC_FADEIN_DELAY) {
                  gain = (ALfloat)fade / (ALfloat)MUSIC_FADEIN_DELAY;
                  soundLock();
                  alSourcef( music_source, AL_GAIN, gain*music_vol );
                  /* Check for errors. */
                  al_checkErr();
                  soundUnlock();
               }
               /* No need to fade anymore. */
               else {
                  /* Set volume to normal level. */
                  soundLock();
                  alSourcef( music_source, AL_GAIN, music_vol );
                  /* Check for errors. */
                  al_checkErr();
                  soundUnlock();

                  /* Change state to playing. */
                  musicLock();
                  music_state = MUSIC_STATE_PLAYING;
                  musicUnlock();
               }
            }
            else if (cur_state == MUSIC_STATE_FADEOUT) {

               if (fade < MUSIC_FADEOUT_DELAY) {
                  gain = 1. - (ALfloat)fade / (ALfloat)MUSIC_FADEOUT_DELAY;
                  soundLock();
                  alSourcef( music_source, AL_GAIN, gain*music_vol );
                  /* Check for errors. */
                  al_checkErr();
                  soundUnlock();
               }
               else {
                  /* Music should stop. */
                  musicLock();
                  music_state = MUSIC_STATE_STOPPING;
                  musicUnlock();
                  break;
               }
            }

            /* Purpose fallthrough. */

         /*
          * Play the song if needed.
          */
         case MUSIC_STATE_PLAYING:

            /* Special case where file has ended. */
            if (active < 0) {
               soundLock();
               alGetSourcei( music_source, AL_SOURCE_STATE, &state );

               if (state == AL_STOPPED) {
                  alGetSourcei( music_source, AL_BUFFERS_PROCESSED, &value );
                  if (value > 0)
                     alSourceUnqueueBuffers( music_source, value, removed );
                  soundUnlock();

                  musicLock();
                  music_state = MUSIC_STATE_IDLE;
                  if (!music_forced)
                     music_rechoose();
                  musicUnlock();
                  break;
               }

               soundUnlock();

               break;
            }

            soundLock();

            /* See if needs another buffer set. */
            alGetSourcei( music_source, AL_BUFFERS_PROCESSED, &state );
            if (state > 0) {

               /* refill active buffer */
               alSourceUnqueueBuffers( music_source, 1, removed );
               ret = stream_loadBuffer( music_buffer[active] );
               if (ret < 0) {
                  active = -1;
               }
               else {
                  alSourceQueueBuffers( music_source, 1, &music_buffer[active] );
                  active = 1 - active;
               }
            }

            /* Check for errors. */
            al_checkErr();

            soundUnlock();
      }

      /*
       * Global thread delay.
       */
      SDL_Delay(0);

   }

   return 0;
}
コード例 #26
0
ファイル: game.cpp プロジェクト: Haris07/zooshi
// For performance, we're using multiple threads so that the game state can
// be updating in the background while openGL renders.
// The general plan is:
// 1. Vsync happens.  Everything begins.
// 2. Renderthread activates.  (The update thread is currently blocked.)
// 3. Renderthread dumps everything into opengl, via RenderAllEntities.  (And
//    any other similar calls, such as calls to IMGUI)  Updatethread is
//    still blocked.  When this is complete, OpenGL now has its own copy of
//    everything, and we can safely change world state data.
// 4. Renderthread signals updatethread to wake up.
// 5a.Renderthread calls gl_flush, (via Renderer.advanceframe) and waits for
//    everything render.  Once complete, it goes to sleep and waits for the
//    next vsync event.
// 5b.Updatethread goes and updates the game state and gets us all ready for
//    next frame.  Once complete, it also goes to sleep and waits for the next
//    vsync event.
void Game::Run() {
  // Start the update thread:
  UpdateThreadData rt_data(&game_exiting_, &world_, &state_machine_, &renderer_,
                           &input_, &audio_engine_, &sync_);

  input_.AdvanceFrame(&renderer_.window_size());
  state_machine_.AdvanceFrame(16);

  SDL_Thread* update_thread =
      SDL_CreateThread(UpdateThread, "Zooshi Update Thread", &rt_data);
  if (!update_thread) {
    LogError("Error creating update thread.");
    assert(false);
  }

#if DISPLAY_FRAMERATE_HISTOGRAM
  for (int i = 0; i < kHistogramSize; i++) {
    histogram[i] = 0;
  }
  last_printout = 0;
#endif  // DISPLAY_FRAMERATE_HISTOGRAM

  // variables used for regulating our framerate:
  // Total size of our history, in frames:
  const int kHistorySize = 60 * 5;
  // Max number of frames we can have dropped in our history, before we
  // switch to queue-stuffing mode, and ignore vsync pauses.
  const int kMaxDroppedFrames = 3;
  // Variable
  bool missed_frame_history[kHistorySize];
  for (int i = 0; i < kHistorySize; i++) {
    missed_frame_history[i] = false;
  }
  int history_index = 0;
  int total_dropped_frames = 0;

  global_vsync_context = &sync_;
#ifdef __ANDROID__
  fplbase::RegisterVsyncCallback(HandleVsync);
#else
  // We don't need this on android because we'll just get vsync events directly.
  SDL_Thread* vsync_simulator_thread = SDL_CreateThread(
      VsyncSimulatorThread, "Zooshi Simulated Vsync Thread", nullptr);
  if (!vsync_simulator_thread) {
    LogError("Error creating vsync simulator thread.");
    assert(false);
  }
#endif  // __ANDROID__
  int last_frame_id = 0;

  // We basically own the lock all the time, except when we're waiting
  // for a vsync event.
  SDL_LockMutex(sync_.renderthread_mutex_);
  while (!game_exiting_) {
#ifdef __ANDROID__
    int current_frame_id = fplbase::GetVsyncFrameId();
#else
    int current_frame_id = 0;
#endif  // __ANDROID__
    // Update our framerate history:
    // The oldest value falls off and is replaced with the most recent frame.
    // Also, we update our counts.
    if (missed_frame_history[history_index]) {
      total_dropped_frames--;
    }
    // We count it as a dropped frame if more than one vsync event passed since
    // we started rendering it.  The check is implemented via equality
    // comparisons because current_frame_id will eventually wrap.)
    missed_frame_history[history_index] =
        (current_frame_id != last_frame_id + 1) &&
        (current_frame_id != last_frame_id);
    if (missed_frame_history[history_index]) {
      total_dropped_frames++;
    }
    history_index = (history_index + 1) % kHistorySize;
    last_frame_id = current_frame_id;

    // -------------------------------------------
    // Steps 1, 2.
    // Wait for start of frame.  (triggered at vsync start on android.)
    // For performance, we only wait if we're not dropping frames.  Otherwise,
    // we just keep rendering as fast as we can and stuff the render queue.
    if (total_dropped_frames <= kMaxDroppedFrames) {
      SDL_CondWait(sync_.start_render_cv_, sync_.renderthread_mutex_);
    }

    // Grab the lock to make sure the game isn't still updating.
    SDL_LockMutex(sync_.gameupdate_mutex_);

    SystraceBegin("RenderFrame");

    // Input update must happen from the render thread.
    // From the SDL documentation on SDL_PollEvent(),
    // https://wiki.libsdl.org/SDL_PollEvent):
    // "As this function implicitly calls SDL_PumpEvents(), you can only call
    // this function in the thread that set the video mode."
    SystraceBegin("Input::AdvanceFrame()");
    input_.AdvanceFrame(&renderer_.window_size());
    game_exiting_ |= input_.exit_requested();
    SystraceEnd();

    // Milliseconds elapsed since last update.
    rt_data.frame_start = CurrentWorldTimeSubFrame(input_);

    // -------------------------------------------
    // Step 3.
    // Render everything.
    // -------------------------------------------
    SystraceBegin("StateMachine::Render()");

    fplbase::RenderTarget::ScreenRenderTarget(renderer_).SetAsRenderTarget();
    renderer_.ClearDepthBuffer();
    renderer_.SetCulling(fplbase::Renderer::kCullBack);

    state_machine_.Render(&renderer_);
    SystraceEnd();

    SDL_UnlockMutex(sync_.gameupdate_mutex_);

    SystraceBegin("StateMachine::HandleUI()");
    state_machine_.HandleUI(&renderer_);
    SystraceEnd();

    // -------------------------------------------
    // Step 4.
    // Signal the update thread that it is safe to start messing with
    // data, now that we've already handed it all off to openGL.
    // -------------------------------------------
    SDL_CondBroadcast(sync_.start_update_cv_);

    // -------------------------------------------
    // Step 5a.
    // Start openGL actually rendering.  AdvanceFrame will (among other things)
    // trigger a gl_flush.  This thread will block until it is completed,
    // but that's ok because the update thread is humming in the background
    // preparing the worlds tate for next frame.
    // -------------------------------------------
    SystraceBegin("AdvanceFrame");
    renderer_.AdvanceFrame(input_.minimized(), input_.Time());
    SystraceEnd();  // AdvanceFrame

    SystraceEnd();  // RenderFrame

    gpg_manager_.Update();

    // Process input device messages since the last game loop.
    // Update render window size.
    if (input_.GetButton(fplbase::FPLK_BACKQUOTE).went_down()) {
      ToggleRelativeMouseMode();
    }

    int new_time = CurrentWorldTimeSubFrame(input_);
    int frame_time = new_time - rt_data.frame_start;
#if DISPLAY_FRAMERATE_HISTOGRAM
    UpdateProfiling(frame_time);
#endif  // DISPLAY_FRAMERATE_HISTOGRAM

    SystraceCounter("FrameTime", frame_time);
  }
  SDL_UnlockMutex(sync_.renderthread_mutex_);
// Clean up asynchronous callbacks to prevent crashing on garbage data.
#ifdef __ANDROID__
  fplbase::RegisterVsyncCallback(nullptr);
#endif  // __ANDROID__
  input_.AddAppEventCallback(nullptr);
}
コード例 #27
0
ファイル: game.cpp プロジェクト: Haris07/zooshi
void HandleVsync() {
  SDL_CondBroadcast(global_vsync_context->start_render_cv_);
}
コード例 #28
0
		int CondBroadcast(Cond *cond)
		{
			return SDL_CondBroadcast(cond);
		}
コード例 #29
0
ファイル: taskmanager.c プロジェクト: laochailan/taisei
static int taskmgr_thread(void *arg) {
	TaskManager *mgr = arg;
	attr_unused SDL_threadID tid = SDL_ThreadID();

	if(SDL_SetThreadPriority(mgr->thread_prio) < 0) {
		log_sdl_error(LOG_WARN, "SDL_SetThreadPriority");
	}

	bool running;
	bool aborted;

	do {
		SDL_LockMutex(mgr->mutex);

		running = mgr->running;
		aborted = mgr->aborted;

		if(!running && !aborted) {
			SDL_CondWait(mgr->cond, mgr->mutex);
		}

		SDL_UnlockMutex(mgr->mutex);
	} while(!running && !aborted);

	while(running && !aborted) {
		SDL_LockMutex(mgr->mutex);
		Task *task = alist_pop(&mgr->queue);

		running = mgr->running;
		aborted = mgr->aborted;

		if(running && task == NULL && !aborted) {
			SDL_CondWait(mgr->cond, mgr->mutex);
		}

		SDL_UnlockMutex(mgr->mutex);

		if(task != NULL) {
			SDL_LockMutex(task->mutex);

			bool task_disowned = task->disowned;

			if(aborted && task->status == TASK_PENDING) {
				task->status = TASK_CANCELLED;
			}

			if(task->status == TASK_PENDING) {
				task->status = TASK_RUNNING;

				SDL_UnlockMutex(task->mutex);
				task->result = task->callback(task->userdata);
				SDL_LockMutex(task->mutex);

				assert(task->in_queue);
				task->in_queue = false;
				(void)SDL_AtomicDecRef(&mgr->numtasks);

				if((task_disowned = task->disowned)) {
					SDL_UnlockMutex(task->mutex);
					task_free(task);
				} else {
					task->status = TASK_FINISHED;
					SDL_CondBroadcast(task->cond);
					SDL_UnlockMutex(task->mutex);
				}
			} else if(task->status == TASK_CANCELLED) {
				assert(task->in_queue);
				task->in_queue = false;
				(void)SDL_AtomicDecRef(&mgr->numtasks);
				SDL_UnlockMutex(task->mutex);

				if(task_disowned) {
					task_free(task);
				}
			} else {
				UNREACHABLE;
			}
		}
	}

	return 0;
}
コード例 #30
0
ファイル: sdlthread.hpp プロジェクト: SDLGUI/sdlgui
def_dll int sdl_condition::broadcast()
{
	return SDL_CondBroadcast(_condition);
}