From eaf4bde6e6585874c4d21a355231813fe08040f6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 20 Jan 2013 02:10:12 +0000 Subject: [PATCH] Add wxProcess::SetPriority() to allow setting the priority of child processes. This uses the same conventions as wxThread::SetPriority() but works on the entire process. Closes #14931. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73406 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- configure | 13 +++++++++++++ configure.in | 6 ++++++ docs/changes.txt | 1 + include/wx/process.h | 11 +++++++++++ interface/wx/process.h | 14 ++++++++++++++ setup.h.in | 3 +++ src/common/process.cpp | 8 ++++++++ src/msw/utilsexc.cpp | 20 ++++++++++++++++++++ src/unix/threadpsx.cpp | 5 ++++- src/unix/utilsunx.cpp | 26 ++++++++++++++++++++++++++ 10 files changed, 106 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 435cefc3c4..7feb68bd40 100755 --- a/configure +++ b/configure @@ -35173,6 +35173,19 @@ $as_echo "$wx_cv_struct_tm_has_gmtoff" >&6; } fi +for ac_func in setpriority +do : + ac_fn_c_check_func "$LINENO" "setpriority" "ac_cv_func_setpriority" +if test "x$ac_cv_func_setpriority" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETPRIORITY 1 +_ACEOF + +fi +done + + + if test "$wxUSE_SOCKETS" = "yes"; then if test "$TOOLKIT" != "MSW"; then ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" diff --git a/configure.in b/configure.in index 20a45a24d4..9e60cef948 100644 --- a/configure.in +++ b/configure.in @@ -6147,6 +6147,12 @@ if test "$wxUSE_DATETIME" = "yes"; then SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS typetest" fi +dnl ------------------------------------------------------------------------ +dnl wxProcess +dnl ------------------------------------------------------------------------ + +AC_CHECK_FUNCS(setpriority) + dnl ------------------------------------------------------------------------ dnl wxSocket dnl ------------------------------------------------------------------------ diff --git a/docs/changes.txt b/docs/changes.txt index 606d65d40d..08b630feda 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -546,6 +546,7 @@ All: - Add new wxFSW_EVENT_ATTRIB and wxFSW_EVENT_UNMOUNT flags (David Hart). - Add separate read/written bytes counters and per-direction NOWAIT and WAITALL flags to wxSocket (Rob Bresalier). +- Add wxProcess::SetPriority() (Marian Meravy). - Add wxDir::Close() method (Silverstorm82). - Fix wxDateTime::GetWeekOfYear() for the last week of year (aimo). - Fix compilation of wxHash{Map,Set} with g++ 4.7 (Nathan Ridge). diff --git a/include/wx/process.h b/include/wx/process.h index 2f1027ae64..5a893a7ed5 100644 --- a/include/wx/process.h +++ b/include/wx/process.h @@ -104,6 +104,15 @@ public: wxInputStream *errStream); #endif // wxUSE_STREAMS + // priority + // Sets the priority to the given value: see wxPRIORITY_XXX constants. + // + // NB: the priority can only be set before the process is created + void SetPriority(unsigned priority); + + // Get the current priority. + unsigned GetPriority() const { return m_priority; } + // implementation only - don't use! // -------------------------------- @@ -116,6 +125,8 @@ protected: int m_id; long m_pid; + unsigned m_priority; + #if wxUSE_STREAMS // these streams are connected to stdout, stderr and stdin of the child // process respectively (yes, m_inputStream corresponds to stdout -- very diff --git a/interface/wx/process.h b/interface/wx/process.h index b47276ebc4..d7ab0baff0 100644 --- a/interface/wx/process.h +++ b/interface/wx/process.h @@ -243,6 +243,20 @@ public: The caught output stream is returned by GetInputStream() as a non-seekable stream. */ void Redirect(); + + /** + Sets the priority of the process, between 0 (lowest) and 100 (highest). + It can only be set before the process is created. + + The following symbolic constants can be used in addition to raw + values in 0..100 range: + - @b wxPRIORITY_MIN: 0 + - @b wxPRIORITY_DEFAULT: 50 + - @b wxPRIORITY_MAX: 100 + + @since 2.9.5 + */ + void SetPriority(unsigned priority); }; diff --git a/setup.h.in b/setup.h.in index 4f6412de9e..9f3391f000 100644 --- a/setup.h.in +++ b/setup.h.in @@ -1240,6 +1240,9 @@ /* Define if getgrgid_r is available. */ #undef HAVE_GETGRGID_R +/* Define if setpriority() is available. */ +#undef HAVE_SETPRIORITY + /* Define if locale_t is available */ #undef HAVE_LOCALE_T diff --git a/src/common/process.cpp b/src/common/process.cpp index 210068e955..2a4f5f5416 100644 --- a/src/common/process.cpp +++ b/src/common/process.cpp @@ -50,6 +50,7 @@ void wxProcess::Init(wxEvtHandler *parent, int id, int flags) m_id = id; m_pid = 0; + m_priority = wxPRIORITY_DEFAULT; m_redirect = (flags & wxPROCESS_REDIRECT) != 0; #if wxUSE_STREAMS @@ -176,3 +177,10 @@ bool wxProcess::Exists(int pid) } } +void wxProcess::SetPriority(unsigned priority) +{ + wxCHECK_RET( priority >= wxPRIORITY_MIN && priority <= wxPRIORITY_MAX, + wxS("Invalid process priority value.") ); + + m_priority = priority; +} diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index cd3572e44d..e9f7ae28b5 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -852,6 +852,26 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler, } } + // Translate wxWidgets priority to Windows conventions. + unsigned prio = handler->GetPriority(); + if ( prio <= 20 ) + dwFlags |= IDLE_PRIORITY_CLASS; + else if ( prio <= 40 ) + dwFlags |= BELOW_NORMAL_PRIORITY_CLASS; + else if ( prio <= 60 ) + dwFlags |= NORMAL_PRIORITY_CLASS; + else if ( prio <= 80 ) + dwFlags |= ABOVE_NORMAL_PRIORITY_CLASS; + else if ( prio <= 99 ) + dwFlags |= HIGH_PRIORITY_CLASS; + else if ( prio <= 100 ) + dwFlags |= REALTIME_PRIORITY_CLASS; + else + { + wxFAIL_MSG(wxT("invalid value of thread priority parameter")); + dwFlags |= THREAD_PRIORITY_NORMAL; + } + bool ok = ::CreateProcess ( // WinCE requires appname to be non null diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index b04eb1d60d..952c77c9c7 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -58,10 +58,13 @@ #include #endif +#ifdef HAVE_SETPRIORITY + #include // for setpriority() +#endif + // we use wxFFile under Linux in GetCPUCount() #ifdef __LINUX__ #include "wx/ffile.h" - #include // for setpriority() #endif #define THR_ID_CAST(id) (reinterpret_cast(id)) diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index a09fb424df..eb01ae41c5 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -132,6 +132,10 @@ #include // for SAGET and MINFO structures #endif +#ifdef HAVE_SETPRIORITY + #include // for setpriority() +#endif + // ---------------------------------------------------------------------------- // conditional compilation // ---------------------------------------------------------------------------- @@ -545,6 +549,21 @@ long wxExecute(char **argv, int flags, wxProcess *process, } } + // priority: we need to map wxWidgets priority which is in the range 0..100 + // to Unix nice value which is in the range -20..19. As there is an odd + // number of elements in our range and an even number in the Unix one, we + // have to do it in this rather ugly way to guarantee that: + // 1. wxPRIORITY_{MIN,DEFAULT,MAX} map to -20, 0 and 19 respectively. + // 2. The mapping is monotonously increasing. + // 3. The mapping is onto the target range. + int prio = process->GetPriority(); + if ( prio <= 50 ) + prio = (2*prio)/5 - 20; + else if ( prio < 55 ) + prio = 1; + else + prio = (2*prio)/5 - 21; + // fork the process // // NB: do *not* use vfork() here, it completely breaks this code for some @@ -578,6 +597,13 @@ long wxExecute(char **argv, int flags, wxProcess *process, } #endif // !__VMS +#if defined(HAVE_SETPRIORITY) + if ( setpriority(PRIO_PROCESS, 0, prio) != 0 ) + { + wxLogSysError(_("Failed to set process priority")); + } +#endif // HAVE_SETPRIORITY + // redirect stdin, stdout and stderr if ( pipeIn.IsOk() ) { -- 2.45.2