From ef8d96c29c73b9da8cdaa2b8b4737862c85ccc20 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 6 Dec 1999 12:31:04 +0000 Subject: [PATCH] wxThread::GetCPUCount() and SetConcurrency() added and documented git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4837 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 4 ++- docs/latex/wx/thread.tex | 21 ++++++++++++ include/wx/thread.h | 15 +++++++++ samples/console/console.cpp | 6 ++-- src/common/textfile.cpp | 5 +++ src/msw/thread.cpp | 11 +++++++ src/unix/threadpsx.cpp | 66 +++++++++++++++++++++++++++++++++++++ 7 files changed, 125 insertions(+), 3 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 861a746147..ee12fcb7d0 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -6,7 +6,9 @@ next release (2.1.12 or 2.2?) wxBase: -- wxThread class modified to support both detached and joinable threads +- wxThread class modified to support both detached and joinable threads, also + added new GetCPUCount() and SetConcurrency() functions (useful under Solaris + only so far) - wxLog functions are now (more) MT-safe - wxStopWatch class, timer functions have more chances to return correct results for your platform (use ANSI function where available) diff --git a/docs/latex/wx/thread.tex b/docs/latex/wx/thread.tex index cfdbc20879..f7c4a1997e 100644 --- a/docs/latex/wx/thread.tex +++ b/docs/latex/wx/thread.tex @@ -127,6 +127,16 @@ joinable threads and is the value returned by \helpref{Wait}{wxthreadwait}. This function is called by wxWindows itself and should never be called directly. +\membersection{wxThread::GetCPUCount}\label{wxthreadgetcpucount} + +\func{static int}{GetCPUCount}{\void} + +Returns the number of system CPUs or -1 if the value is unknown. + +\wxheading{See also} + +\helpref{SetConcurrency}{wxthreadsetconcurrency} + \membersection{wxThread::GetId}\label{wxthreadgetid} \constfunc{unsigned long}{GetId}{\void} @@ -253,6 +263,17 @@ Resumes a thread suspended by the call to \helpref{Pause}{wxthreadpause}. This function can only be called from another thread context. +\membersection{wxThread::SetConcurrency}\label{wxthreadsetconcurrency} + +\func{static bool}{SetConcurrency}{\param{size\_t }{level}} + +Sets the thread concurrency level for this process. This is, roughly, the +number of threads that the system tries to schedule to run in parallel. +The value of $0$ for {\it level} may be used to set the default one. + +Returns TRUE on success or FALSE otherwise (for example, if this function is +not implemented for this platform (currently everything except Solaris)). + \membersection{wxThread::TestDestroy}\label{wxthreadtestdestroy} \func{bool}{TestDestroy}{\void} diff --git a/include/wx/thread.h b/include/wx/thread.h index 7c9df994de..a4c4b465df 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -280,6 +280,21 @@ public: // NB: at least under MSW worker threads can not call ::wxSleep()! static void Sleep(unsigned long milliseconds); + // get the number of system CPUs - useful with SetConcurrency() + // (the "best" value for it is usually number of CPUs + 1) + // + // Returns -1 if unknown, number of CPUs otherwise + static int GetCPUCount(); + + // sets the concurrency level: this is, roughly, the number of threads + // the system tries to schedule to run in parallel. 0 means the + // default value (usually acceptable, but may not yield the best + // performance for this process) + // + // Returns TRUE on success, FALSE otherwise (if not implemented, for + // example) + static bool SetConcurrency(size_t level); + // constructor only creates the C++ thread object and doesn't create (or // start) the real thread wxThread(wxThreadKind kind = wxTHREAD_DETACHED); diff --git a/samples/console/console.cpp b/samples/console/console.cpp index 981a302ac3..0a08f86c14 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -32,8 +32,8 @@ //#define TEST_ARRAYS //#define TEST_LOG //#define TEST_STRINGS -//#define TEST_THREADS -#define TEST_TIME +#define TEST_THREADS +//#define TEST_TIME //#define TEST_LONGLONG // ============================================================================ @@ -647,6 +647,8 @@ int main(int argc, char **argv) #endif // TEST_LOG #ifdef TEST_THREADS + printf("This system has %d CPUs\n", wxThread::GetCPUCount()); + if ( argc > 1 && argv[1][0] == 't' ) wxLog::AddTraceMask("thread"); diff --git a/src/common/textfile.cpp b/src/common/textfile.cpp index 9b35dfd8de..5c74b3ab57 100644 --- a/src/common/textfile.cpp +++ b/src/common/textfile.cpp @@ -145,6 +145,11 @@ wxTextFile::~wxTextFile() // file operations // ---------------------------------------------------------------------------- +bool wxTextFile::Exists() const +{ + return wxFile::Exists(m_strFile); +} + bool wxTextFile::Open(const wxString& strFile) { m_strFile = strFile; diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index 3ae5d7b979..35838d9a29 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -527,6 +527,17 @@ void wxThread::Sleep(unsigned long milliseconds) ::Sleep(milliseconds); } +int wxThread::GetCPUCount() +{ + return -1; +} + +bool wxThread::SetConcurrency(size_t level) +{ + // ok only for the default one + return level == 0; +} + // ctor and dtor // ------------- diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index fad73a2df9..34f3cd81b4 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -45,6 +45,15 @@ #include #endif +#ifdef HAVE_THR_SETCONCURRENCY + #include +#endif + +// we use wxFFile under Linux in GetCPUCount() +#ifdef __LINUX__ + #include "wx/ffile.h" +#endif + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -834,6 +843,63 @@ void wxThread::Sleep(unsigned long milliseconds) wxUsleep(milliseconds); } +int wxThread::GetCPUCount() +{ +#if defined(__LINUX__) + // read from proc (can't use wxTextFile here because it's a special file: + // it has 0 size but still can be read from) + wxLogNull nolog; + + wxFFile file(_T("/proc/cpuinfo")); + if ( file.IsOpened() ) + { + // slurp the whole file + wxString s; + if ( file.ReadAll(&s) ) + { + // (ab)use Replace() to find the number of "processor" strings + size_t count = s.Replace(_T("processor"), _T("")); + if ( count > 0 ) + { + return count; + } + + wxLogDebug(_T("failed to parse /proc/cpuinfo")); + } + else + { + wxLogDebug(_T("failed to read /proc/cpuinfo")); + } + } +#elif defined(_SC_NPROCESSORS_ONLN) + // this works for Solaris + int rc = sysconf(_SC_NPROCESSORS_ONLN); + if ( rc != -1 ) + { + return rc; + } +#endif // different ways to get number of CPUs + + // unknown + return -1; +} + +bool wxThread::SetConcurrency(size_t level) +{ +#ifdef HAVE_THR_SETCONCURRENCY + int rc = thr_setconcurrency(level); + if ( rc != 0 ) + { + wxLogSysError(rc, _T("thr_setconcurrency() failed")); + } + + return rc == 0; +#else // !HAVE_THR_SETCONCURRENCY + // ok only for the default value + return level == 0; +#endif // HAVE_THR_SETCONCURRENCY/!HAVE_THR_SETCONCURRENCY +} + // ----------------------------------------------------------------------------- // creating thread // ----------------------------------------------------------------------------- -- 2.45.2