$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r85864 - in trunk: boost/thread boost/thread/detail libs/thread/doc libs/thread/src/pthread libs/thread/src/win32 libs/thread/test
From: tim_at_[hidden]
Date: 2013-09-24 02:41:24
Author: timblechmann
Date: 2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)
New Revision: 85864
URL: http://svn.boost.org/trac/boost/changeset/85864
Log:
thread: implement physical_concurrency
Added:
   trunk/libs/thread/test/test_physical_concurrency.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/thread/detail/thread.hpp                 |     1                                         
   trunk/boost/thread/scoped_thread.hpp                 |     6 +++                                     
   trunk/libs/thread/doc/scoped_thread.qbk              |    15 ++++++++++                              
   trunk/libs/thread/doc/thread_ref.qbk                 |    16 ++++++++++                              
   trunk/libs/thread/src/pthread/thread.cpp             |    59 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/thread/src/win32/thread.cpp               |    25 ++++++++++++++++                        
   trunk/libs/thread/test/Jamfile.v2                    |     1                                         
   trunk/libs/thread/test/test_physical_concurrency.cpp |    24 ++++++++++++++++                        
   8 files changed, 145 insertions(+), 2 deletions(-)
Modified: trunk/boost/thread/detail/thread.hpp
==============================================================================
--- trunk/boost/thread/detail/thread.hpp	Tue Sep 24 01:35:11 2013	(r85863)
+++ trunk/boost/thread/detail/thread.hpp	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -546,6 +546,7 @@
         void detach();
 
         static unsigned hardware_concurrency() BOOST_NOEXCEPT;
+        static unsigned physical_concurrency() BOOST_NOEXCEPT;
 
 #define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
         typedef detail::thread_data_base::native_handle_type native_handle_type;
Modified: trunk/boost/thread/scoped_thread.hpp
==============================================================================
--- trunk/boost/thread/scoped_thread.hpp	Tue Sep 24 01:35:11 2013	(r85863)
+++ trunk/boost/thread/scoped_thread.hpp	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -261,11 +261,15 @@
     }
 #endif
 
-    static unsigned hardware_concurrency()BOOST_NOEXCEPT
+    static unsigned hardware_concurrency() BOOST_NOEXCEPT
     {
       return thread::hardware_concurrency();
     }
 
+    static unsigned physical_concurrency() BOOST_NOEXCEPT
+    {
+      return thread::physical_concurrency();
+    }
   };
 
   /**
Modified: trunk/libs/thread/doc/scoped_thread.qbk
==============================================================================
--- trunk/libs/thread/doc/scoped_thread.qbk	Tue Sep 24 01:35:11 2013	(r85863)
+++ trunk/libs/thread/doc/scoped_thread.qbk	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -216,6 +216,7 @@
         void detach();
 
         static unsigned hardware_concurrency() noexcept;
+        static unsigned physical_concurrency() noexcept;
 
         typedef thread::native_handle_type native_handle_type;
         native_handle_type native_handle();
@@ -458,6 +459,20 @@
 
 [endsect]
 
+
+[section:physical_concurrency Static member function `physical_concurrency()`]
+
+    unsigned physical_concurrency() noexecpt;
+
+[variablelist
+
+[[Effects:] [Equivalent to return `thread::physical_concurrency()`.]]
+
+]
+
+[endsect]
+
+
 [section:nativehandle Member function `native_handle()`]
 
     typedef thread::native_handle_type native_handle_type;
Modified: trunk/libs/thread/doc/thread_ref.qbk
==============================================================================
--- trunk/libs/thread/doc/thread_ref.qbk	Tue Sep 24 01:35:11 2013	(r85863)
+++ trunk/libs/thread/doc/thread_ref.qbk	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -470,6 +470,7 @@
         void detach();
 
         static unsigned hardware_concurrency() noexcept;
+        static unsigned physical_concurrency() noexcept;
 
         typedef platform-specific-type native_handle_type;
         native_handle_type native_handle();
@@ -991,6 +992,21 @@
 
 [endsect]
 
+[section:physical_concurrency Static member function `physical_concurrency()`]
+
+    unsigned physical_concurrency() noexecpt;
+
+[variablelist
+
+[[Returns:] [The number of physical cores available on the current system. In contrast to `hardware_concurrency()` it does not return
+ the number of virtual cores, but it counts only physical cores.]]
+
+[[Throws:] [Nothing]]
+
+]
+
+[endsect]
+
 [section:nativehandle Member function `native_handle()`]
 
     typedef platform-specific-type native_handle_type;
Modified: trunk/libs/thread/src/pthread/thread.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/thread.cpp	Tue Sep 24 01:35:11 2013	(r85863)
+++ trunk/libs/thread/src/pthread/thread.cpp	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -27,6 +27,15 @@
 #include <unistd.h>
 #endif
 
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <fstream>
+#include <string>
+#include <set>
+#include <vector>
+
 #include "./timeconv.inl"
 
 namespace boost
@@ -543,6 +552,56 @@
 #endif
     }
 
+    unsigned thread::physical_concurrency() BOOST_NOEXCEPT
+    {
+#ifdef __linux__
+        try {
+            using namespace std;
+
+            ifstream proc_cpuinfo ("/proc/cpuinfo");
+
+            unsigned current_processor = 0;
+            const string physical_id("physical id"), core_id("core id");
+
+            typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id]
+
+            std::set<core_entry> cores;
+
+            core_entry current_core_entry;
+
+            for (string line; getline(proc_cpuinfo, line); ) {
+                vector<string> key_val(2);
+                boost::split(key_val, line, boost::is_any_of(":"));
+
+                string key   = key_val[0];
+                string value = key_val[1];
+                boost::trim(key);
+                boost::trim(value);
+
+                if (key == physical_id) {
+                    current_core_entry.first = boost::lexical_cast<unsigned>(value);
+                    continue;
+                }
+
+                if (key == core_id) {
+                    current_core_entry.second = boost::lexical_cast<unsigned>(value);
+                    cores.insert(current_core_entry);
+                    continue;
+                }
+            }
+            return cores.size();
+        } catch(...) {
+            return 0;
+        }
+#elif defined(__APPLE__)
+        int count;
+        size_t size=sizeof(count);
+        return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count;
+#else
+        return hardware_concurrency();
+#endif
+    }
+
 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     void thread::interrupt()
     {
Modified: trunk/libs/thread/src/win32/thread.cpp
==============================================================================
--- trunk/libs/thread/src/win32/thread.cpp	Tue Sep 24 01:35:11 2013	(r85863)
+++ trunk/libs/thread/src/win32/thread.cpp	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -407,6 +407,8 @@
         return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
     }
 
+#endif
+
     unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
     {
         //SYSTEM_INFO info={{0}};
@@ -414,7 +416,28 @@
         GetSystemInfo(&info);
         return info.dwNumberOfProcessors;
     }
-#endif
+
+    unsigned thread::physical_concurrency() BOOST_NOEXCEPT
+    {
+        unsigned cores = 0;
+        DWORD size = 0;
+
+        GetLogicalProcessorInformation(NULL, &size);
+        if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
+            return 0;
+
+        std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(size);
+        if (GetLogicalProcessorInformation(buffer.data(), &size) == FALSE)
+            return 0;
+
+        const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+
+        for (size_t i = 0; i < Elements; ++i) {
+            if (buffer[i].Relationship == RelationProcessorCore)
+                ++cores;
+        }
+        return cores;
+    }
 
     thread::native_handle_type thread::native_handle()
     {
Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2	Tue Sep 24 01:35:11 2013	(r85863)
+++ trunk/libs/thread/test/Jamfile.v2	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -209,6 +209,7 @@
           [ thread-test test_thread.cpp ]
           [ thread-test test_thread_id.cpp ]
           [ thread-test test_hardware_concurrency.cpp ]
+          [ thread-test test_physical_concurrency.cpp ]
           [ thread-test test_thread_move.cpp ]
           [ thread-test test_thread_return_local.cpp ]
           [ thread-test test_thread_move_return.cpp ]
Added: trunk/libs/thread/test/test_physical_concurrency.cpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/thread/test/test_physical_concurrency.cpp	2013-09-24 02:41:24 EDT (Tue, 24 Sep 2013)	(r85864)
@@ -0,0 +1,24 @@
+// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2013 Tim Blechmann
+//
+//  Distributed under the Boost Software License, Version 1.0. (See accompanying
+//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/thread/thread_only.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread/mutex.hpp>
+
+void test_physical_concurrency_is_non_zero()
+{
+    BOOST_CHECK(boost::thread::physical_concurrency()!=0);
+}
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char*[])
+{
+    boost::unit_test::test_suite* test =
+        BOOST_TEST_SUITE("Boost.Threads: physical concurrency test suite");
+
+    test->add(BOOST_TEST_CASE(test_physical_concurrency_is_non_zero));
+    return test;
+}
+
+