Matei
08d3ff2952
- Fixed some invalid member function references in wxJS code that gcc 4.0 didn't like. - Some conversion changes. - Don't try to construct wxSound from memory in OS X (it's not available). - Added dependency on zlib in AtlasUI (something there uses _compress). - Added Mac code for finding current executable's path. - Added dummy code for getting display size that does not use X. - Fixed dir_get_changed_file stub to return ERR::AGAIN (end of files) instead of INFO::OK. This was SVN commit r5312.
149 lines
3.9 KiB
C++
149 lines
3.9 KiB
C++
#include "precompiled.h"
|
|
|
|
#include "MessagePasserImpl.h"
|
|
#include "Messages.h"
|
|
|
|
#include "lib/timer.h"
|
|
|
|
using namespace AtlasMessage;
|
|
|
|
|
|
MessagePasserImpl::MessagePasserImpl()
|
|
: m_Trace(false)
|
|
{
|
|
}
|
|
|
|
void MessagePasserImpl::Add(IMessage* msg)
|
|
{
|
|
debug_assert(msg);
|
|
debug_assert(msg->GetType() == IMessage::Message);
|
|
|
|
if (m_Trace)
|
|
debug_printf("%8.3f add message: %s\n", get_time(), msg->GetName());
|
|
|
|
m_Mutex.Lock();
|
|
m_Queue.push(msg);
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
IMessage* MessagePasserImpl::Retrieve()
|
|
{
|
|
// (It should be fairly easy to use a more efficient thread-safe queue,
|
|
// since there's only one thread adding items and one thread consuming;
|
|
// but it's not worthwhile yet.)
|
|
|
|
m_Mutex.Lock();
|
|
|
|
IMessage* msg = NULL;
|
|
if (! m_Queue.empty())
|
|
{
|
|
msg = m_Queue.front();
|
|
m_Queue.pop();
|
|
}
|
|
|
|
m_Mutex.Unlock();
|
|
|
|
if (m_Trace && msg)
|
|
debug_printf("%8.3f retrieved message: %s\n", get_time(), msg->GetName());
|
|
|
|
return msg;
|
|
}
|
|
|
|
void MessagePasserImpl::Query(QueryMessage* qry, void(* UNUSED(timeoutCallback) )())
|
|
{
|
|
debug_assert(qry);
|
|
debug_assert(qry->GetType() == IMessage::Query);
|
|
|
|
if (m_Trace)
|
|
debug_printf("%8.3f add query: %s\n", get_time(), qry->GetName());
|
|
|
|
// Initialise a semaphore, so we can block until the query has been handled
|
|
int err = 0;
|
|
sem_t* psem = (sem_t*) SEM_FAILED;
|
|
//sem_t sem;
|
|
//psem = &sem;
|
|
//err = sem_init(psem, 0, 0);
|
|
const char* sem_name = "/tmp/atlas";
|
|
psem = sem_open(sem_name, O_CREAT, 0777, 0);
|
|
err = errno;
|
|
if (psem == (sem_t*) SEM_FAILED)
|
|
{
|
|
// Probably-fatal error
|
|
debug_printf("errno: %d (%s)\n", err, strerror(err));
|
|
debug_warn("sem_init failed");
|
|
return;
|
|
}
|
|
qry->m_Semaphore = (void*)psem;
|
|
|
|
m_Mutex.Lock();
|
|
m_Queue.push(qry);
|
|
m_Mutex.Unlock();
|
|
|
|
// Wait until the query handler has handled the query and called sem_post:
|
|
|
|
|
|
// The following code was necessary to avoid deadlock, but it still breaks
|
|
// in some cases (e.g. when Atlas issues a query before its event loop starts
|
|
// running) and doesn't seem to be the simplest possible solution.
|
|
// So currently we're trying to not do anything like that at all, and
|
|
// just stop the game making windows (which is what seems (from experience) to
|
|
// deadlock things) by overriding ah_display_error. Hopefully it'll work like
|
|
// that, and the redundant code below/elsewhere can be removed, but it's
|
|
// left in here in case it needs to be reinserted in the future to make it
|
|
// work.
|
|
// (See http://www.wildfiregames.com/forum/index.php?s=&showtopic=10236&view=findpost&p=174617)
|
|
|
|
// // At least on Win32, it is necessary for the UI thread to run its event
|
|
// // loop to avoid deadlocking the system (particularly when the game
|
|
// // tries to show a dialog box); so timeoutCallback is called whenever we
|
|
// // think it's necessary for that to happen.
|
|
//
|
|
// #if OS_WIN
|
|
// // On Win32, use MsgWaitForMultipleObjects, which waits on the semaphore
|
|
// // but is also interrupted by incoming Windows-messages.
|
|
// // while (0 != (err = sem_msgwait_np(psem)))
|
|
//
|
|
// while (0 != (err = sem_wait(psem)))
|
|
// #else
|
|
// // TODO: On non-Win32, I have no idea whether the same problem exists; but
|
|
// // it might do, so call the callback every few seconds just in case it helps.
|
|
// struct timespec abs_timeout;
|
|
// clock_gettime(CLOCK_REALTIME, &abs_timeout);
|
|
// abs_timeout.tv_sec += 2;
|
|
// while (0 != (err = sem_timedwait(psem, &abs_timeout)))
|
|
// #endif
|
|
|
|
while (0 != (err = sem_wait(psem)))
|
|
{
|
|
// If timed out, call callback and try again
|
|
// if (errno == ETIMEDOUT)
|
|
// timeoutCallback();
|
|
// else
|
|
// Keep retrying while EINTR, but other errors are probably fatal
|
|
if (errno != EINTR)
|
|
{
|
|
debug_warn("Semaphore wait failed");
|
|
return; // (leaks the semaphore)
|
|
}
|
|
}
|
|
|
|
// Clean up
|
|
qry->m_Semaphore = NULL;
|
|
//sem_destroy(psem);
|
|
sem_close(psem);
|
|
sem_unlink(sem_name);
|
|
}
|
|
|
|
bool MessagePasserImpl::IsEmpty()
|
|
{
|
|
m_Mutex.Lock();
|
|
bool empty = m_Queue.empty();
|
|
m_Mutex.Unlock();
|
|
return empty;
|
|
}
|
|
|
|
void MessagePasserImpl::SetTrace(bool t)
|
|
{
|
|
m_Trace = t;
|
|
}
|