Client does not inherit Thread anymore. Use separte thread to run the client on.

git-svn-id: http://voip.null.ro/svn/yate@4987 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
oana 2012-04-04 09:42:06 +00:00
parent 241e65a97f
commit edf4c2fc7a
4 changed files with 108 additions and 17 deletions

View File

@ -3398,6 +3398,11 @@ void QtClient::loadWindows(const char* file)
} }
} }
bool QtClient::isUIThread()
{
return (QApplication::instance() && QApplication::instance()->thread() == QThread::currentThread());
}
// Open a file open dialog window // Open a file open dialog window
// Parameters that can be specified include 'caption', // Parameters that can be specified include 'caption',
// 'dir', 'filter', 'selectedfilter', 'confirmoverwrite', 'choosedir' // 'dir', 'filter', 'selectedfilter', 'confirmoverwrite', 'choosedir'
@ -4271,8 +4276,8 @@ void QtClient::setWidgetHeight(QWidget* w, const String& height)
/** /**
* QtDriver * QtDriver
*/ */
QtDriver::QtDriver() QtDriver::QtDriver(bool buildClientThread)
: m_init(false) : m_init(false), m_clientThread(buildClientThread)
{ {
qInstallMsgHandler(qtMsgHandler); qInstallMsgHandler(qtMsgHandler);
} }
@ -4289,7 +4294,8 @@ void QtDriver::initialize()
if (!QtClient::self()) { if (!QtClient::self()) {
debugCopy(); debugCopy();
new QtClient; new QtClient;
QtClient::self()->startup(); if (m_clientThread)
QtClient::self()->startup();
} }
if (!m_init) { if (!m_init) {
m_init = true; m_init = true;

View File

@ -152,8 +152,7 @@ public:
virtual void quit() { virtual void quit() {
if (m_app) if (m_app)
m_app->quit(); m_app->quit();
else Engine::halt(0);
Engine::halt(0);
} }
/** /**
@ -546,6 +545,7 @@ public:
protected: protected:
virtual void loadWindows(const char* file = 0); virtual void loadWindows(const char* file = 0);
virtual bool isUIThread();
private: private:
QApplication* m_app; QApplication* m_app;
ObjList m_events; // Proxy events objects ObjList m_events; // Proxy events objects
@ -554,11 +554,12 @@ private:
class YQT4_API QtDriver : public ClientDriver class YQT4_API QtDriver : public ClientDriver
{ {
public: public:
QtDriver(); QtDriver(bool buildClientThread = true);
virtual ~QtDriver(); virtual ~QtDriver();
virtual void initialize(); virtual void initialize();
private: private:
bool m_init; // Already initialized flag bool m_init; // Already initialized flag
bool m_clientThread; // does the client need a thread to run on?
}; };
class YQT4_API QtWindow : public QWidget, public Window class YQT4_API QtWindow : public QWidget, public Window

View File

@ -155,6 +155,52 @@ private:
TrayIconDef() : NamedPointer("") {} // No default constructor TrayIconDef() : NamedPointer("") {} // No default constructor
}; };
namespace { // anonymous
/**
* Helper class providing a thread on which the Client to run on
* A thread for the client
*/
class ClientThread : public Thread
{
public:
/**
* Constructor
* @param name Static name of the thread (for debugging purpose only)
* @param prio Thread priority
*/
ClientThread(Client* client, Priority prio = Normal)
: Thread("Client",prio),
m_client(client)
{ }
/**
* Destructor
*/
inline ~ClientThread()
{}
/**
* Run thread, inherited from Thread
*/
virtual void run()
{
m_client->run();
}
/**
* Clean up, inherited from Thread
*/
virtual void cleanup()
{
m_client->cleanup();
m_client->setThread(0);
}
private:
Client* m_client;
};
}; // anonymous namespace
/** /**
* Static classes/function/data * Static classes/function/data
@ -869,8 +915,8 @@ bool ClientThreadProxy::execute()
*/ */
// Constructor // Constructor
Client::Client(const char *name) Client::Client(const char *name)
: Thread(name), m_initialized(false), m_line(0), m_oneThread(true), : m_initialized(false), m_line(0), m_oneThread(true),
m_defaultLogic(0) m_defaultLogic(0), m_clientThread(0)
{ {
s_client = this; s_client = this;
@ -912,6 +958,28 @@ Client::~Client()
Engine::halt(0); Engine::halt(0);
} }
bool Client::startup()
{
DDebug(ClientDriver::self(),DebugAll,"Client::startup() [%p]",this);
if (m_clientThread) {
Debug(ClientDriver::self(),DebugNote,"Trying to build a client thread when you already have one '%s' [%p]",
m_clientThread->name(),m_clientThread);
return true;
}
else {
m_clientThread = new ClientThread(this);
if (!m_clientThread->startup()) {
Debug(ClientDriver::self(),DebugWarn,"Failed to startup the client thread '%s' [%p]",m_clientThread->name(),m_clientThread);
delete static_cast<ClientThread*>(m_clientThread);
m_clientThread = 0;
return false;
}
Debug(ClientDriver::self(),DebugInfo,"Starting up client thread '%s' [%p]",m_clientThread->name(),m_clientThread);
return true;
}
return false;
}
// Cleanup before halting // Cleanup before halting
void Client::cleanup() void Client::cleanup()
{ {
@ -2116,7 +2184,7 @@ bool Client::received(Message& msg, int id)
// Postpone messages to be redispatched from UI thread // Postpone messages to be redispatched from UI thread
bool Client::postpone(const Message& msg, int id, bool copyUserData) bool Client::postpone(const Message& msg, int id, bool copyUserData)
{ {
if (isCurrent()) if (isUIThread())
return false; return false;
PostponedMessage* postponed = new PostponedMessage(msg,id,copyUserData); PostponedMessage* postponed = new PostponedMessage(msg,id,copyUserData);
s_postponeMutex.lock(); s_postponeMutex.lock();
@ -2323,14 +2391,14 @@ bool Client::driverLock(long maxwait)
bool Client::driverLockLoop() bool Client::driverLockLoop()
{ {
if (!(isCurrent() && ClientDriver::self())) if (!(isUIThread() && ClientDriver::self()))
return false; return false;
while (!driverLock()) { while (!driverLock()) {
if (Engine::exiting() || !ClientDriver::self()) if (Engine::exiting() || !ClientDriver::self())
return false; return false;
idleActions(); idleActions();
yield(); Thread::yield();
} }
return true; return true;
} }

View File

@ -762,10 +762,10 @@ private:
}; };
/** /**
* Singleton class that holds the User Interface's main thread and methods * Singleton class that holds the User Interface's main methods
* @short Thread that runs the User Interface * @short Class that runs the User Interface
*/ */
class YATE_API Client : public Thread, public MessageReceiver class YATE_API Client : public MessageReceiver
{ {
friend class Window; friend class Window;
friend class ClientChannel; friend class ClientChannel;
@ -843,7 +843,13 @@ public:
virtual ~Client(); virtual ~Client();
/** /**
* Run the client's thread * Start up the client thread
* @return True if the client thread is started, false otherwise
*/
virtual bool startup();
/**
* Run the client's main loop
*/ */
virtual void run(); virtual void run();
@ -879,6 +885,13 @@ public:
inline void unlockOther() inline void unlockOther()
{ if (!m_oneThread) unlock(); } { if (!m_oneThread) unlock(); }
/**
* Set the client's thread
* @param th The thread on which the client will run on
*/
inline void setThread(Thread* th)
{ m_clientThread = th; }
/** /**
* Handle all windows closed event from UI * Handle all windows closed event from UI
*/ */
@ -1269,7 +1282,7 @@ public:
* @return True if the client is valid (running) or the method is called from client's thread * @return True if the client is valid (running) or the method is called from client's thread
*/ */
static inline bool valid() static inline bool valid()
{ return self() && (self() == Thread::current() || !(exiting() || Engine::exiting())); } { return self() && (self()->isUIThread() || !(exiting() || Engine::exiting())); }
/** /**
* Check if a message is sent by the client * Check if a message is sent by the client
@ -1712,8 +1725,10 @@ protected:
virtual void initClient(); virtual void initClient();
virtual void exitClient() virtual void exitClient()
{} {}
virtual bool isUIThread()
{ return Thread::current() == m_clientThread; }
inline bool needProxy() const inline bool needProxy() const
{ return m_oneThread && !isCurrent(); } { return m_oneThread && !(Client::self() && Client::self()->isUIThread()); }
bool driverLockLoop(); bool driverLockLoop();
static bool driverLock(long maxwait = 0); static bool driverLock(long maxwait = 0);
static void driverUnlock(); static void driverUnlock();
@ -1731,6 +1746,7 @@ protected:
static int s_changing; static int s_changing;
static ObjList s_logics; static ObjList s_logics;
static bool s_idleLogicsTick; // Call logics' timerTick() static bool s_idleLogicsTick; // Call logics' timerTick()
Thread* m_clientThread;
}; };
/** /**