From aaa38880c4b267f00077f3ce47685d25cf9e8f5e Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Wed, 30 Dec 1998 16:24:18 +0000 Subject: [PATCH] Motif corrections in wxDC (match wxWin 2.0 drawing stuff) on idle handling -> speed-up threads work now modules work now (also in release mode...) wxMotif compiles with configure again git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1282 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/make.env | 2 +- src/motif.inc | 2 +- src/motif/app.cpp | 15 +- src/motif/dcclient.cpp | 6 +- src/motif/thread.cpp | 374 ++++++++++++++++++++++++++++++----------- 5 files changed, 294 insertions(+), 105 deletions(-) diff --git a/src/make.env b/src/make.env index b47aa8787d..944038e5ae 100644 --- a/src/make.env +++ b/src/make.env @@ -38,7 +38,7 @@ GUISUFFIX = _stubs # Misc options OPTIONS = -D__WXDEBUG__ COPTIONS = -DEBUGFLAGS = -ggdb +DEBUGFLAGS = INCLUDE = WARN = -Wall -Wno-unused # -w CWARN = -Wall -Wno-unused # -w diff --git a/src/motif.inc b/src/motif.inc index 512418c8fd..e42e5fa91e 100644 --- a/src/motif.inc +++ b/src/motif.inc @@ -105,7 +105,6 @@ LIB_CPP_SRC=\ motif/metafile.cpp \ motif/minifram.cpp \ motif/msgdlg.cpp \ - motif/notebook.cpp \ motif/palette.cpp \ motif/pen.cpp \ motif/print.cpp \ @@ -138,6 +137,7 @@ LIB_CPP_SRC=\ generic/listctrl.cpp \ generic/laywin.cpp \ generic/msgdlgg.cpp \ + generic/notebook.cpp \ generic/panelg.cpp \ generic/printps.cpp \ generic/prntdlgg.cpp \ diff --git a/src/motif/app.cpp b/src/motif/app.cpp index 622e9c126e..cc74c9b771 100644 --- a/src/motif/app.cpp +++ b/src/motif/app.cpp @@ -28,6 +28,7 @@ #include "wx/log.h" #include "wx/module.h" #include "wx/memory.h" +#include "wx/thread.h" #if wxUSE_WX_RESOURCES #include "wx/resource.h" @@ -93,7 +94,7 @@ bool wxApp::Initialize() wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER); wxModule::RegisterModules(); - wxASSERT( wxModule::InitializeModules() == TRUE ); + if (!wxModule::InitializeModules()) return FALSE; return TRUE; } @@ -293,7 +294,17 @@ int wxApp::MainLoop() XtAppNextEvent( (XtAppContext) wxTheApp->GetAppContext(), &event); ProcessXEvent((WXEvent*) & event); - ProcessIdle(); + + if (XtAppPending( (XtAppContext) wxTheApp->GetAppContext() ) == 0) + { + if (!ProcessIdle()) + { + wxMutexGuiLeave(); + usleep(20); + wxMutexGuiEnter(); + } + } + } return 0; diff --git a/src/motif/dcclient.cpp b/src/motif/dcclient.cpp index a1078d9791..f9e71014b2 100644 --- a/src/motif/dcclient.cpp +++ b/src/motif/dcclient.cpp @@ -57,8 +57,10 @@ static Pixmap bdiag, cdiag, fdiag, cross, horiz, verti; //----------------------------------------------------------------------------- #define RAD2DEG 57.2957795131 + // Fudge factor. Obsolete? -#define WX_GC_CF 0 + // No. Robert Roebling +#define WX_GC_CF 1 //----------------------------------------------------------------------------- // wxWindowDC @@ -1515,7 +1517,7 @@ void wxWindowDC::SetPen( const wxPen &pen ) break; case wxCAP_ROUND: default: - cap = CapRound; + cap = (scaled_width <= 1) ? CapNotLast : CapRound; break; } diff --git a/src/motif/thread.cpp b/src/motif/thread.cpp index e12b45e63b..cf16365374 100644 --- a/src/motif/thread.cpp +++ b/src/motif/thread.cpp @@ -1,8 +1,8 @@ ///////////////////////////////////////////////////////////////////////////// // Name: thread.cpp -// Purpose: wxThread Implementation. For Unix ports, see e.g. src/gtk +// Purpose: wxThread Implementation for Posix threads // Author: Original from Wolfram Gloger/Guilhem Lavaux -// Modified by: +// Modified by: Robert Roebling // Created: 04/22/98 // RCS-ID: $Id$ // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998) @@ -13,56 +13,127 @@ #pragma implementation "thread.h" #endif +#include +#include +#include +#include #include "wx/module.h" #include "wx/thread.h" #include "wx/utils.h" +#include "wx/log.h" -enum thread_state { +#include +#include + +// for select() +#include +#include +#ifdef __sgi +#include +#endif + +//-------------------------------------------------------------------- +// constants +//-------------------------------------------------------------------- + +enum thread_state +{ STATE_IDLE = 0, STATE_RUNNING, + STATE_PAUSING, + STATE_PAUSED, STATE_CANCELED, STATE_EXITED }; -///////////////////////////////////////////////////////////////////////////// -// Static variables -///////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------- +// global data +//-------------------------------------------------------------------- -wxMutex *wxMainMutex; // controls access to all GUI functions +static pthread_t p_mainid; -///////////////////////////////////////////////////////////////////////////// -// Windows implementation -///////////////////////////////////////////////////////////////////////////// +wxMutex *wxMainMutex = (wxMutex*) NULL; /* controls access to all GUI functions */ + +/* TODO for Xt */ + +static int p_thrd_pipe[2] = { -1, -1 }; + +//------------------------------------------------------------------------- +// global functions +//------------------------------------------------------------------------- -class wxMutexInternal { +static void wxThreadGuiInit() +{ +/* TODO for Xt */ +} + +static void wxThreadGuiExit() +{ +/* TODO for Xt */ +} + +void wxMutexGuiEnter() +{ + if (wxMainMutex) + wxMainMutex->Lock(); +} + +void wxMutexGuiLeave() +{ + if (wxMainMutex) + wxMainMutex->Unlock(); +} + +//-------------------------------------------------------------------- +// wxMutex (Posix implementation) +//-------------------------------------------------------------------- + +class wxMutexInternal +{ public: - // TODO: internal mutex handle + pthread_mutex_t p_mutex; }; wxMutex::wxMutex() { p_internal = new wxMutexInternal; - // TODO: create internal mutext handle + pthread_mutex_init(&(p_internal->p_mutex), NULL); m_locked = 0; } wxMutex::~wxMutex() { if (m_locked > 0) - wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked); - // TODO: free internal mutext handle + wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked ); + + pthread_mutex_destroy(&(p_internal->p_mutex)); + delete p_internal; } wxMutexError wxMutex::Lock() { - // TODO + int err; + + err = pthread_mutex_lock(&(p_internal->p_mutex)); + if (err == EDEADLK) + return wxMUTEX_DEAD_LOCK; + m_locked++; return wxMUTEX_NO_ERROR; } wxMutexError wxMutex::TryLock() { - // TODO + int err; + + if (m_locked) + return wxMUTEX_BUSY; + + err = pthread_mutex_trylock(&(p_internal->p_mutex)); + switch (err) + { + case EBUSY: return wxMUTEX_BUSY; + } m_locked++; return wxMUTEX_NO_ERROR; } @@ -71,159 +142,254 @@ wxMutexError wxMutex::Unlock() { if (m_locked > 0) m_locked--; - - // TODO + else + return wxMUTEX_UNLOCKED; + + pthread_mutex_unlock(&(p_internal->p_mutex)); return wxMUTEX_NO_ERROR; } -class wxConditionInternal { +//-------------------------------------------------------------------- +// wxCondition (Posix implementation) +//-------------------------------------------------------------------- + +class wxConditionInternal +{ public: - // TODO: internal handle - int waiters; + pthread_cond_t p_condition; }; wxCondition::wxCondition() { p_internal = new wxConditionInternal; - // TODO: create internal handle - p_internal->waiters = 0; + pthread_cond_init(&(p_internal->p_condition), NULL); } wxCondition::~wxCondition() { - // TODO: destroy internal handle + pthread_cond_destroy(&(p_internal->p_condition)); + delete p_internal; } void wxCondition::Wait(wxMutex& mutex) { - mutex.Unlock(); - p_internal->waiters++; - // TODO wait here - p_internal->waiters--; - mutex.Lock(); + pthread_cond_wait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex)); } -bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, - unsigned long nsec) +bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, unsigned long nsec) { - mutex.Unlock(); - p_internal->waiters++; - - // TODO wait here - p_internal->waiters--; - mutex.Lock(); + struct timespec tspec; - return FALSE; + tspec.tv_sec = time(NULL)+sec; + tspec.tv_nsec = nsec; + return (pthread_cond_timedwait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex), &tspec) != ETIMEDOUT); } void wxCondition::Signal() { - // TODO + pthread_cond_signal(&(p_internal->p_condition)); } void wxCondition::Broadcast() { - // TODO + pthread_cond_broadcast(&(p_internal->p_condition)); } -class wxThreadInternal { +//-------------------------------------------------------------------- +// wxThread (Posix implementation) +//-------------------------------------------------------------------- + +class wxThreadInternal +{ public: - // TODO + wxThreadInternal() { state = STATE_IDLE; } + ~wxThreadInternal() {} + static void *PthreadStart(void *ptr); + pthread_t thread_id; + int state; + int prio; + int defer_destroy; }; -wxThreadError wxThread::Create() +void *wxThreadInternal::PthreadStart(void *ptr) { - // TODO - return wxTHREAD_NO_ERROR; -} + wxThread *thread = (wxThread *)ptr; -wxThreadError wxThread::Destroy() -{ - // TODO - return wxTHREAD_NO_ERROR; + // Call the main entry + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + void* status = thread->Entry(); + + thread->Exit(status); + + return NULL; } -wxThreadError wxThread::Pause() +wxThreadError wxThread::Create() { - // TODO + pthread_attr_t a; + int min_prio, max_prio, p; + struct sched_param sp; + + if (p_internal->state != STATE_IDLE) + return wxTHREAD_RUNNING; + + // Change thread priority + pthread_attr_init(&a); + pthread_attr_getschedpolicy(&a, &p); + + min_prio = sched_get_priority_min(p); + max_prio = sched_get_priority_max(p); + + pthread_attr_getschedparam(&a, &sp); + sp.sched_priority = min_prio + + (p_internal->prio*(max_prio-min_prio))/100; + pthread_attr_setschedparam(&a, &sp); + + // this is the point of no return + p_internal->state = STATE_RUNNING; + if (pthread_create(&p_internal->thread_id, &a, + wxThreadInternal::PthreadStart, (void *)this) != 0) + { + p_internal->state = STATE_IDLE; + pthread_attr_destroy(&a); + return wxTHREAD_NO_RESOURCE; + } + pthread_attr_destroy(&a); + return wxTHREAD_NO_ERROR; } -wxThreadError wxThread::Resume() +void wxThread::SetPriority(int prio) { - // TODO - return wxTHREAD_NO_ERROR; + if (p_internal->state == STATE_RUNNING) + return; + + if (prio > 100) prio = 100; + + if (prio < 0) prio = 0; + + p_internal->prio = prio; } -void wxThread::Exit(void *status) +int wxThread::GetPriority() const { - // TODO + return p_internal->prio; } -void wxThread::SetPriority(int prio) +void wxThread::DeferDestroy(bool on) { - // TODO + if (on) + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + else + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); } -int wxThread::GetPriority() const +wxThreadError wxThread::Destroy() { - // TODO - return 0; + int res = 0; + + if (p_internal->state == STATE_RUNNING) + { + res = pthread_cancel(p_internal->thread_id); + if (res == 0) + p_internal->state = STATE_CANCELED; + } + + return wxTHREAD_NO_ERROR; } -void wxThread::DeferDestroy(bool on) +wxThreadError wxThread::Pause() { - // TODO + if (p_internal->state != STATE_RUNNING) + return wxTHREAD_NOT_RUNNING; + + if (!p_internal->defer_destroy) + return wxTHREAD_MISC_ERROR; + + p_internal->state = STATE_PAUSING; + return wxTHREAD_NO_ERROR; } -void wxThread::TestDestroy() +wxThreadError wxThread::Resume() { - // TODO + if (p_internal->state == STATE_PAUSING || p_internal->state == STATE_PAUSED) + p_internal->state = STATE_RUNNING; + + return wxTHREAD_NO_ERROR; } void *wxThread::Join() { - // TODO - return (void*) NULL; + void* status = 0; + + if (p_internal->state != STATE_IDLE) + { + bool do_unlock = wxThread::IsMain(); + + while (p_internal->state == STATE_RUNNING) + wxYield(); + + if (do_unlock) wxMainMutex->Unlock(); + + pthread_join(p_internal->thread_id, &status); + + if (do_unlock) wxMainMutex->Lock(); + + p_internal->state = STATE_IDLE; + } + + return status; } unsigned long wxThread::GetID() const { - // TODO - return 0; + return p_internal->thread_id; } -/* -wxThread *wxThread::GetThreadFromID(unsigned long id) +void wxThread::Exit(void *status) { - // TODO - return NULL; + wxThread* ptr = this; + +/* THREAD_SEND_EXIT_MSG(ptr); TODO for Xt */ + + p_internal->state = STATE_EXITED; + pthread_exit(status); } -*/ -bool wxThread::IsAlive() const +void wxThread::TestDestroy() { - // TODO - return FALSE; + if (p_internal->state == STATE_PAUSING) + { + p_internal->state = STATE_PAUSED; + while (p_internal->state == STATE_PAUSED) + { + pthread_testcancel(); + usleep(1); + } + } + pthread_testcancel(); +} + +bool wxThread::IsMain() +{ + return (bool)pthread_equal(pthread_self(), p_mainid); } bool wxThread::IsRunning() const { - // TODO - return FALSE; + return (p_internal->state == STATE_RUNNING); } -bool wxThread::IsMain() +bool wxThread::IsAlive() const { - // TODO - return FALSE; + return (p_internal->state == STATE_RUNNING) || + (p_internal->state == STATE_PAUSING) || + (p_internal->state == STATE_PAUSED); } wxThread::wxThread() { p_internal = new wxThreadInternal(); - - // TODO } wxThread::~wxThread() @@ -239,23 +405,33 @@ void wxThread::OnExit() Join(); } -// Automatic initialization -class wxThreadModule : public wxModule { +//-------------------------------------------------------------------- +// wxThreadModule +//-------------------------------------------------------------------- + +class wxThreadModule : public wxModule +{ DECLARE_DYNAMIC_CLASS(wxThreadModule) + public: - virtual bool OnInit() { - /* TODO p_mainid = GetCurrentThread(); */ - wxMainMutex = new wxMutex(); - wxMainMutex->Lock(); - return TRUE; - } - - // Global cleanup - virtual void OnExit() { - wxMainMutex->Unlock(); - delete wxMainMutex; + virtual bool OnInit() + { + wxMainMutex = new wxMutex(); + wxThreadGuiInit(); + p_mainid = pthread_self(); + wxMainMutex->Lock(); + + return TRUE; + } + + virtual void OnExit() + { + wxMainMutex->Unlock(); + wxThreadGuiExit(); + delete wxMainMutex; } }; IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule) + -- 2.47.2