Bladeren bron

added system test based on boost interprocess code. added new field (modified) in view data.

avkonst 11 jaren geleden
bovenliggende
commit
65a6902558
100 gewijzigde bestanden met toevoegingen van 21477 en 29 verwijderingen
  1. 4 3
      mainline/doc/home.html
  2. 11 4
      mainline/ext/std/tools/view.py
  3. 12 0
      mainline/tests/common.py
  4. 11 0
      mainline/tests/general/test_basic/test_std_general_metrics_view_nest_per_file_stdout.gold.txt
  5. 11 0
      mainline/tests/general/test_basic/test_std_lines_metrics_view_nest_per_file_stdout.gold.txt
  6. 11 11
      mainline/tests/general/test_basic/test_view_format_view_nest_per_file_stdout.gold.txt
  7. 11 11
      mainline/tests/general/test_basic/test_workflow_view_second_per_file_stdout.gold.txt
  8. 11 0
      mainline/tests/general/test_basic/test_workflow_view_second_per_file_txt_all_stdout.gold.txt
  9. 11 0
      mainline/tests/general/test_basic/test_workflow_view_second_per_file_txt_new_stdout.gold.txt
  10. 11 0
      mainline/tests/general/test_basic/test_workflow_view_second_per_file_txt_touched_stdout.gold.txt
  11. 107 0
      mainline/tests/general/test_std_code_cpp/test_parser_view_files_stdout.gold.txt
  12. 55 0
      mainline/tests/general/test_std_code_cs/test_parser_view_files_stdout.gold.txt
  13. 130 0
      mainline/tests/general/test_std_code_java/test_parser_view_files_stdout.gold.txt
  14. 131 0
      mainline/tests/system/test_boost_parts.py
  15. 468 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/adaptive_pool.hpp
  16. 311 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/allocator.hpp
  17. 356 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/cached_adaptive_pool.hpp
  18. 327 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/cached_node_allocator.hpp
  19. 108 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/adaptive_node_pool.hpp
  20. 867 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/allocator_common.hpp
  21. 109 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/node_pool.hpp
  22. 50 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/node_tools.hpp
  23. 452 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/node_allocator.hpp
  24. 468 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/private_adaptive_pool.hpp
  25. 445 0
      mainline/tests/system/test_boost_parts/sources/interprocess/allocators/private_node_allocator.hpp
  26. 117 0
      mainline/tests/system/test_boost_parts/sources/interprocess/anonymous_shared_memory.hpp
  27. 40 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/allocation_type.hpp
  28. 40 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/containers_fwd.hpp
  29. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/deque.hpp
  30. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/flat_map.hpp
  31. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/flat_set.hpp
  32. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/list.hpp
  33. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/map.hpp
  34. 34 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/pair.hpp
  35. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/set.hpp
  36. 32 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/slist.hpp
  37. 32 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/stable_vector.hpp
  38. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/string.hpp
  39. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/vector.hpp
  40. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/containers/version_type.hpp
  41. 77 0
      mainline/tests/system/test_boost_parts/sources/interprocess/creation_tags.hpp
  42. 562 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/atomic.hpp
  43. 29 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/cast_tags.hpp
  44. 48 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/config_begin.hpp
  45. 17 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/config_end.hpp
  46. 298 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/file_locking_helpers.hpp
  47. 202 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/file_wrapper.hpp
  48. 73 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/in_place_interface.hpp
  49. 48 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/intermodule_singleton.hpp
  50. 495 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/intermodule_singleton_common.hpp
  51. 31 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/interprocess_tester.hpp
  52. 1040 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/intersegment_ptr.hpp
  53. 115 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_global_memory.hpp
  54. 750 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_memory_impl.hpp
  55. 408 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_multi_shared_memory.hpp
  56. 484 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_open_or_create_impl.hpp
  57. 110 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/math_functions.hpp
  58. 40 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/min_max.hpp
  59. 28 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/move.hpp
  60. 152 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/mpl.hpp
  61. 46 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/multi_segment_services.hpp
  62. 349 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/named_proxy.hpp
  63. 696 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/os_file_functions.hpp
  64. 211 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/os_thread_functions.hpp
  65. 74 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/pointer_type.hpp
  66. 356 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/portable_intermodule_singleton.hpp
  67. 42 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/posix_time_types_wrk.hpp
  68. 203 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/preprocessor.hpp
  69. 33 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/ptime_wrk.hpp
  70. 439 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/robust_emulation.hpp
  71. 513 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/segment_manager_helper.hpp
  72. 181 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/tmp_dir_helpers.hpp
  73. 195 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/transform_iterator.hpp
  74. 158 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/type_traits.hpp
  75. 218 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/utilities.hpp
  76. 153 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/variadic_templates_tools.hpp
  77. 1852 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/win32_api.hpp
  78. 306 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/windows_intermodule_singleton.hpp
  79. 160 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/workaround.hpp
  80. 392 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/xsi_shared_memory_device.hpp
  81. 80 0
      mainline/tests/system/test_boost_parts/sources/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
  82. 236 0
      mainline/tests/system/test_boost_parts/sources/interprocess/errors.hpp
  83. 150 0
      mainline/tests/system/test_boost_parts/sources/interprocess/exceptions.hpp
  84. 184 0
      mainline/tests/system/test_boost_parts/sources/interprocess/file_mapping.hpp
  85. 78 0
      mainline/tests/system/test_boost_parts/sources/interprocess/indexes/flat_map_index.hpp
  86. 150 0
      mainline/tests/system/test_boost_parts/sources/interprocess/indexes/iset_index.hpp
  87. 368 0
      mainline/tests/system/test_boost_parts/sources/interprocess/indexes/iunordered_set_index.hpp
  88. 100 0
      mainline/tests/system/test_boost_parts/sources/interprocess/indexes/map_index.hpp
  89. 68 0
      mainline/tests/system/test_boost_parts/sources/interprocess/indexes/null_index.hpp
  90. 113 0
      mainline/tests/system/test_boost_parts/sources/interprocess/indexes/unordered_map_index.hpp
  91. 418 0
      mainline/tests/system/test_boost_parts/sources/interprocess/interprocess_fwd.hpp
  92. 900 0
      mainline/tests/system/test_boost_parts/sources/interprocess/ipc/message_queue.hpp
  93. 113 0
      mainline/tests/system/test_boost_parts/sources/interprocess/managed_external_buffer.hpp
  94. 148 0
      mainline/tests/system/test_boost_parts/sources/interprocess/managed_heap_memory.hpp
  95. 217 0
      mainline/tests/system/test_boost_parts/sources/interprocess/managed_mapped_file.hpp
  96. 215 0
      mainline/tests/system/test_boost_parts/sources/interprocess/managed_shared_memory.hpp
  97. 194 0
      mainline/tests/system/test_boost_parts/sources/interprocess/managed_windows_shared_memory.hpp
  98. 198 0
      mainline/tests/system/test_boost_parts/sources/interprocess/managed_xsi_shared_memory.hpp
  99. 883 0
      mainline/tests/system/test_boost_parts/sources/interprocess/mapped_region.hpp
  100. 0 0
      mainline/tests/system/test_boost_parts/sources/interprocess/mem_algo/detail/mem_algo_common.hpp

+ 4 - 3
mainline/doc/home.html

@@ -197,14 +197,14 @@
             <li>Assisiting on <strong>per minute</strong> basis during code refactoring and code development, where coding and quality standards matter.</li>
           </ul>
 
-          <p>The workflow sections explain basic application principles.</p>
+          <p>The workflow sections below demonstarate basic application usecases.</p>
 
           <h3>Languages supported</h3>
           <p>The tool can parse C/C++, C# and Java source code files. The parser identifies certain regions in the code,
              such as classes, functions, namespaces, interfaces, etc. It obviously detects comments, strings and code for preprocessor.
              The identified regions form a tree of nested source code blocks, which are refered after and additionally scanned by metrics plugins.
              This concept allows to attribute metrics per regions, what gives fine grained data and rich input to analysis tools.
-             The following example demonstrates this.</p>
+             The following example demonstrates regions concept.</p>
              
           <table class="table">
             <thead>
@@ -293,7 +293,8 @@ file: __global__: comment
                 <td rowspan="4"><ul><li>Monitoring growth of source code base.</li>
                     <li>Normalizing other metrics.</li>
                     <li>Preventing large files and regions (large things difficult to maintain).</li>
-                    <li>Predicting delivery dates by comparing S-shaped code base growth / change curves.</li></ul></td>
+                    <li>Predicting delivery dates by comparing
+                        <a href="http://www.compaid.com/caiInternet/casestudies/kanarticle2.pdf">S-shaped code base growth / change curves</a>.</li></ul></td>
               </tr>
               <tr>
                 <td>std.code.length.total</td>

+ 11 - 4
mainline/ext/std/tools/view.py

@@ -305,13 +305,16 @@ def append_regions(file_data_tree, file_data, file_data_prev, nest_regions):
         regions = []
         for region in file_data.iterate_regions():
             region_data_tree = region.get_data_tree()
+            is_modified = None
             if regions_matcher != None and regions_matcher.is_matched(region.get_id()):
                 region_data_prev = file_data_prev.get_region(regions_matcher.get_prev_id(region.get_id()))
                 region_data_tree = append_diff(region_data_tree,
                                                region_data_prev.get_data_tree())
+                is_modified = regions_matcher.is_modified(region.get_id())
             regions.append({"info": {"name" : region.name,
-                                     'type' : file_data.get_region_types()().to_str(region.get_type()),
-                                     "cursor" : region.cursor,
+                                     'type': file_data.get_region_types()().to_str(region.get_type()),
+                                     'modified': is_modified,
+                                     'cursor' : region.cursor,
                                      'line_begin': region.line_begin,
                                      'line_end': region.line_end,
                                      'offset_begin': region.begin,
@@ -322,13 +325,16 @@ def append_regions(file_data_tree, file_data, file_data_prev, nest_regions):
         def append_rec(region_id, file_data_tree, file_data, file_data_prev):
             region = file_data.get_region(region_id)
             region_data_tree = region.get_data_tree()
+            is_modified = None
             if regions_matcher != None and regions_matcher.is_matched(region.get_id()):
                 region_data_prev = file_data_prev.get_region(regions_matcher.get_prev_id(region.get_id()))
                 region_data_tree = append_diff(region_data_tree,
                                                region_data_prev.get_data_tree())
+                is_modified = regions_matcher.is_modified(region.get_id())
             result = {"info": {"name" : region.name,
                                'type' : file_data.get_region_types()().to_str(region.get_type()),
-                               "cursor" : region.cursor,
+                               'modified': is_modified,
+                               'cursor' : region.cursor,
                                'line_begin': region.line_begin,
                                'line_end': region.line_end,
                                'offset_begin': region.begin,
@@ -532,7 +538,8 @@ def cout_txt_regions(path, regions, indent = 0):
             ('Region name', region['info']['name']),
             ('Region type', region['info']['type']),
             ('Offsets', str(region['info']['offset_begin']) + "-" + str(region['info']['offset_end'])),
-            ('Line numbers', str(region['info']['line_begin']) + "-" + str(region['info']['line_end']))
+            ('Line numbers', str(region['info']['line_begin']) + "-" + str(region['info']['line_end'])),
+            ('Modified', str(region['info']['modified']))
         ]
         for namespace in region['data'].keys():
             diff_data = {}

+ 12 - 0
mainline/tests/common.py

@@ -197,6 +197,17 @@ class ToolRunner(object):
         return self.dbfile_prev
     
 class TestCase(unittest.TestCase):
+    
+    def __init__(self, methodName='runTest'):
+        unittest.TestCase.__init__(self, methodName=methodName)
+        if 'METRIXPLUSPLUS_LOG_LEVEL' not in os.environ.keys():
+            # launch of individual unit test
+            os.environ['METRIXPLUSPLUS_LOG_LEVEL'] = 'ERROR'
+            os.environ['METRIXPLUSPLUS_INSTALL_DIR'] = os.path.dirname(os.path.dirname(__file__))
+            os.environ['METRIXPLUSPLUS_TEST_MODE'] = str("True")
+            if 'METRIXPLUSPLUS_TEST_GENERATE_GOLDS' not in os.environ.keys():
+                os.environ['METRIXPLUSPLUS_TEST_GENERATE_GOLDS'] = str("False")
+            os.chdir(os.environ['METRIXPLUSPLUS_INSTALL_DIR'])
 
     def get_content_paths(self, cwd='sources'): 
         curframe = inspect.currentframe()
@@ -220,6 +231,7 @@ class TestCase(unittest.TestCase):
         unittest.TestCase.setUp(self)
 
         logging.basicConfig(format="[TEST-LOG]: %(levelname)s:\t%(message)s", level=logging.WARN)
+
         log_level = os.environ['METRIXPLUSPLUS_LOG_LEVEL']
         if log_level == 'ERROR':
             log_level = logging.ERROR

+ 11 - 0
mainline/tests/general/test_basic/test_std_general_metrics_view_nest_per_file_stdout.gold.txt

@@ -3,66 +3,77 @@
 	Region type    : global
 	Offsets        : 0-697
 	Line numbers   : 1-71
+	Modified       : None
 
 .   ./simple.cpp:4: info: Metrics per 'hmm' region
     	Region name    : hmm
     	Region type    : namespace
     	Offsets        : 2-696
     	Line numbers   : 3-70
+    	Modified       : None
 
 .   .   ./simple.cpp:9: info: Metrics per 'A' region
         	Region name    : A
         	Region type    : class
         	Offsets        : 94-692
         	Line numbers   : 9-68
+        	Modified       : None
 
 .   .   .   ./simple.cpp:12: info: Metrics per 'A' region
             	Region name    : A
             	Region type    : function
             	Offsets        : 106-252
             	Line numbers   : 12-23
+            	Modified       : None
 
 .   .   .   ./simple.cpp:26: info: Metrics per 'func' region
             	Region name    : func
             	Region type    : function
             	Offsets        : 256-405
             	Line numbers   : 26-40
+            	Modified       : None
 
 .   .   .   .   ./simple.cpp:28: info: Metrics per 'embeded' region
                 	Region name    : embeded
                 	Region type    : class
                 	Offsets        : 285-391
                 	Line numbers   : 28-38
+                	Modified       : None
 
 .   .   .   .   .   ./simple.cpp:30: info: Metrics per 'embeded' region
                     	Region name    : embeded
                     	Region type    : function
                     	Offsets        : 306-387
                     	Line numbers   : 30-37
+                    	Modified       : None
 
 .   .   .   ./simple.cpp:42: info: Metrics per 'func_to_be_removed_in_new_sources' region
             	Region name    : func_to_be_removed_in_new_sources
             	Region type    : function
             	Offsets        : 408-596
             	Line numbers   : 42-56
+            	Modified       : None
 
 .   .   .   .   ./simple.cpp:44: info: Metrics per 'embeded' region
                 	Region name    : embeded
                 	Region type    : class
                 	Offsets        : 466-577
                 	Line numbers   : 44-54
+                	Modified       : None
 
 .   .   .   .   .   ./simple.cpp:46: info: Metrics per 'embeded' region
                     	Region name    : embeded
                     	Region type    : function
                     	Offsets        : 487-573
                     	Line numbers   : 46-53
+                    	Modified       : None
 
 .   .   .   ./simple.cpp:58: info: Metrics per 'never' region
             	Region name    : never
             	Region type    : function
             	Offsets        : 599-669
             	Line numbers   : 58-65
+            	Modified       : None
 
 ./simple.cpp:0: info: Metrics per file
 	std.general:proctime: 0.01

+ 11 - 0
mainline/tests/general/test_basic/test_std_lines_metrics_view_nest_per_file_stdout.gold.txt

@@ -3,6 +3,7 @@
 	Region type    : global
 	Offsets        : 0-697
 	Line numbers   : 1-71
+	Modified       : None
 	std.code.lines:code: 0
 	std.code.lines:total: 0
 	std.code.lines:preprocessor: 0
@@ -13,6 +14,7 @@
     	Region type    : namespace
     	Offsets        : 2-696
     	Line numbers   : 3-70
+    	Modified       : None
     	std.code.lines:code: 4
     	std.code.lines:total: 6
     	std.code.lines:preprocessor: 1
@@ -23,6 +25,7 @@
         	Region type    : class
         	Offsets        : 94-692
         	Line numbers   : 9-68
+        	Modified       : None
         	std.code.lines:code: 4
         	std.code.lines:total: 4
         	std.code.lines:preprocessor: 0
@@ -33,6 +36,7 @@
             	Region type    : function
             	Offsets        : 106-252
             	Line numbers   : 12-23
+            	Modified       : None
             	std.code.lines:code: 11
             	std.code.lines:total: 12
             	std.code.lines:preprocessor: 0
@@ -43,6 +47,7 @@
             	Region type    : function
             	Offsets        : 256-405
             	Line numbers   : 26-40
+            	Modified       : None
             	std.code.lines:code: 5
             	std.code.lines:total: 5
             	std.code.lines:preprocessor: 0
@@ -53,6 +58,7 @@
                 	Region type    : class
                 	Offsets        : 285-391
                 	Line numbers   : 28-38
+                	Modified       : None
                 	std.code.lines:code: 3
                 	std.code.lines:total: 3
                 	std.code.lines:preprocessor: 0
@@ -63,6 +69,7 @@
                     	Region type    : function
                     	Offsets        : 306-387
                     	Line numbers   : 30-37
+                    	Modified       : None
                     	std.code.lines:code: 7
                     	std.code.lines:total: 8
                     	std.code.lines:preprocessor: 0
@@ -73,6 +80,7 @@
             	Region type    : function
             	Offsets        : 408-596
             	Line numbers   : 42-56
+            	Modified       : None
             	std.code.lines:code: 5
             	std.code.lines:total: 5
             	std.code.lines:preprocessor: 0
@@ -83,6 +91,7 @@
                 	Region type    : class
                 	Offsets        : 466-577
                 	Line numbers   : 44-54
+                	Modified       : None
                 	std.code.lines:code: 3
                 	std.code.lines:total: 3
                 	std.code.lines:preprocessor: 0
@@ -93,6 +102,7 @@
                     	Region type    : function
                     	Offsets        : 487-573
                     	Line numbers   : 46-53
+                    	Modified       : None
                     	std.code.lines:code: 7
                     	std.code.lines:total: 8
                     	std.code.lines:preprocessor: 0
@@ -103,6 +113,7 @@
             	Region type    : function
             	Offsets        : 599-669
             	Line numbers   : 58-65
+            	Modified       : None
             	std.code.lines:code: 7
             	std.code.lines:total: 7
             	std.code.lines:preprocessor: 0

+ 11 - 11
mainline/tests/general/test_basic/test_view_format_view_nest_per_file_stdout.gold.txt

@@ -5,19 +5,19 @@
         <file-data>
             <regions>
                 <region>
-                    <info cursor="0" name="__global__" offset_end="836" line_begin="1" type="global" line_end="78" offset_begin="0" />
+                    <info cursor="0" name="__global__" type="global" offset_end="836" line_begin="1" line_end="78" modified="False" offset_begin="0" />
                     <data />
                     <subregions>
                         <subregion>
-                            <info cursor="4" name="hmm" offset_end="835" line_begin="3" type="namespace" line_end="77" offset_begin="2" />
+                            <info cursor="4" name="hmm" type="namespace" offset_end="835" line_begin="3" line_end="77" modified="True" offset_begin="2" />
                             <data />
                             <subregions>
                                 <subregion>
-                                    <info cursor="10" name="A" offset_end="831" line_begin="10" type="class" line_end="75" offset_begin="111" />
+                                    <info cursor="10" name="A" type="class" offset_end="831" line_begin="10" line_end="75" modified="True" offset_begin="111" />
                                     <data />
                                     <subregions>
                                         <subregion>
-                                            <info cursor="13" name="A" offset_end="269" line_begin="13" type="function" line_end="24" offset_begin="123" />
+                                            <info cursor="13" name="A" type="function" offset_end="269" line_begin="13" line_end="24" modified="False" offset_begin="123" />
                                             <data>
                                                 <std.code.complexity cyclomatic="3">
                                                     <__diff__ cyclomatic="0" />
@@ -27,7 +27,7 @@
                                             </subregions>
                                         </subregion>
                                         <subregion>
-                                            <info cursor="26" name="func" offset_end="455" line_begin="26" type="function" line_end="42" offset_begin="272" />
+                                            <info cursor="26" name="func" type="function" offset_end="455" line_begin="26" line_end="42" modified="False" offset_begin="272" />
                                             <data>
                                                 <std.code.complexity cyclomatic="1">
                                                     <__diff__ cyclomatic="0" />
@@ -35,11 +35,11 @@
                                             </data>
                                             <subregions>
                                                 <subregion>
-                                                    <info cursor="28" name="embeded" offset_end="441" line_begin="28" type="class" line_end="40" offset_begin="301" />
+                                                    <info cursor="28" name="embeded" type="class" offset_end="441" line_begin="28" line_end="40" modified="False" offset_begin="301" />
                                                     <data />
                                                     <subregions>
                                                         <subregion>
-                                                            <info cursor="30" name="embeded" offset_end="437" line_begin="30" type="function" line_end="39" offset_begin="322" />
+                                                            <info cursor="30" name="embeded" type="function" offset_end="437" line_begin="30" line_end="39" modified="True" offset_begin="322" />
                                                             <data>
                                                                 <std.code.complexity cyclomatic="2">
                                                                     <__diff__ cyclomatic="1" />
@@ -53,7 +53,7 @@
                                             </subregions>
                                         </subregion>
                                         <subregion>
-                                            <info cursor="44" name="never" offset_end="549" line_begin="44" type="function" line_end="51" offset_begin="458" />
+                                            <info cursor="44" name="never" type="function" offset_end="549" line_begin="44" line_end="51" modified="True" offset_begin="458" />
                                             <data>
                                                 <std.code.complexity cyclomatic="1">
                                                     <__diff__ cyclomatic="0" />
@@ -63,7 +63,7 @@
                                             </subregions>
                                         </subregion>
                                         <subregion>
-                                            <info cursor="53" name="new_func" offset_end="585" line_begin="53" type="function" line_end="56" offset_begin="552" />
+                                            <info cursor="53" name="new_func" type="function" offset_end="585" line_begin="53" line_end="56" modified="None" offset_begin="552" />
                                             <data>
                                                 <std.code.complexity cyclomatic="0" />
                                             </data>
@@ -71,7 +71,7 @@
                                             </subregions>
                                         </subregion>
                                         <subregion>
-                                            <info cursor="58" name="new_func_complex" offset_end="646" line_begin="58" type="function" line_end="62" offset_begin="588" />
+                                            <info cursor="58" name="new_func_complex" type="function" offset_end="646" line_begin="58" line_end="62" modified="None" offset_begin="588" />
                                             <data>
                                                 <std.code.complexity cyclomatic="1" />
                                             </data>
@@ -79,7 +79,7 @@
                                             </subregions>
                                         </subregion>
                                         <subregion>
-                                            <info cursor="65" name="new_func_complex_but_suppressed" offset_end="808" line_begin="64" type="function" line_end="72" offset_begin="649" />
+                                            <info cursor="65" name="new_func_complex_but_suppressed" type="function" offset_end="808" line_begin="64" line_end="72" modified="None" offset_begin="649" />
                                             <data>
                                                 <std.code.complexity cyclomatic="2" />
                                             </data>

+ 11 - 11
mainline/tests/general/test_basic/test_workflow_view_second_per_file_stdout.gold.txt

@@ -5,7 +5,7 @@
         <file-data>
             <regions>
                 <region>
-                    <info cursor="0" name="__global__" offset_end="836" line_begin="1" type="global" line_end="78" offset_begin="0" />
+                    <info cursor="0" name="__global__" type="global" offset_end="836" line_begin="1" line_end="78" modified="False" offset_begin="0" />
                     <data>
                         <std.code.lines total="0" code="0" preprocessor="0" comments="0">
                             <__diff__ code="0" total="0" preprocessor="0" comments="0" />
@@ -13,7 +13,7 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="4" name="hmm" offset_end="835" line_begin="3" type="namespace" line_end="77" offset_begin="2" />
+                    <info cursor="4" name="hmm" type="namespace" offset_end="835" line_begin="3" line_end="77" modified="True" offset_begin="2" />
                     <data>
                         <std.code.lines total="7" code="4" preprocessor="2" comments="1">
                             <__diff__ code="0" total="1" preprocessor="1" comments="0" />
@@ -21,7 +21,7 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="10" name="A" offset_end="831" line_begin="10" type="class" line_end="75" offset_begin="111" />
+                    <info cursor="10" name="A" type="class" offset_end="831" line_begin="10" line_end="75" modified="True" offset_begin="111" />
                     <data>
                         <std.code.lines total="4" code="4" preprocessor="0" comments="0">
                             <__diff__ code="0" total="0" preprocessor="0" comments="0" />
@@ -29,7 +29,7 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="13" name="A" offset_end="269" line_begin="13" type="function" line_end="24" offset_begin="123" />
+                    <info cursor="13" name="A" type="function" offset_end="269" line_begin="13" line_end="24" modified="False" offset_begin="123" />
                     <data>
                         <std.code.complexity cyclomatic="3">
                             <__diff__ cyclomatic="0" />
@@ -40,7 +40,7 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="26" name="func" offset_end="455" line_begin="26" type="function" line_end="42" offset_begin="272" />
+                    <info cursor="26" name="func" type="function" offset_end="455" line_begin="26" line_end="42" modified="False" offset_begin="272" />
                     <data>
                         <std.code.complexity cyclomatic="1">
                             <__diff__ cyclomatic="0" />
@@ -51,7 +51,7 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="28" name="embeded" offset_end="441" line_begin="28" type="class" line_end="40" offset_begin="301" />
+                    <info cursor="28" name="embeded" type="class" offset_end="441" line_begin="28" line_end="40" modified="False" offset_begin="301" />
                     <data>
                         <std.code.lines total="3" code="3" preprocessor="0" comments="0">
                             <__diff__ code="0" total="0" preprocessor="0" comments="0" />
@@ -59,7 +59,7 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="30" name="embeded" offset_end="437" line_begin="30" type="function" line_end="39" offset_begin="322" />
+                    <info cursor="30" name="embeded" type="function" offset_end="437" line_begin="30" line_end="39" modified="True" offset_begin="322" />
                     <data>
                         <std.code.complexity cyclomatic="2">
                             <__diff__ cyclomatic="1" />
@@ -70,7 +70,7 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="44" name="never" offset_end="549" line_begin="44" type="function" line_end="51" offset_begin="458" />
+                    <info cursor="44" name="never" type="function" offset_end="549" line_begin="44" line_end="51" modified="True" offset_begin="458" />
                     <data>
                         <std.code.complexity cyclomatic="1">
                             <__diff__ cyclomatic="0" />
@@ -81,21 +81,21 @@
                     </data>
                 </region>
                 <region>
-                    <info cursor="53" name="new_func" offset_end="585" line_begin="53" type="function" line_end="56" offset_begin="552" />
+                    <info cursor="53" name="new_func" type="function" offset_end="585" line_begin="53" line_end="56" modified="None" offset_begin="552" />
                     <data>
                         <std.code.complexity cyclomatic="0" />
                         <std.code.lines total="4" code="3" preprocessor="0" comments="1" />
                     </data>
                 </region>
                 <region>
-                    <info cursor="58" name="new_func_complex" offset_end="646" line_begin="58" type="function" line_end="62" offset_begin="588" />
+                    <info cursor="58" name="new_func_complex" type="function" offset_end="646" line_begin="58" line_end="62" modified="None" offset_begin="588" />
                     <data>
                         <std.code.complexity cyclomatic="1" />
                         <std.code.lines total="5" code="5" preprocessor="0" comments="0" />
                     </data>
                 </region>
                 <region>
-                    <info cursor="65" name="new_func_complex_but_suppressed" offset_end="808" line_begin="64" type="function" line_end="72" offset_begin="649" />
+                    <info cursor="65" name="new_func_complex_but_suppressed" type="function" offset_end="808" line_begin="64" line_end="72" modified="None" offset_begin="649" />
                     <data>
                         <std.code.complexity cyclomatic="2" />
                         <std.suppress count="1" list="[std.code.complexity:cyclomatic]" />

+ 11 - 0
mainline/tests/general/test_basic/test_workflow_view_second_per_file_txt_all_stdout.gold.txt

@@ -3,6 +3,7 @@
 	Region type    : global
 	Offsets        : 0-836
 	Line numbers   : 1-78
+	Modified       : False
 	std.code.lines:code: 0 [+0]
 	std.code.lines:total: 0 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -13,6 +14,7 @@
 	Region type    : namespace
 	Offsets        : 2-835
 	Line numbers   : 3-77
+	Modified       : True
 	std.code.lines:code: 4 [+0]
 	std.code.lines:total: 7 [+1]
 	std.code.lines:preprocessor: 2 [+1]
@@ -23,6 +25,7 @@
 	Region type    : class
 	Offsets        : 111-831
 	Line numbers   : 10-75
+	Modified       : True
 	std.code.lines:code: 4 [+0]
 	std.code.lines:total: 4 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -33,6 +36,7 @@
 	Region type    : function
 	Offsets        : 123-269
 	Line numbers   : 13-24
+	Modified       : False
 	std.code.complexity:cyclomatic: 3 [+0]
 	std.code.lines:code: 11 [+0]
 	std.code.lines:total: 12 [+0]
@@ -44,6 +48,7 @@
 	Region type    : function
 	Offsets        : 272-455
 	Line numbers   : 26-42
+	Modified       : False
 	std.code.complexity:cyclomatic: 1 [+0]
 	std.code.lines:code: 5 [+0]
 	std.code.lines:total: 5 [+0]
@@ -55,6 +60,7 @@
 	Region type    : class
 	Offsets        : 301-441
 	Line numbers   : 28-40
+	Modified       : False
 	std.code.lines:code: 3 [+0]
 	std.code.lines:total: 3 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -65,6 +71,7 @@
 	Region type    : function
 	Offsets        : 322-437
 	Line numbers   : 30-39
+	Modified       : True
 	std.code.complexity:cyclomatic: 2 [+1]
 	std.code.lines:code: 8 [+1]
 	std.code.lines:total: 9 [+1]
@@ -76,6 +83,7 @@
 	Region type    : function
 	Offsets        : 458-549
 	Line numbers   : 44-51
+	Modified       : True
 	std.code.complexity:cyclomatic: 1 [+0]
 	std.code.lines:code: 7 [+0]
 	std.code.lines:total: 7 [+0]
@@ -87,6 +95,7 @@
 	Region type    : function
 	Offsets        : 552-585
 	Line numbers   : 53-56
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 	std.code.lines:code: 3
 	std.code.lines:total: 4
@@ -98,6 +107,7 @@
 	Region type    : function
 	Offsets        : 588-646
 	Line numbers   : 58-62
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 	std.code.lines:code: 5
 	std.code.lines:total: 5
@@ -109,6 +119,7 @@
 	Region type    : function
 	Offsets        : 649-808
 	Line numbers   : 64-72
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 	std.suppress:count: 1
 	std.suppress:list: [std.code.complexity:cyclomatic]

+ 11 - 0
mainline/tests/general/test_basic/test_workflow_view_second_per_file_txt_new_stdout.gold.txt

@@ -3,6 +3,7 @@
 	Region type    : global
 	Offsets        : 0-836
 	Line numbers   : 1-78
+	Modified       : False
 	std.code.lines:code: 0 [+0]
 	std.code.lines:total: 0 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -13,6 +14,7 @@
 	Region type    : namespace
 	Offsets        : 2-835
 	Line numbers   : 3-77
+	Modified       : True
 	std.code.lines:code: 4 [+0]
 	std.code.lines:total: 7 [+1]
 	std.code.lines:preprocessor: 2 [+1]
@@ -23,6 +25,7 @@
 	Region type    : class
 	Offsets        : 111-831
 	Line numbers   : 10-75
+	Modified       : True
 	std.code.lines:code: 4 [+0]
 	std.code.lines:total: 4 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -33,6 +36,7 @@
 	Region type    : function
 	Offsets        : 123-269
 	Line numbers   : 13-24
+	Modified       : False
 	std.code.complexity:cyclomatic: 3 [+0]
 	std.code.lines:code: 11 [+0]
 	std.code.lines:total: 12 [+0]
@@ -44,6 +48,7 @@
 	Region type    : function
 	Offsets        : 272-455
 	Line numbers   : 26-42
+	Modified       : False
 	std.code.complexity:cyclomatic: 1 [+0]
 	std.code.lines:code: 5 [+0]
 	std.code.lines:total: 5 [+0]
@@ -55,6 +60,7 @@
 	Region type    : class
 	Offsets        : 301-441
 	Line numbers   : 28-40
+	Modified       : False
 	std.code.lines:code: 3 [+0]
 	std.code.lines:total: 3 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -65,6 +71,7 @@
 	Region type    : function
 	Offsets        : 322-437
 	Line numbers   : 30-39
+	Modified       : True
 	std.code.complexity:cyclomatic: 2 [+1]
 	std.code.lines:code: 8 [+1]
 	std.code.lines:total: 9 [+1]
@@ -76,6 +83,7 @@
 	Region type    : function
 	Offsets        : 458-549
 	Line numbers   : 44-51
+	Modified       : True
 	std.code.complexity:cyclomatic: 1 [+0]
 	std.code.lines:code: 7 [+0]
 	std.code.lines:total: 7 [+0]
@@ -87,6 +95,7 @@
 	Region type    : function
 	Offsets        : 552-585
 	Line numbers   : 53-56
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 	std.code.lines:code: 3
 	std.code.lines:total: 4
@@ -98,6 +107,7 @@
 	Region type    : function
 	Offsets        : 588-646
 	Line numbers   : 58-62
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 	std.code.lines:code: 5
 	std.code.lines:total: 5
@@ -109,6 +119,7 @@
 	Region type    : function
 	Offsets        : 649-808
 	Line numbers   : 64-72
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 	std.suppress:count: 1
 	std.suppress:list: [std.code.complexity:cyclomatic]

+ 11 - 0
mainline/tests/general/test_basic/test_workflow_view_second_per_file_txt_touched_stdout.gold.txt

@@ -3,6 +3,7 @@
 	Region type    : global
 	Offsets        : 0-836
 	Line numbers   : 1-78
+	Modified       : False
 	std.code.lines:code: 0 [+0]
 	std.code.lines:total: 0 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -13,6 +14,7 @@
 	Region type    : namespace
 	Offsets        : 2-835
 	Line numbers   : 3-77
+	Modified       : True
 	std.code.lines:code: 4 [+0]
 	std.code.lines:total: 7 [+1]
 	std.code.lines:preprocessor: 2 [+1]
@@ -23,6 +25,7 @@
 	Region type    : class
 	Offsets        : 111-831
 	Line numbers   : 10-75
+	Modified       : True
 	std.code.lines:code: 4 [+0]
 	std.code.lines:total: 4 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -33,6 +36,7 @@
 	Region type    : function
 	Offsets        : 123-269
 	Line numbers   : 13-24
+	Modified       : False
 	std.code.complexity:cyclomatic: 3 [+0]
 	std.code.lines:code: 11 [+0]
 	std.code.lines:total: 12 [+0]
@@ -44,6 +48,7 @@
 	Region type    : function
 	Offsets        : 272-455
 	Line numbers   : 26-42
+	Modified       : False
 	std.code.complexity:cyclomatic: 1 [+0]
 	std.code.lines:code: 5 [+0]
 	std.code.lines:total: 5 [+0]
@@ -55,6 +60,7 @@
 	Region type    : class
 	Offsets        : 301-441
 	Line numbers   : 28-40
+	Modified       : False
 	std.code.lines:code: 3 [+0]
 	std.code.lines:total: 3 [+0]
 	std.code.lines:preprocessor: 0 [+0]
@@ -65,6 +71,7 @@
 	Region type    : function
 	Offsets        : 322-437
 	Line numbers   : 30-39
+	Modified       : True
 	std.code.complexity:cyclomatic: 2 [+1]
 	std.code.lines:code: 8 [+1]
 	std.code.lines:total: 9 [+1]
@@ -76,6 +83,7 @@
 	Region type    : function
 	Offsets        : 458-549
 	Line numbers   : 44-51
+	Modified       : True
 	std.code.complexity:cyclomatic: 1 [+0]
 	std.code.lines:code: 7 [+0]
 	std.code.lines:total: 7 [+0]
@@ -87,6 +95,7 @@
 	Region type    : function
 	Offsets        : 552-585
 	Line numbers   : 53-56
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 	std.code.lines:code: 3
 	std.code.lines:total: 4
@@ -98,6 +107,7 @@
 	Region type    : function
 	Offsets        : 588-646
 	Line numbers   : 58-62
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 	std.code.lines:code: 5
 	std.code.lines:total: 5
@@ -109,6 +119,7 @@
 	Region type    : function
 	Offsets        : 649-808
 	Line numbers   : 64-72
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 	std.suppress:count: 1
 	std.suppress:list: [std.code.complexity:cyclomatic]

+ 107 - 0
mainline/tests/general/test_std_code_cpp/test_parser_view_files_stdout.gold.txt

@@ -3,24 +3,28 @@
 	Region type    : global
 	Offsets        : 0-163
 	Line numbers   : 1-20
+	Modified       : None
 
 ./function_ends_on_class.cpp:2: info: Metrics per 'my_namespace' region
 	Region name    : my_namespace
 	Region type    : namespace
 	Offsets        : 1-162
 	Line numbers   : 2-19
+	Modified       : None
 
 ./function_ends_on_class.cpp:4: info: Metrics per 'my_class' region
 	Region name    : my_class
 	Region type    : class
 	Offsets        : 27-158
 	Line numbers   : 4-17
+	Modified       : None
 
 ./function_ends_on_class.cpp:5: info: Metrics per 'function_end_on_class' region
 	Region name    : function_end_on_class
 	Region type    : function
 	Offsets        : 45-79
 	Line numbers   : 5-8
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./function_ends_on_class.cpp:9: info: Metrics per 'function_end_on_struct' region
@@ -28,6 +32,7 @@
 	Region type    : function
 	Offsets        : 81-116
 	Line numbers   : 9-12
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./function_ends_on_class.cpp:13: info: Metrics per 'function_end_on_namespace' region
@@ -35,6 +40,7 @@
 	Region type    : function
 	Offsets        : 118-156
 	Line numbers   : 13-16
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./function_ends_on_class.cpp:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric
@@ -51,18 +57,21 @@
 	Region type    : global
 	Offsets        : 0-2068
 	Line numbers   : 1-86
+	Modified       : None
 
 ./operator_test.hpp:2: info: Metrics per '__noname__' region
 	Region name    : __noname__
 	Region type    : namespace
 	Offsets        : 1-1146
 	Line numbers   : 2-32
+	Modified       : None
 
 ./operator_test.hpp:6: info: Metrics per 'policy_mcr' region
 	Region name    : policy_mcr
 	Region type    : function
 	Offsets        : 13-1118
 	Line numbers   : 3-29
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 
 ./operator_test.hpp:31: info: Metrics per 'function_after' region
@@ -70,6 +79,7 @@
 	Region type    : function
 	Offsets        : 1126-1144
 	Line numbers   : 31-31
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:35: info: Metrics per 'ALL_operators' region
@@ -77,12 +87,14 @@
 	Region type    : class
 	Offsets        : 1149-2066
 	Line numbers   : 35-85
+	Modified       : None
 
 ./operator_test.hpp:36: info: Metrics per 'operator int' region
 	Region name    : operator int
 	Region type    : function
 	Offsets        : 1172-1190
 	Line numbers   : 36-36
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:37: info: Metrics per 'operator new' region
@@ -90,6 +102,7 @@
 	Region type    : function
 	Offsets        : 1192-1210
 	Line numbers   : 37-37
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:38: info: Metrics per 'operator delete' region
@@ -97,6 +110,7 @@
 	Region type    : function
 	Offsets        : 1212-1233
 	Line numbers   : 38-38
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:39: info: Metrics per 'operator new[ ]' region
@@ -104,6 +118,7 @@
 	Region type    : function
 	Offsets        : 1235-1256
 	Line numbers   : 39-39
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:40: info: Metrics per 'operator delete []' region
@@ -111,6 +126,7 @@
 	Region type    : function
 	Offsets        : 1258-1282
 	Line numbers   : 40-40
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:41: info: Metrics per 'operator+' region
@@ -118,6 +134,7 @@
 	Region type    : function
 	Offsets        : 1284-1299
 	Line numbers   : 41-41
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:42: info: Metrics per 'operator -' region
@@ -125,6 +142,7 @@
 	Region type    : function
 	Offsets        : 1301-1317
 	Line numbers   : 42-42
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:43: info: Metrics per 'operator *' region
@@ -132,6 +150,7 @@
 	Region type    : function
 	Offsets        : 1319-1335
 	Line numbers   : 43-43
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:44: info: Metrics per 'operator /' region
@@ -139,6 +158,7 @@
 	Region type    : function
 	Offsets        : 1337-1353
 	Line numbers   : 44-44
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:45: info: Metrics per 'operator=' region
@@ -146,6 +166,7 @@
 	Region type    : function
 	Offsets        : 1355-1370
 	Line numbers   : 45-45
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:46: info: Metrics per 'operator<' region
@@ -153,6 +174,7 @@
 	Region type    : function
 	Offsets        : 1372-1387
 	Line numbers   : 46-46
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:47: info: Metrics per 'operator >' region
@@ -160,6 +182,7 @@
 	Region type    : function
 	Offsets        : 1389-1405
 	Line numbers   : 47-47
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:48: info: Metrics per 'operator+=' region
@@ -167,6 +190,7 @@
 	Region type    : function
 	Offsets        : 1407-1423
 	Line numbers   : 48-48
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:49: info: Metrics per 'operator -=' region
@@ -174,6 +198,7 @@
 	Region type    : function
 	Offsets        : 1425-1442
 	Line numbers   : 49-49
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:50: info: Metrics per 'operator*=' region
@@ -181,6 +206,7 @@
 	Region type    : function
 	Offsets        : 1444-1460
 	Line numbers   : 50-50
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:51: info: Metrics per 'operator/=' region
@@ -188,6 +214,7 @@
 	Region type    : function
 	Offsets        : 1462-1478
 	Line numbers   : 51-51
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:52: info: Metrics per 'operator<<' region
@@ -195,6 +222,7 @@
 	Region type    : function
 	Offsets        : 1480-1495
 	Line numbers   : 52-52
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:53: info: Metrics per 'operator >>' region
@@ -202,6 +230,7 @@
 	Region type    : function
 	Offsets        : 1497-1514
 	Line numbers   : 53-53
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:54: info: Metrics per 'operator <<=' region
@@ -209,6 +238,7 @@
 	Region type    : function
 	Offsets        : 1516-1533
 	Line numbers   : 54-54
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:55: info: Metrics per 'operator>>=' region
@@ -216,6 +246,7 @@
 	Region type    : function
 	Offsets        : 1535-1551
 	Line numbers   : 55-55
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:56: info: Metrics per 'operator==' region
@@ -223,6 +254,7 @@
 	Region type    : function
 	Offsets        : 1553-1568
 	Line numbers   : 56-56
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:57: info: Metrics per 'operator!=' region
@@ -230,6 +262,7 @@
 	Region type    : function
 	Offsets        : 1570-1585
 	Line numbers   : 57-57
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:58: info: Metrics per 'operator<=' region
@@ -237,6 +270,7 @@
 	Region type    : function
 	Offsets        : 1587-1602
 	Line numbers   : 58-58
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:59: info: Metrics per 'operator >=' region
@@ -244,6 +278,7 @@
 	Region type    : function
 	Offsets        : 1604-1621
 	Line numbers   : 59-59
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:60: info: Metrics per 'operator ++' region
@@ -251,6 +286,7 @@
 	Region type    : function
 	Offsets        : 1623-1640
 	Line numbers   : 60-60
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:61: info: Metrics per 'operator--' region
@@ -258,6 +294,7 @@
 	Region type    : function
 	Offsets        : 1642-1657
 	Line numbers   : 61-61
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:62: info: Metrics per 'operator%' region
@@ -265,6 +302,7 @@
 	Region type    : function
 	Offsets        : 1659-1673
 	Line numbers   : 62-62
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:63: info: Metrics per 'operator &' region
@@ -272,6 +310,7 @@
 	Region type    : function
 	Offsets        : 1675-1690
 	Line numbers   : 63-63
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:64: info: Metrics per 'operator ^' region
@@ -279,6 +318,7 @@
 	Region type    : function
 	Offsets        : 1692-1707
 	Line numbers   : 64-64
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:65: info: Metrics per 'operator !' region
@@ -286,6 +326,7 @@
 	Region type    : function
 	Offsets        : 1709-1724
 	Line numbers   : 65-65
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:66: info: Metrics per 'operator|' region
@@ -293,6 +334,7 @@
 	Region type    : function
 	Offsets        : 1726-1740
 	Line numbers   : 66-66
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:67: info: Metrics per 'operator~' region
@@ -300,6 +342,7 @@
 	Region type    : function
 	Offsets        : 1742-1756
 	Line numbers   : 67-67
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:68: info: Metrics per 'operator &=' region
@@ -307,6 +350,7 @@
 	Region type    : function
 	Offsets        : 1758-1774
 	Line numbers   : 68-68
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:69: info: Metrics per 'operator ^=' region
@@ -314,6 +358,7 @@
 	Region type    : function
 	Offsets        : 1776-1792
 	Line numbers   : 69-69
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:70: info: Metrics per 'operator |=' region
@@ -321,6 +366,7 @@
 	Region type    : function
 	Offsets        : 1794-1810
 	Line numbers   : 70-70
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:71: info: Metrics per 'operator &&' region
@@ -328,6 +374,7 @@
 	Region type    : function
 	Offsets        : 1812-1828
 	Line numbers   : 71-71
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 
 ./operator_test.hpp:72: info: Metrics per 'operator ||' region
@@ -335,6 +382,7 @@
 	Region type    : function
 	Offsets        : 1830-1848
 	Line numbers   : 72-72
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 
 ./operator_test.hpp:73: info: Metrics per 'operator %=' region
@@ -342,6 +390,7 @@
 	Region type    : function
 	Offsets        : 1850-1866
 	Line numbers   : 73-73
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:74: info: Metrics per 'operator []' region
@@ -349,6 +398,7 @@
 	Region type    : function
 	Offsets        : 1868-1886
 	Line numbers   : 74-74
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:75: info: Metrics per 'operator  ()' region
@@ -356,6 +406,7 @@
 	Region type    : function
 	Offsets        : 1888-1907
 	Line numbers   : 75-75
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:76: info: Metrics per 'operator()' region
@@ -363,6 +414,7 @@
 	Region type    : function
 	Offsets        : 1909-1925
 	Line numbers   : 76-76
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:77: info: Metrics per 'operator()' region
@@ -370,6 +422,7 @@
 	Region type    : function
 	Offsets        : 1927-1941
 	Line numbers   : 77-77
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:78: info: Metrics per 'operator()' region
@@ -377,6 +430,7 @@
 	Region type    : function
 	Offsets        : 1943-1960
 	Line numbers   : 78-78
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:79: info: Metrics per 'operator ()' region
@@ -384,6 +438,7 @@
 	Region type    : function
 	Offsets        : 1962-1978
 	Line numbers   : 79-79
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:80: info: Metrics per 'operator ()' region
@@ -391,6 +446,7 @@
 	Region type    : function
 	Offsets        : 1980-1995
 	Line numbers   : 80-80
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:81: info: Metrics per 'operator ,' region
@@ -398,6 +454,7 @@
 	Region type    : function
 	Offsets        : 1997-2012
 	Line numbers   : 81-81
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:82: info: Metrics per 'operator ->*' region
@@ -405,6 +462,7 @@
 	Region type    : function
 	Offsets        : 2014-2031
 	Line numbers   : 82-82
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:83: info: Metrics per 'operator->' region
@@ -412,6 +470,7 @@
 	Region type    : function
 	Offsets        : 2033-2048
 	Line numbers   : 83-83
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:84: info: Metrics per 'operator.' region
@@ -419,6 +478,7 @@
 	Region type    : function
 	Offsets        : 2050-2064
 	Line numbers   : 84-84
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./operator_test.hpp:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric
@@ -437,12 +497,14 @@
 	Region type    : global
 	Offsets        : 0-8296
 	Line numbers   : 1-359
+	Modified       : None
 
 ./test.c:12: info: Metrics per 'function_start' region
 	Region name    : function_start
 	Region type    : function
 	Offsets        : 88-159
 	Line numbers   : 12-14
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:108: info: Metrics per 'boost' region
@@ -450,18 +512,21 @@
 	Region type    : namespace
 	Offsets        : 2048-5407
 	Line numbers   : 108-266
+	Modified       : None
 
 ./test.c:125: info: Metrics per 'tessss' region
 	Region name    : tessss
 	Region type    : class
 	Offsets        : 2516-2551
 	Line numbers   : 125-125
+	Modified       : None
 
 ./test.c:125: info: Metrics per 'funct' region
 	Region name    : funct
 	Region type    : function
 	Offsets        : 2541-2550
 	Line numbers   : 125-125
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:134: info: Metrics per 'mycontainer' region
@@ -469,12 +534,14 @@
 	Region type    : class
 	Offsets        : 2624-2785
 	Line numbers   : 132-139
+	Modified       : None
 
 ./test.c:137: info: Metrics per 'mycontainer' region
 	Region name    : mycontainer
 	Region type    : function
 	Offsets        : 2699-2745
 	Line numbers   : 136-137
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:138: info: Metrics per 'increase' region
@@ -482,6 +549,7 @@
 	Region type    : function
 	Offsets        : 2750-2783
 	Line numbers   : 138-138
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:143: info: Metrics per 'mycontainer' region
@@ -489,12 +557,14 @@
 	Region type    : class
 	Offsets        : 2788-3054
 	Line numbers   : 141-153
+	Modified       : None
 
 ./test.c:146: info: Metrics per 'mycontainer' region
 	Region name    : mycontainer
 	Region type    : function
 	Offsets        : 2881-2930
 	Line numbers   : 145-146
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:147: info: Metrics per 'uppercase' region
@@ -502,6 +572,7 @@
 	Region type    : function
 	Offsets        : 2935-3052
 	Line numbers   : 147-152
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 
 ./test.c:156: info: Metrics per 'main' region
@@ -509,6 +580,7 @@
 	Region type    : function
 	Offsets        : 3057-3225
 	Line numbers   : 155-162
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:164: info: Metrics per 'scoped_ptr' region
@@ -516,12 +588,14 @@
 	Region type    : struct
 	Offsets        : 3227-5142
 	Line numbers   : 164-252
+	Modified       : None
 
 ./test.c:185: info: Metrics per 'scoped_ptr' region
 	Region name    : scoped_ptr
 	Region type    : function
 	Offsets        : 3619-3790
 	Line numbers   : 185-190
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:192: info: Metrics per 'scoped_ptr' region
@@ -529,6 +603,7 @@
 	Region type    : function
 	Offsets        : 3796-3988
 	Line numbers   : 192-198
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:202: info: Metrics per 'scoped_ptr' region
@@ -536,6 +611,7 @@
 	Region type    : function
 	Offsets        : 4021-4206
 	Line numbers   : 202-207
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:210: info: Metrics per '~scoped_ptr' region
@@ -543,6 +619,7 @@
 	Region type    : function
 	Offsets        : 4208-4389
 	Line numbers   : 209-216
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:216: info: Metrics per 'reset' region
@@ -550,6 +627,7 @@
 	Region type    : function
 	Offsets        : 4389-4543
 	Line numbers   : 216-220
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 
 ./test.c:220: info: Metrics per 'operator*' region
@@ -557,6 +635,7 @@
 	Region type    : function
 	Offsets        : 4543-4645
 	Line numbers   : 220-224
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:226: info: Metrics per 'operator->' region
@@ -564,6 +643,7 @@
 	Region type    : function
 	Offsets        : 4651-4753
 	Line numbers   : 226-230
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:232: info: Metrics per 'operator  float' region
@@ -571,6 +651,7 @@
 	Region type    : function
 	Offsets        : 4759-4866
 	Line numbers   : 232-236
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:238: info: Metrics per 'get' region
@@ -578,6 +659,7 @@
 	Region type    : function
 	Offsets        : 4872-4934
 	Line numbers   : 238-241
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:246: info: Metrics per 'swap' region
@@ -585,6 +667,7 @@
 	Region type    : function
 	Offsets        : 5026-5140
 	Line numbers   : 246-251
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:254: info: Metrics per 'swap' region
@@ -592,6 +675,7 @@
 	Region type    : function
 	Offsets        : 5145-5262
 	Line numbers   : 254-257
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:261: info: Metrics per 'get_pointer' region
@@ -599,6 +683,7 @@
 	Region type    : function
 	Offsets        : 5315-5404
 	Line numbers   : 261-264
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:276: info: Metrics per 'Central' region
@@ -606,12 +691,14 @@
 	Region type    : class
 	Offsets        : 5586-8219
 	Line numbers   : 276-346
+	Modified       : None
 
 ./test.c:277: info: Metrics per 'register' region
 	Region name    : register
 	Region type    : function
 	Offsets        : 5613-6269
 	Line numbers   : 277-294
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:296: info: Metrics per 'save' region
@@ -619,6 +706,7 @@
 	Region type    : function
 	Offsets        : 6275-7372
 	Line numbers   : 296-321
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 
 ./test.c:323: info: Metrics per 'show' region
@@ -626,6 +714,7 @@
 	Region type    : function
 	Offsets        : 7378-7821
 	Line numbers   : 323-330
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:332: info: Metrics per 'main' region
@@ -633,6 +722,7 @@
 	Region type    : function
 	Offsets        : 7827-8216
 	Line numbers   : 332-344
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 
 ./test.c:349: info: Metrics per 'f1' region
@@ -640,6 +730,7 @@
 	Region type    : function
 	Offsets        : 8222-8228
 	Line numbers   : 349-349
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test.c:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric
@@ -658,18 +749,21 @@
 	Region type    : global
 	Offsets        : 0-628
 	Line numbers   : 1-53
+	Modified       : None
 
 ./test2.cpp:5: info: Metrics per 'A' region
 	Region name    : A
 	Region type    : class
 	Offsets        : 39-170
 	Line numbers   : 5-19
+	Modified       : None
 
 ./test2.cpp:7: info: Metrics per 'A' region
 	Region name    : A
 	Region type    : function
 	Offsets        : 50-87
 	Line numbers   : 7-10
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 
 ./test2.cpp:10: info: Metrics per 'method' region
@@ -677,6 +771,7 @@
 	Region type    : function
 	Offsets        : 87-117
 	Line numbers   : 10-13
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test2.cpp:13: info: Metrics per 'operator ++' region
@@ -684,6 +779,7 @@
 	Region type    : function
 	Offsets        : 117-153
 	Line numbers   : 13-16
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test2.cpp:22: info: Metrics per 'aaa' region
@@ -691,12 +787,14 @@
 	Region type    : namespace
 	Offsets        : 173-350
 	Line numbers   : 21-39
+	Modified       : None
 
 ./test2.cpp:23: info: Metrics per 'main' region
 	Region name    : main
 	Region type    : function
 	Offsets        : 192-348
 	Line numbers   : 23-38
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 
 ./test2.cpp:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric
@@ -715,18 +813,21 @@
 	Region type    : global
 	Offsets        : 0-2797
 	Line numbers   : 1-110
+	Modified       : None
 
 ./test3.cpp:37: info: Metrics per 'Tester' region
 	Region name    : Tester
 	Region type    : class
 	Offsets        : 1672-2192
 	Line numbers   : 37-68
+	Modified       : None
 
 ./test3.cpp:39: info: Metrics per 'doColor' region
 	Region name    : doColor
 	Region type    : function
 	Offsets        : 1703-1871
 	Line numbers   : 38-48
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 
 ./test3.cpp:53: info: Metrics per 'doFont' region
@@ -734,6 +835,7 @@
 	Region type    : function
 	Offsets        : 1923-2189
 	Line numbers   : 53-66
+	Modified       : None
 	std.code.complexity:cyclomatic: 1
 
 ./test3.cpp:72: info: Metrics per 'doFont222' region
@@ -741,6 +843,7 @@
 	Region type    : function
 	Offsets        : 2194-2561
 	Line numbers   : 68-87
+	Modified       : None
 	std.code.complexity:cyclomatic: 2
 
 ./test3.cpp:90: info: Metrics per 'not_closed' region
@@ -748,12 +851,14 @@
 	Region type    : namespace
 	Offsets        : 2566-2797
 	Line numbers   : 110-130
+	Modified       : None
 
 ./test3.cpp:91: info: Metrics per 'main' region
 	Region name    : main
 	Region type    : function
 	Offsets        : 2589-2753
 	Line numbers   : 110-120
+	Modified       : None
 	std.code.complexity:cyclomatic: 0
 
 ./test3.cpp:102: info: Metrics per '__noname__' region
@@ -761,12 +866,14 @@
 	Region type    : namespace
 	Offsets        : 2755-2793
 	Line numbers   : 122-126
+	Modified       : None
 
 ./test3.cpp:103: info: Metrics per '__noname__' region
 	Region name    : __noname__
 	Region type    : struct
 	Offsets        : 2768-2787
 	Line numbers   : 123-125
+	Modified       : None
 
 ./test3.cpp:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric
 	Average        : 1.0

+ 55 - 0
mainline/tests/general/test_std_code_cs/test_parser_view_files_stdout.gold.txt

@@ -3,24 +3,28 @@
 	Region type    : global
 	Offsets        : 0-9141
 	Line numbers   : 1-448
+	Modified       : None
 
 .   ./File.cs:21: info: Metrics per 'Microsoft.VisualBasic' region
     	Region name    : Microsoft.VisualBasic
     	Region type    : namespace
     	Offsets        : 855-9104
     	Line numbers   : 21-447
+    	Modified       : None
 
 .   .   ./File.cs:30: info: Metrics per 'File' region
         	Region name    : File
         	Region type    : class
         	Offsets        : 1012-9037
         	Line numbers   : 30-437
+        	Modified       : None
 
 .   .   .   ./File.cs:74: info: Metrics per 'get' region
             	Region name    : get
             	Region type    : function
             	Offsets        : 1961-2222
             	Line numbers   : 74-89
+            	Modified       : None
             	std.code.complexity:cyclomatic: 3
 
 .   .   .   ./File.cs:95: info: Metrics per 'get' region
@@ -28,6 +32,7 @@
             	Region type    : function
             	Offsets        : 2295-2781
             	Line numbers   : 95-114
+            	Modified       : None
             	std.code.complexity:cyclomatic: 2
 
 .   .   .   ./File.cs:120: info: Metrics per 'get' region
@@ -35,6 +40,7 @@
             	Region type    : function
             	Offsets        : 2888-3022
             	Line numbers   : 120-128
+            	Modified       : None
             	std.code.complexity:cyclomatic: 1
 
 .   .   .   ./File.cs:134: info: Metrics per 'get' region
@@ -42,6 +48,7 @@
             	Region type    : function
             	Offsets        : 3129-3263
             	Line numbers   : 134-142
+            	Modified       : None
             	std.code.complexity:cyclomatic: 1
 
 .   .   .   ./File.cs:148: info: Metrics per 'get' region
@@ -49,6 +56,7 @@
             	Region type    : function
             	Offsets        : 3355-3489
             	Line numbers   : 148-156
+            	Modified       : None
             	std.code.complexity:cyclomatic: 1
 
 .   .   .   ./File.cs:160: info: Metrics per 'Close' region
@@ -56,6 +64,7 @@
             	Region type    : function
             	Offsets        : 3497-4076
             	Line numbers   : 159-187
+            	Modified       : None
             	std.code.complexity:cyclomatic: 4
 
 .   .   .   ./File.cs:190: info: Metrics per 'SetRecord' region
@@ -63,6 +72,7 @@
             	Region type    : function
             	Offsets        : 4079-4794
             	Line numbers   : 189-226
+            	Modified       : None
             	std.code.complexity:cyclomatic: 6
 
 .   .   .   ./File.cs:229: info: Metrics per 'FileTable' region
@@ -70,12 +80,14 @@
             	Region type    : class
             	Offsets        : 4797-5103
             	Line numbers   : 228-242
+            	Modified       : None
 
 .   .   .   .   ./File.cs:235: info: Metrics per 'FileTable' region
                 	Region name    : FileTable
                 	Region type    : function
                 	Offsets        : 4943-5099
                 	Line numbers   : 235-240
+                	Modified       : None
                 	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./File.cs:245: info: Metrics per 'GetFile' region
@@ -83,6 +95,7 @@
             	Region type    : function
             	Offsets        : 5126-5822
             	Line numbers   : 244-274
+            	Modified       : None
             	std.code.complexity:cyclomatic: 5
 
 .   .   .   ./File.cs:277: info: Metrics per 'GetFile' region
@@ -90,6 +103,7 @@
             	Region type    : function
             	Offsets        : 5825-6140
             	Line numbers   : 276-285
+            	Modified       : None
             	std.code.complexity:cyclomatic: 1
 
 .   .   .   ./File.cs:288: info: Metrics per 'AllocateFile' region
@@ -97,6 +111,7 @@
             	Region type    : function
             	Offsets        : 6143-7049
             	Line numbers   : 287-324
+            	Modified       : None
             	std.code.complexity:cyclomatic: 5
 
 .   .   .   ./File.cs:327: info: Metrics per 'FindFreeFile' region
@@ -104,6 +119,7 @@
             	Region type    : function
             	Offsets        : 7052-7735
             	Line numbers   : 326-358
+            	Modified       : None
             	std.code.complexity:cyclomatic: 5
 
 .   .   .   ./File.cs:361: info: Metrics per 'CloseAll' region
@@ -111,6 +127,7 @@
             	Region type    : function
             	Offsets        : 7738-8342
             	Line numbers   : 360-387
+            	Modified       : None
             	std.code.complexity:cyclomatic: 4
 
 .   .   .   ./File.cs:391: info: Metrics per 'Write' region
@@ -118,6 +135,7 @@
             	Region type    : function
             	Offsets        : 8345-8437
             	Line numbers   : 389-394
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./File.cs:398: info: Metrics per 'WriteLine' region
@@ -125,6 +143,7 @@
             	Region type    : function
             	Offsets        : 8440-8541
             	Line numbers   : 396-401
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./File.cs:405: info: Metrics per 'Tab' region
@@ -132,6 +151,7 @@
             	Region type    : function
             	Offsets        : 8544-8631
             	Line numbers   : 403-408
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./File.cs:412: info: Metrics per 'Space' region
@@ -139,6 +159,7 @@
             	Region type    : function
             	Offsets        : 8634-8726
             	Line numbers   : 410-415
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./File.cs:419: info: Metrics per 'Lock' region
@@ -146,6 +167,7 @@
             	Region type    : function
             	Offsets        : 8729-8839
             	Line numbers   : 417-422
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./File.cs:426: info: Metrics per 'Unlock' region
@@ -153,6 +175,7 @@
             	Region type    : function
             	Offsets        : 8842-9034
             	Line numbers   : 424-435
+            	Modified       : None
             	std.code.complexity:cyclomatic: 1
 
 ./File.cs:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric
@@ -175,30 +198,35 @@
 	Region type    : global
 	Offsets        : 0-3134
 	Line numbers   : 1-106
+	Modified       : None
 
 .   ./Generics.cs:22: info: Metrics per 'Generics' region
     	Region name    : Generics
     	Region type    : class
     	Offsets        : 1182-3133
     	Line numbers   : 22-105
+    	Modified       : None
 
 .   .   ./Generics.cs:24: info: Metrics per 'MyArray' region
         	Region name    : MyArray
         	Region type    : class
         	Offsets        : 1214-1664
         	Line numbers   : 24-57
+        	Modified       : None
 
 .   .   .   ./Generics.cs:26: info: Metrics per 'NestedClass' region
             	Region name    : NestedClass
             	Region type    : class
             	Offsets        : 1243-1316
             	Line numbers   : 26-30
+            	Modified       : None
 
 .   .   .   ./Generics.cs:40: info: Metrics per 'MyArray' region
             	Region name    : MyArray
             	Region type    : function
             	Offsets        : 1391-1458
             	Line numbers   : 40-43
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./Generics.cs:45: info: Metrics per 'Size' region
@@ -206,6 +234,7 @@
             	Region type    : function
             	Offsets        : 1464-1546
             	Line numbers   : 45-48
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./Generics.cs:50: info: Metrics per 'Grow' region
@@ -213,6 +242,7 @@
             	Region type    : function
             	Offsets        : 1552-1661
             	Line numbers   : 50-56
+            	Modified       : None
             	std.code.complexity:cyclomatic: 1
 
 .   .   ./Generics.cs:59: info: Metrics per 'IInterface' region
@@ -220,18 +250,21 @@
         	Region type    : interface
         	Offsets        : 1668-1775
         	Line numbers   : 59-63
+        	Modified       : None
 
 .   .   ./Generics.cs:65: info: Metrics per 'Base' region
         	Region name    : Base
         	Region type    : class
         	Offsets        : 1779-2084
         	Line numbers   : 65-74
+        	Modified       : None
 
 .   .   .   ./Generics.cs:71: info: Metrics per 'Generics.IInterface.Method2' region
             	Region name    : Generics.IInterface.Method2
             	Region type    : function
             	Offsets        : 1960-2081
             	Line numbers   : 70-73
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   ./Generics.cs:76: info: Metrics per 'Derived' region
@@ -239,12 +272,14 @@
         	Region type    : class
         	Offsets        : 2088-2245
         	Line numbers   : 76-82
+        	Modified       : None
 
 .   .   .   ./Generics.cs:79: info: Metrics per 'Method1' region
             	Region name    : Method1
             	Region type    : function
             	Offsets        : 2130-2242
             	Line numbers   : 78-81
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   ./Generics.cs:92: info: Metrics per 'MethodWithConstraint' region
@@ -252,6 +287,7 @@
         	Region type    : function
         	Offsets        : 2698-2798
         	Line numbers   : 92-94
+        	Modified       : None
         	std.code.complexity:cyclomatic: 0
 
 .   .   ./Generics.cs:96: info: Metrics per 'MethodWithStructConstraint' region
@@ -259,6 +295,7 @@
         	Region type    : function
         	Offsets        : 2802-2875
         	Line numbers   : 96-98
+        	Modified       : None
         	std.code.complexity:cyclomatic: 0
 
 .   .   ./Generics.cs:100: info: Metrics per 'Dictionary' region
@@ -266,6 +303,7 @@
         	Region type    : function
         	Offsets        : 2879-3131
         	Line numbers   : 100-104
+        	Modified       : None
         	std.code.complexity:cyclomatic: 0
 
 ./Generics.cs:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric
@@ -283,36 +321,42 @@
 	Region type    : global
 	Offsets        : 0-6584
 	Line numbers   : 1-219
+	Modified       : None
 
 .   ./interface.cs:22: info: Metrics per 'System.Runtime.Serialization' region
     	Region name    : System.Runtime.Serialization
     	Region type    : namespace
     	Offsets        : 918-1139
     	Line numbers   : 22-37
+    	Modified       : None
 
 .   .   ./interface.cs:30: info: Metrics per 'IDeserializationCallback' region
         	Region name    : IDeserializationCallback
         	Region type    : interface
         	Offsets        : 960-1097
         	Line numbers   : 25-35
+        	Modified       : None
 
 .   ./interface.cs:61: info: Metrics per 'System.Globalization' region
     	Region name    : System.Globalization
     	Region type    : namespace
     	Offsets        : 2040-6548
     	Line numbers   : 61-218
+    	Modified       : None
 
 .   .   ./interface.cs:69: info: Metrics per 'TextInfo' region
         	Region name    : TextInfo
         	Region type    : class
         	Offsets        : 2183-6526
         	Line numbers   : 69-216
+        	Modified       : None
 
 .   .   .   ./interface.cs:80: info: Metrics per 'TextInfo' region
             	Region name    : TextInfo
             	Region type    : function
             	Offsets        : 2288-2687
             	Line numbers   : 75-83
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:88: info: Metrics per 'get' region
@@ -320,6 +364,7 @@
             	Region type    : function
             	Offsets        : 2802-2940
             	Line numbers   : 88-92
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:98: info: Metrics per 'get' region
@@ -327,6 +372,7 @@
             	Region type    : function
             	Offsets        : 3073-3209
             	Line numbers   : 98-102
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:108: info: Metrics per 'get' region
@@ -334,6 +380,7 @@
             	Region type    : function
             	Offsets        : 3336-3475
             	Line numbers   : 108-112
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:118: info: Metrics per 'get' region
@@ -341,6 +388,7 @@
             	Region type    : function
             	Offsets        : 3602-3739
             	Line numbers   : 118-122
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:128: info: Metrics per 'get' region
@@ -348,6 +396,7 @@
             	Region type    : function
             	Offsets        : 3863-3934
             	Line numbers   : 128-131
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:135: info: Metrics per 'Equals' region
@@ -355,6 +404,7 @@
             	Region type    : function
             	Offsets        : 3954-4348
             	Line numbers   : 134-146
+            	Modified       : None
             	std.code.complexity:cyclomatic: 1
 
 .   .   .   ./interface.cs:149: info: Metrics per 'GetHashCode' region
@@ -362,6 +412,7 @@
             	Region type    : function
             	Offsets        : 4354-4489
             	Line numbers   : 148-152
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:169: info: Metrics per 'ToTitleCase' region
@@ -369,6 +420,7 @@
             	Region type    : function
             	Offsets        : 5003-5940
             	Line numbers   : 168-195
+            	Modified       : None
             	std.code.complexity:cyclomatic: 4
 
 .   .   .   ./interface.cs:198: info: Metrics per 'I.Deserialization.Callback.OnDeserialization' region
@@ -376,6 +428,7 @@
             	Region type    : function
             	Offsets        : 5946-6128
             	Line numbers   : 197-201
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:204: info: Metrics per 'ToString' region
@@ -383,6 +436,7 @@
             	Region type    : function
             	Offsets        : 6134-6296
             	Line numbers   : 203-207
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 .   .   .   ./interface.cs:211: info: Metrics per 'IDeserializationCallback.OnDeserialization' region
@@ -390,6 +444,7 @@
             	Region type    : function
             	Offsets        : 6302-6523
             	Line numbers   : 209-214
+            	Modified       : None
             	std.code.complexity:cyclomatic: 0
 
 ./interface.cs:: info: Overall metrics for 'std.code.complexity:cyclomatic' metric

File diff suppressed because it is too large
+ 130 - 0
mainline/tests/general/test_std_code_java/test_parser_view_files_stdout.gold.txt


+ 131 - 0
mainline/tests/system/test_boost_parts.py

@@ -0,0 +1,131 @@
+#
+#    Metrix++, Copyright 2009-2013, Metrix++ Project
+#    Link: http://metrixplusplus.sourceforge.net
+#    
+#    This file is a part of Metrix++ Tool.
+#    
+#    Metrix++ is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, version 3 of the License.
+#    
+#    Metrix++ is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#    GNU General Public License for more details.
+#    
+#    You should have received a copy of the GNU General Public License
+#    along with Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+
+import unittest
+
+import tests.common
+
+class Test(tests.common.TestCase):
+
+    def test_workflow(self):
+        
+        # first collection
+        runner = tests.common.ToolRunner('collect',
+                                         ['--std.code.complexity.cyclomatic',
+                                          '--std.code.lines.code',
+                                          '--log-level=INFO'],
+                                         check_stderr=[(0, -1)],
+                                         save_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('collect',
+                                         ['--std.code.complexity.cyclomatic',
+                                          '--std.code.lines.code',
+                                          '--log-level=INFO'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second',
+                                         cwd="sources_changed",
+                                         use_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('view',
+                                         ['--log-level=INFO'],
+                                         check_stderr=[(0, -1)])
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('view',
+                                         ['--log-level=INFO', '--scope-mode=all'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second_all',
+                                         use_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('view',
+                                         ['--log-level=INFO', '--scope-mode=touched'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second_touched',
+                                         use_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('view',
+                                         ['--log-level=INFO', '--scope-mode=new'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second_new',
+                                         use_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('view',
+                                         ['--log-level=INFO', '--format=xml'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second_per_file',
+                                         dirs_list=['./interprocess/detail/managed_open_or_create_impl.hpp'],
+                                         use_prev=True)
+
+        runner = tests.common.ToolRunner('limit',
+                                         ['--log-level=INFO',
+                                          '--max-limit=std.code.complexity:cyclomatic:15'],
+                                         check_stderr=[(0, -1)],
+                                         exit_code=9)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('limit',
+                                         ['--log-level=INFO',
+                                          '--max-limit=std.code.complexity:cyclomatic:15',
+                                          '--warn-mode=touched'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second_touched',
+                                         exit_code=6,
+                                         use_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('limit',
+                                         ['--log-level=INFO',
+                                          '--max-limit=std.code.complexity:cyclomatic:15',
+                                          '--warn-mode=trend'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second_trend',
+                                         exit_code=2,
+                                         use_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('limit',
+                                         ['--log-level=INFO',
+                                          '--max-limit=std.code.complexity:cyclomatic:15',
+                                          '--warn-mode=new'],
+                                         check_stderr=[(0, -1)],
+                                         prefix='second_new',
+                                         exit_code=0,
+                                         use_prev=True)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('info',
+                                         ['--log-level=INFO'],
+                                         check_stderr=[(0, -1)],
+                                         exit_code=0)
+        self.assertExec(runner.run())
+
+        runner = tests.common.ToolRunner('export',
+                                         ['--log-level=INFO'],
+                                         check_stderr=[(0, -1)],
+                                         exit_code=0)
+        self.assertExec(runner.run())
+
+if __name__ == '__main__':
+    unittest.main()

+ 468 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/adaptive_pool.hpp

@@ -0,0 +1,468 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
+#define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes adaptive_pool pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+namespace ipcdetail{
+
+template < unsigned int Version
+         , class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         , std::size_t MaxFreeBlocks
+         , unsigned char OverheadPercent
+         >
+class adaptive_pool_base
+   : public node_pool_allocation_impl
+   < adaptive_pool_base
+      < Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
+   , Version
+   , T
+   , SegmentManager
+   >
+{
+   public:
+   typedef typename SegmentManager::void_pointer         void_pointer;
+   typedef SegmentManager                                segment_manager;
+   typedef adaptive_pool_base
+      <Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>   self_t;
+
+   /// @cond
+
+   template <int dummy>
+   struct node_pool
+   {
+      typedef ipcdetail::shared_adaptive_node_pool
+      < SegmentManager, sizeof_value<T>::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type;
+
+      static type *get(void *p)
+      {  return static_cast<type*>(p);  }
+   };
+   /// @endcond
+
+   BOOST_STATIC_ASSERT((Version <=2));
+
+   public:
+   //-------
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<T>::type                         pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const T>::type                   const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::difference_type     difference_type;
+
+   typedef boost::interprocess::version_type<adaptive_pool_base, Version>   version;
+   typedef boost::container::container_detail::transform_multiallocation_chain
+      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+   //!Obtains adaptive_pool_base from
+   //!adaptive_pool_base
+   template<class T2>
+   struct rebind
+   {
+      typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>       other;
+   };
+
+   /// @cond
+   private:
+   //!Not assignable from related adaptive_pool_base
+   template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2>
+   adaptive_pool_base& operator=
+      (const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
+
+   /// @endcond
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   adaptive_pool_base(segment_manager *segment_mngr)
+      : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
+
+   //!Copy constructor from other adaptive_pool_base. Increments the reference
+   //!count of the associated node pool. Never throws
+   adaptive_pool_base(const adaptive_pool_base &other)
+      : mp_node_pool(other.get_node_pool())
+   {
+      node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count();
+   }
+
+   //!Assignment from other adaptive_pool_base
+   adaptive_pool_base& operator=(const adaptive_pool_base &other)
+   {
+      adaptive_pool_base c(other);
+      swap(*this, c);
+      return *this;
+   }
+
+   //!Copy constructor from related adaptive_pool_base. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   adaptive_pool_base
+      (const adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~adaptive_pool_base()
+   {  ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool)));   }
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   void* get_node_pool() const
+   {  return ipcdetail::to_raw_pointer(mp_node_pool);   }
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const
+   {  return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager();  }
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2)
+   {  ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool);  }
+
+   /// @cond
+   private:
+   void_pointer   mp_node_pool;
+   /// @endcond
+};
+
+//!Equality test for same type
+//!of adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
+bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
+                const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
+   {  return alloc1.get_node_pool() == alloc2.get_node_pool(); }
+
+//!Inequality test for same type
+//!of adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
+bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
+                const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
+   {  return alloc1.get_node_pool() != alloc2.get_node_pool(); }
+
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock = 64
+         , std::size_t MaxFreeBlocks = 2
+         , unsigned char OverheadPercent = 5
+         >
+class adaptive_pool_v1
+   :  public adaptive_pool_base
+         < 1
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         , MaxFreeBlocks
+         , OverheadPercent
+         >
+{
+   public:
+   typedef ipcdetail::adaptive_pool_base
+         < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
+   };
+
+   adaptive_pool_v1(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   adaptive_pool_v1
+      (const adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : base_t(other)
+   {}
+};
+
+}  //namespace ipcdetail{
+
+/// @endcond
+
+//!An STL node allocator that uses a segment manager as memory
+//!source. The internal pointer type will of the same type (raw, smart) as
+//!"typename SegmentManager::void_pointer" type. This allows
+//!placing the allocator in shared memory, memory mapped-files, etc...
+//!
+//!This node allocator shares a segregated storage between all instances
+//!of adaptive_pool with equal sizeof(T) placed in the same segment
+//!group. NodesPerBlock is the number of nodes allocated at once when the allocator
+//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
+//!that the adaptive node pool will hold. The rest of the totally free blocks will be
+//!deallocated with the segment manager.
+//!
+//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
+//!(memory usable for nodes / total memory allocated from the segment manager)
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         , std::size_t MaxFreeBlocks
+         , unsigned char OverheadPercent
+         >
+class adaptive_pool
+   /// @cond
+   :  public ipcdetail::adaptive_pool_base
+         < 2
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         , MaxFreeBlocks
+         , OverheadPercent
+         >
+   /// @endcond
+{
+
+   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   typedef ipcdetail::adaptive_pool_base
+         < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
+   public:
+   typedef boost::interprocess::version_type<adaptive_pool, 2>   version;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
+   };
+
+   adaptive_pool(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   adaptive_pool
+      (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : base_t(other)
+   {}
+
+   #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   public:
+   typedef implementation_defined::segment_manager       segment_manager;
+   typedef segment_manager::void_pointer                 void_pointer;
+   typedef implementation_defined::pointer               pointer;
+   typedef implementation_defined::const_pointer         const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::difference_type     difference_type;
+
+   //!Obtains adaptive_pool from
+   //!adaptive_pool
+   template<class T2>
+   struct rebind
+   {
+      typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+   };
+
+   private:
+   //!Not assignable from
+   //!related adaptive_pool
+   template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
+   adaptive_pool& operator=
+      (const adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
+
+   //!Not assignable from
+   //!other adaptive_pool
+   //adaptive_pool& operator=(const adaptive_pool&);
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   adaptive_pool(segment_manager *segment_mngr);
+
+   //!Copy constructor from other adaptive_pool. Increments the reference
+   //!count of the associated node pool. Never throws
+   adaptive_pool(const adaptive_pool &other);
+
+   //!Copy constructor from related adaptive_pool. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   adaptive_pool
+      (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~adaptive_pool();
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   void* get_node_pool() const;
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const;
+
+   //!Returns the number of elements that could be allocated.
+   //!Never throws
+   size_type max_size() const;
+
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0);
+
+   //!Deallocate allocated memory.
+   //!Never throws
+   void deallocate(const pointer &ptr, size_type count);
+
+   //!Deallocates all free blocks
+   //!of the pool
+   void deallocate_free_blocks();
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2);
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const;
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const;
+/*
+   //!Copy construct an object.
+   //!Throws if T's copy constructor throws
+   void construct(const pointer &ptr, const_reference v);
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr);
+*/
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const;
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain);
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one();
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements);
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p);
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain it);
+   #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+                const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+                const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
+

+ 311 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/allocator.hpp

@@ -0,0 +1,311 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_ALLOCATOR_HPP
+#define BOOST_INTERPROCESS_ALLOCATOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/containers/allocation_type.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+
+#include <memory>
+#include <new>
+#include <algorithm>
+#include <cstddef>
+#include <stdexcept>
+
+//!\file
+//!Describes an allocator that allocates portions of fixed size
+//!memory buffer (shared memory, mapped file...)
+
+namespace boost {
+namespace interprocess {
+
+
+//!An STL compatible allocator that uses a segment manager as
+//!memory source. The internal pointer type will of the same type (raw, smart) as
+//!"typename SegmentManager::void_pointer" type. This allows
+//!placing the allocator in shared memory, memory mapped-files, etc...
+template<class T, class SegmentManager>
+class allocator
+{
+   public:
+   //Segment manager
+   typedef SegmentManager                                segment_manager;
+   typedef typename SegmentManager::void_pointer         void_pointer;
+
+   /// @cond
+   private:
+
+   //Self type
+   typedef allocator<T, SegmentManager>   self_t;
+
+   //Pointer to void
+   typedef typename segment_manager::void_pointer  aux_pointer_t;
+
+   //Typedef to const void pointer
+   typedef typename boost::intrusive::
+      pointer_traits<aux_pointer_t>::template
+         rebind_pointer<const void>::type          cvoid_ptr;
+
+   //Pointer to the allocator
+   typedef typename boost::intrusive::
+      pointer_traits<cvoid_ptr>::template
+         rebind_pointer<segment_manager>::type          alloc_ptr_t;
+
+   //Not assignable from related allocator
+   template<class T2, class SegmentManager2>
+   allocator& operator=(const allocator<T2, SegmentManager2>&);
+
+   //Not assignable from other allocator
+   allocator& operator=(const allocator&);
+
+   //Pointer to the allocator
+   alloc_ptr_t mp_mngr;
+   /// @endcond
+
+   public:
+   typedef T                                    value_type;
+   typedef typename boost::intrusive::
+      pointer_traits<cvoid_ptr>::template
+         rebind_pointer<T>::type                pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<pointer>::template
+         rebind_pointer<const T>::type          const_pointer;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type         reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type   const_reference;
+   typedef typename segment_manager::size_type               size_type;
+   typedef typename segment_manager::difference_type         difference_type;
+
+   typedef boost::interprocess::version_type<allocator, 2>   version;
+
+   /// @cond
+
+   //Experimental. Don't use.
+   typedef boost::container::container_detail::transform_multiallocation_chain
+      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+   /// @endcond
+
+   //!Obtains an allocator that allocates
+   //!objects of type T2
+   template<class T2>
+   struct rebind
+   {
+      typedef allocator<T2, SegmentManager>     other;
+   };
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const
+   {  return ipcdetail::to_raw_pointer(mp_mngr);   }
+
+   //!Constructor from the segment manager.
+   //!Never throws
+   allocator(segment_manager *segment_mngr)
+      : mp_mngr(segment_mngr) { }
+
+   //!Constructor from other allocator.
+   //!Never throws
+   allocator(const allocator &other)
+      : mp_mngr(other.get_segment_manager()){ }
+
+   //!Constructor from related allocator.
+   //!Never throws
+   template<class T2>
+   allocator(const allocator<T2, SegmentManager> &other)
+      : mp_mngr(other.get_segment_manager()){}
+
+   //!Allocates memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_ptr hint = 0)
+   {
+      (void)hint;
+      if(size_overflows<sizeof(T)>(count)){
+         throw bad_alloc();
+      }
+      return pointer(static_cast<value_type*>(mp_mngr->allocate(count*sizeof(T))));
+   }
+
+   //!Deallocates memory previously allocated.
+   //!Never throws
+   void deallocate(const pointer &ptr, size_type)
+   {  mp_mngr->deallocate((void*)ipcdetail::to_raw_pointer(ptr));  }
+
+   //!Returns the number of elements that could be allocated.
+   //!Never throws
+   size_type max_size() const
+   {  return mp_mngr->get_size()/sizeof(T);   }
+
+   //!Swap segment manager. Does not throw. If each allocator is placed in
+   //!different memory segments, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2)
+   {  ipcdetail::do_swap(alloc1.mp_mngr, alloc2.mp_mngr);   }
+
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const
+   {
+      return (size_type)mp_mngr->size(ipcdetail::to_raw_pointer(p))/sizeof(T);
+   }
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0)
+   {
+      return mp_mngr->allocation_command
+         (command, limit_size, preferred_size, received_size, ipcdetail::to_raw_pointer(reuse));
+   }
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many
+      (size_type elem_size, size_type num_elements)
+   {
+      if(size_overflows<sizeof(T)>(elem_size)){
+         throw bad_alloc();
+      }
+      return multiallocation_chain(mp_mngr->allocate_many(elem_size*sizeof(T), num_elements));
+   }
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many
+      (const size_type *elem_sizes, size_type n_elements)
+   {
+      multiallocation_chain(mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T)));
+   }
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain)
+   {
+      return mp_mngr->deallocate_many(chain.extract_multiallocation_chain());
+   }
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one()
+   {  return this->allocate(1);  }
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual
+      (size_type num_elements)
+   {  return this->allocate_many(1, num_elements); }
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p)
+   {  return this->deallocate(p, 1);  }
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain chain)
+   {  return this->deallocate_many(boost::move(chain)); }
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const
+   {  return pointer(boost::addressof(value));  }
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const
+   {  return const_pointer(boost::addressof(value));  }
+
+   //!Constructs an object
+   //!Throws if T's constructor throws
+   //!For backwards compatibility with libraries using C++03 allocators
+   template<class P>
+   void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
+   {  ::new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(::boost::forward<P>(p));  }
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr)
+   {  BOOST_ASSERT(ptr != 0); (*ptr).~value_type();  }
+
+};
+
+//!Equality test for same type
+//!of allocator
+template<class T, class SegmentManager> inline
+bool operator==(const allocator<T , SegmentManager>  &alloc1,
+                const allocator<T, SegmentManager>  &alloc2)
+   {  return alloc1.get_segment_manager() == alloc2.get_segment_manager(); }
+
+//!Inequality test for same type
+//!of allocator
+template<class T, class SegmentManager> inline
+bool operator!=(const allocator<T, SegmentManager>  &alloc1,
+                const allocator<T, SegmentManager>  &alloc2)
+   {  return alloc1.get_segment_manager() != alloc2.get_segment_manager(); }
+
+}  //namespace interprocess {
+
+/// @cond
+
+template<class T>
+struct has_trivial_destructor;
+
+template<class T, class SegmentManager>
+struct has_trivial_destructor
+   <boost::interprocess::allocator <T, SegmentManager> >
+{
+   static const bool value = true;
+};
+/// @endcond
+
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_ALLOCATOR_HPP
+

+ 356 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/cached_adaptive_pool.hpp

@@ -0,0 +1,356 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP
+#define BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/interprocess/allocators/detail/node_tools.hpp>
+#include <cstddef>
+
+//!\file
+//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+namespace ipcdetail {
+
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock = 64
+         , std::size_t MaxFreeBlocks = 2
+         , unsigned char OverheadPercent = 5
+         >
+class cached_adaptive_pool_v1
+   :  public ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_adaptive_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            , MaxFreeBlocks
+            , OverheadPercent
+            >
+         , 1>
+{
+   public:
+   typedef ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_adaptive_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            , MaxFreeBlocks
+            , OverheadPercent
+            >
+         , 1> base_t;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef cached_adaptive_pool_v1
+         <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
+   };
+
+   typedef typename base_t::size_type size_type;
+
+   cached_adaptive_pool_v1(SegmentManager *segment_mngr,
+                           size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
+      : base_t(segment_mngr, max_cached_nodes)
+   {}
+
+   template<class T2>
+   cached_adaptive_pool_v1
+      (const cached_adaptive_pool_v1
+         <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : base_t(other)
+   {}
+};
+
+}  //namespace ipcdetail{
+
+/// @endcond
+
+//!An STL node allocator that uses a segment manager as memory
+//!source. The internal pointer type will of the same type (raw, smart) as
+//!"typename SegmentManager::void_pointer" type. This allows
+//!placing the allocator in shared memory, memory mapped-files, etc...
+//!
+//!This node allocator shares a segregated storage between all instances of
+//!cached_adaptive_pool with equal sizeof(T) placed in the same
+//!memory segment. But also caches some nodes privately to
+//!avoid some synchronization overhead.
+//!
+//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when
+//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
+//!that the adaptive node pool will hold. The rest of the totally free blocks will be
+//!deallocated with the segment manager.
+//!
+//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
+//!(memory usable for nodes / total memory allocated from the segment manager)
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         , std::size_t MaxFreeBlocks
+         , unsigned char OverheadPercent
+         >
+class cached_adaptive_pool
+   /// @cond
+   :  public ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_adaptive_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            , MaxFreeBlocks
+            , OverheadPercent
+            >
+         , 2>
+   /// @endcond
+{
+
+   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   public:
+   typedef ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_adaptive_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            , MaxFreeBlocks
+            , OverheadPercent
+            >
+         , 2> base_t;
+
+   public:
+   typedef boost::interprocess::version_type<cached_adaptive_pool, 2>   version;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef cached_adaptive_pool
+         <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
+   };
+
+   cached_adaptive_pool(SegmentManager *segment_mngr,
+                         std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
+      : base_t(segment_mngr, max_cached_nodes)
+   {}
+
+   template<class T2>
+   cached_adaptive_pool
+      (const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : base_t(other)
+   {}
+
+   #else
+   public:
+   typedef implementation_defined::segment_manager       segment_manager;
+   typedef segment_manager::void_pointer                 void_pointer;
+   typedef implementation_defined::pointer               pointer;
+   typedef implementation_defined::const_pointer         const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::difference_type     difference_type;
+
+   //!Obtains cached_adaptive_pool from
+   //!cached_adaptive_pool
+   template<class T2>
+   struct rebind
+   {
+      typedef cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+   };
+
+   private:
+   //!Not assignable from
+   //!related cached_adaptive_pool
+   template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
+   cached_adaptive_pool& operator=
+      (const cached_adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
+
+   //!Not assignable from
+   //!other cached_adaptive_pool
+   cached_adaptive_pool& operator=(const cached_adaptive_pool&);
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   cached_adaptive_pool(segment_manager *segment_mngr);
+
+   //!Copy constructor from other cached_adaptive_pool. Increments the reference
+   //!count of the associated node pool. Never throws
+   cached_adaptive_pool(const cached_adaptive_pool &other);
+
+   //!Copy constructor from related cached_adaptive_pool. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   cached_adaptive_pool
+      (const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~cached_adaptive_pool();
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   node_pool_t* get_node_pool() const;
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const;
+
+   //!Returns the number of elements that could be allocated.
+   //!Never throws
+   size_type max_size() const;
+
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0);
+
+   //!Deallocate allocated memory.
+   //!Never throws
+   void deallocate(const pointer &ptr, size_type count);
+
+   //!Deallocates all free blocks
+   //!of the pool
+   void deallocate_free_blocks();
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2);
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const;
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const;
+
+   //!Copy construct an object.
+   //!Throws if T's copy constructor throws
+   void construct(const pointer &ptr, const_reference v);
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr);
+
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const;
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain);
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one();
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements);
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p);
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain chain);
+   //!Sets the new max cached nodes value. This can provoke deallocations
+   //!if "newmax" is less than current cached nodes. Never throws
+   void set_max_cached_nodes(size_type newmax);
+
+   //!Returns the max cached nodes parameter.
+   //!Never throws
+   size_type get_max_cached_nodes() const;
+   #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of cached_adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline
+bool operator==(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+                const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of cached_adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline
+bool operator!=(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+                const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP
+

+ 327 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/cached_node_allocator.hpp

@@ -0,0 +1,327 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
+#define BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/allocators/detail/node_pool.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/interprocess/allocators/detail/node_tools.hpp>
+#include <cstddef>
+
+//!\file
+//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+
+/// @cond
+
+namespace ipcdetail {
+
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock = 64
+         >
+class cached_node_allocator_v1
+   :  public ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            >
+         , 1>
+{
+   public:
+   typedef ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            >
+         , 1> base_t;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef cached_node_allocator_v1
+         <T2, SegmentManager, NodesPerBlock>  other;
+   };
+
+   typedef typename base_t::size_type size_type;
+
+   cached_node_allocator_v1(SegmentManager *segment_mngr,
+                         size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
+      : base_t(segment_mngr, max_cached_nodes)
+   {}
+
+   template<class T2>
+   cached_node_allocator_v1
+      (const cached_node_allocator_v1
+         <T2, SegmentManager, NodesPerBlock> &other)
+      : base_t(other)
+   {}
+};
+
+}  //namespace ipcdetail{
+
+/// @endcond
+
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         >
+class cached_node_allocator
+   /// @cond
+   :  public ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            >
+         , 2>
+   /// @endcond
+{
+
+   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   public:
+   typedef ipcdetail::cached_allocator_impl
+         < T
+         , ipcdetail::shared_node_pool
+            < SegmentManager
+            , sizeof_value<T>::value
+            , NodesPerBlock
+            >
+         , 2> base_t;
+
+   public:
+   typedef boost::interprocess::version_type<cached_node_allocator, 2>   version;
+   typedef typename base_t::size_type size_type;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef cached_node_allocator<T2, SegmentManager, NodesPerBlock>  other;
+   };
+
+   cached_node_allocator(SegmentManager *segment_mngr,
+                         size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
+      : base_t(segment_mngr, max_cached_nodes)
+   {}
+
+   template<class T2>
+   cached_node_allocator
+      (const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
+      : base_t(other)
+   {}
+
+   #else
+   public:
+   typedef implementation_defined::segment_manager       segment_manager;
+   typedef segment_manager::void_pointer                 void_pointer;
+   typedef implementation_defined::pointer               pointer;
+   typedef implementation_defined::const_pointer         const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename SegmentManager::size_type            size_type;
+   typedef typename SegmentManager::difference_type      difference_type;
+
+   //!Obtains cached_node_allocator from
+   //!cached_node_allocator
+   template<class T2>
+   struct rebind
+   {
+      typedef cached_node_allocator<T2, SegmentManager> other;
+   };
+
+   private:
+   //!Not assignable from
+   //!related cached_node_allocator
+   template<class T2, class SegmentManager2, std::size_t N2>
+   cached_node_allocator& operator=
+      (const cached_node_allocator<T2, SegmentManager2, N2>&);
+
+   //!Not assignable from
+   //!other cached_node_allocator
+   cached_node_allocator& operator=(const cached_node_allocator&);
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   cached_node_allocator(segment_manager *segment_mngr);
+
+   //!Copy constructor from other cached_node_allocator. Increments the reference
+   //!count of the associated node pool. Never throws
+   cached_node_allocator(const cached_node_allocator &other);
+
+   //!Copy constructor from related cached_node_allocator. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   cached_node_allocator
+      (const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &other);
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~cached_node_allocator();
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   node_pool_t* get_node_pool() const;
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const;
+
+   //!Returns the number of elements that could be allocated.
+   //!Never throws
+   size_type max_size() const;
+
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0);
+
+   //!Deallocate allocated memory.
+   //!Never throws
+   void deallocate(const pointer &ptr, size_type count);
+
+   //!Deallocates all free blocks
+   //!of the pool
+   void deallocate_free_blocks();
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2);
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const;
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const;
+
+   //!Default construct an object.
+   //!Throws if T's default constructor throws
+   void construct(const pointer &ptr, const_reference v);
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr);
+
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const;
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain);
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one();
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements);
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p);
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain it);
+   //!Sets the new max cached nodes value. This can provoke deallocations
+   //!if "newmax" is less than current cached nodes. Never throws
+   void set_max_cached_nodes(size_type newmax);
+
+   //!Returns the max cached nodes parameter.
+   //!Never throws
+   size_type get_max_cached_nodes() const;
+   #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of cached_node_allocator
+template<class T, class S, std::size_t NPC> inline
+bool operator==(const cached_node_allocator<T, S, NPC> &alloc1,
+                const cached_node_allocator<T, S, NPC> &alloc2);
+
+//!Inequality test for same type
+//!of cached_node_allocator
+template<class T, class S, std::size_t NPC> inline
+bool operator!=(const cached_node_allocator<T, S, NPC> &alloc1,
+                const cached_node_allocator<T, S, NPC> &alloc2);
+
+#endif
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
+

+ 108 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/adaptive_node_pool.hpp

@@ -0,0 +1,108 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP
+#define BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/math_functions.hpp>
+#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/slist.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
+#include <boost/interprocess/allocators/detail/node_tools.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <cstddef>
+#include <boost/config/no_tr1/cmath.hpp>
+#include <boost/container/detail/adaptive_node_pool_impl.hpp>
+#include <boost/assert.hpp>
+
+//!\file
+//!Describes the real adaptive pool shared by many Interprocess pool allocators
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template< class SegmentManager
+        , std::size_t NodeSize
+        , std::size_t NodesPerBlock
+        , std::size_t MaxFreeBlocks
+        , unsigned char OverheadPercent
+        >
+class private_adaptive_node_pool
+   :  public boost::container::container_detail::private_adaptive_node_pool_impl
+         <typename SegmentManager::segment_manager_base_type>
+{
+   typedef boost::container::container_detail::private_adaptive_node_pool_impl
+      <typename SegmentManager::segment_manager_base_type> base_t;
+   //Non-copyable
+   private_adaptive_node_pool();
+   private_adaptive_node_pool(const private_adaptive_node_pool &);
+   private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
+
+   public:
+   typedef SegmentManager              segment_manager;
+   typedef typename base_t::size_type  size_type;
+
+   static const size_type nodes_per_block = NodesPerBlock;
+
+   //Deprecated, use node_per_block
+   static const size_type nodes_per_chunk = NodesPerBlock;
+
+   //!Constructor from a segment manager. Never throws
+   private_adaptive_node_pool(segment_manager *segment_mngr)
+      :  base_t(segment_mngr, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent)
+   {}
+
+   //!Returns the segment manager. Never throws
+   segment_manager* get_segment_manager() const
+   {  return static_cast<segment_manager*>(base_t::get_segment_manager_base()); }
+};
+
+//!Pooled shared memory allocator using adaptive pool. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template< class SegmentManager
+        , std::size_t NodeSize
+        , std::size_t NodesPerBlock
+        , std::size_t MaxFreeBlocks
+        , unsigned char OverheadPercent
+        >
+class shared_adaptive_node_pool
+   :  public ipcdetail::shared_pool_impl
+      < private_adaptive_node_pool
+         <SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
+      >
+{
+   typedef ipcdetail::shared_pool_impl
+      < private_adaptive_node_pool
+         <SegmentManager, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
+      > base_t;
+   public:
+   shared_adaptive_node_pool(SegmentManager *segment_mgnr)
+      : base_t(segment_mgnr)
+   {}
+};
+
+}  //namespace ipcdetail {
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP

+ 867 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/allocator_common.hpp

@@ -0,0 +1,867 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
+#define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/detail/utilities.hpp> //to_raw_pointer
+#include <boost/utility/addressof.hpp> //boost::addressof
+#include <boost/assert.hpp>   //BOOST_ASSERT
+#include <boost/interprocess/exceptions.hpp> //bad_alloc
+#include <boost/interprocess/sync/scoped_lock.hpp> //scoped_lock
+#include <boost/interprocess/containers/allocation_type.hpp> //boost::interprocess::allocation_type
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
+#include <boost/interprocess/detail/segment_manager_helper.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <algorithm> //std::swap
+#include <utility>   //std::pair
+#include <new>
+
+namespace boost {
+namespace interprocess {
+
+template <class T>
+struct sizeof_value
+{
+   static const std::size_t value = sizeof(T);
+};
+
+template <>
+struct sizeof_value<void>
+{
+   static const std::size_t value = sizeof(void*);
+};
+
+template <>
+struct sizeof_value<const void>
+{
+   static const std::size_t value = sizeof(void*);
+};
+
+template <>
+struct sizeof_value<volatile void>
+{
+   static const std::size_t value = sizeof(void*);
+};
+
+template <>
+struct sizeof_value<const volatile void>
+{
+   static const std::size_t value = sizeof(void*);
+};
+
+namespace ipcdetail {
+
+//!Object function that creates the node allocator if it is not created and
+//!increments reference count if it is already created
+template<class NodePool>
+struct get_or_create_node_pool_func
+{
+
+   //!This connects or constructs the unique instance of node_pool_t
+   //!Can throw boost::interprocess::bad_alloc
+   void operator()()
+   {
+      //Find or create the node_pool_t
+      mp_node_pool =    mp_segment_manager->template find_or_construct
+                        <NodePool>(boost::interprocess::unique_instance)(mp_segment_manager);
+      //If valid, increment link count
+      if(mp_node_pool != 0)
+         mp_node_pool->inc_ref_count();
+   }
+
+   //!Constructor. Initializes function
+   //!object parameters
+   get_or_create_node_pool_func(typename NodePool::segment_manager *mngr)
+      : mp_segment_manager(mngr){}
+
+   NodePool                            *mp_node_pool;
+   typename NodePool::segment_manager  *mp_segment_manager;
+};
+
+template<class NodePool>
+inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgnr)
+{
+   ipcdetail::get_or_create_node_pool_func<NodePool> func(mgnr);
+   mgnr->atomic_func(func);
+   return func.mp_node_pool;
+}
+
+//!Object function that decrements the reference count. If the count
+//!reaches to zero destroys the node allocator from memory.
+//!Never throws
+template<class NodePool>
+struct destroy_if_last_link_func
+{
+   //!Decrements reference count and destroys the object if there is no
+   //!more attached allocators. Never throws
+   void operator()()
+   {
+      //If not the last link return
+      if(mp_node_pool->dec_ref_count() != 0) return;
+
+      //Last link, let's destroy the segment_manager
+      mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance);
+   }
+
+   //!Constructor. Initializes function
+   //!object parameters
+   destroy_if_last_link_func(NodePool *pool)
+      : mp_node_pool(pool)
+   {}
+
+   NodePool                           *mp_node_pool;
+};
+
+//!Destruction function, initializes and executes destruction function
+//!object. Never throws
+template<class NodePool>
+inline void destroy_node_pool_if_last_link(NodePool *pool)
+{
+   //Get segment manager
+   typename NodePool::segment_manager *mngr = pool->get_segment_manager();
+   //Execute destruction functor atomically
+   destroy_if_last_link_func<NodePool>func(pool);
+   mngr->atomic_func(func);
+}
+
+template<class NodePool>
+class cache_impl
+{
+   typedef typename NodePool::segment_manager::
+      void_pointer                                          void_pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<NodePool>::type                     node_pool_ptr;
+   typedef typename NodePool::multiallocation_chain         multiallocation_chain;
+   typedef typename NodePool::segment_manager::size_type    size_type;
+   node_pool_ptr                 mp_node_pool;
+   multiallocation_chain         m_cached_nodes;
+   size_type                     m_max_cached_nodes;
+
+   public:
+   typedef typename NodePool::segment_manager            segment_manager;
+
+   cache_impl(segment_manager *segment_mngr, size_type max_cached_nodes)
+      : mp_node_pool(get_or_create_node_pool<NodePool>(segment_mngr))
+      , m_max_cached_nodes(max_cached_nodes)
+   {}
+
+   cache_impl(const cache_impl &other)
+      : mp_node_pool(other.get_node_pool())
+      , m_max_cached_nodes(other.get_max_cached_nodes())
+   {
+      mp_node_pool->inc_ref_count();
+   }
+
+   ~cache_impl()
+   {
+      this->deallocate_all_cached_nodes();
+      ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool));
+   }
+
+   NodePool *get_node_pool() const
+   {  return ipcdetail::to_raw_pointer(mp_node_pool); }
+
+   segment_manager *get_segment_manager() const
+   {  return mp_node_pool->get_segment_manager(); }
+
+   size_type get_max_cached_nodes() const
+   {  return m_max_cached_nodes; }
+
+   void *cached_allocation()
+   {
+      //If don't have any cached node, we have to get a new list of free nodes from the pool
+      if(m_cached_nodes.empty()){
+         m_cached_nodes = mp_node_pool->allocate_nodes(m_max_cached_nodes/2);
+      }
+      void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front());
+      return ret;
+   }
+
+   multiallocation_chain cached_allocation(size_type n)
+   {
+      multiallocation_chain chain;
+      size_type count = n, allocated(0);
+      BOOST_TRY{
+         //If don't have any cached node, we have to get a new list of free nodes from the pool
+         while(!m_cached_nodes.empty() && count--){
+            void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front());
+            chain.push_back(ret);
+            ++allocated;
+         }
+
+         if(allocated != n){
+            multiallocation_chain chain2(mp_node_pool->allocate_nodes(n - allocated));
+            chain.splice_after(chain.last(), chain2, chain2.before_begin(), chain2.last(), n - allocated);
+         }
+         return boost::move(chain);
+      }
+      BOOST_CATCH(...){
+         this->cached_deallocation(boost::move(chain));
+         BOOST_RETHROW
+      }
+      BOOST_CATCH_END
+   }
+
+   void cached_deallocation(void *ptr)
+   {
+      //Check if cache is full
+      if(m_cached_nodes.size() >= m_max_cached_nodes){
+         //This only occurs if this allocator deallocate memory allocated
+         //with other equal allocator. Since the cache is full, and more
+         //deallocations are probably coming, we'll make some room in cache
+         //in a single, efficient multi node deallocation.
+         this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2);
+      }
+      m_cached_nodes.push_front(ptr);
+   }
+
+   void cached_deallocation(multiallocation_chain chain)
+   {
+      m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain);
+
+      //Check if cache is full
+      if(m_cached_nodes.size() >= m_max_cached_nodes){
+         //This only occurs if this allocator deallocate memory allocated
+         //with other equal allocator. Since the cache is full, and more
+         //deallocations are probably coming, we'll make some room in cache
+         //in a single, efficient multi node deallocation.
+         this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2);
+      }
+   }
+
+   //!Sets the new max cached nodes value. This can provoke deallocations
+   //!if "newmax" is less than current cached nodes. Never throws
+   void set_max_cached_nodes(size_type newmax)
+   {
+      m_max_cached_nodes = newmax;
+      this->priv_deallocate_remaining_nodes();
+   }
+
+   //!Frees all cached nodes.
+   //!Never throws
+   void deallocate_all_cached_nodes()
+   {
+      if(m_cached_nodes.empty()) return;
+      mp_node_pool->deallocate_nodes(boost::move(m_cached_nodes));
+   }
+
+   private:
+   //!Frees all cached nodes at once.
+   //!Never throws
+   void priv_deallocate_remaining_nodes()
+   {
+      if(m_cached_nodes.size() > m_max_cached_nodes){
+         priv_deallocate_n_nodes(m_cached_nodes.size()-m_max_cached_nodes);
+      }
+   }
+
+   //!Frees n cached nodes at once. Never throws
+   void priv_deallocate_n_nodes(size_type n)
+   {
+      //This only occurs if this allocator deallocate memory allocated
+      //with other equal allocator. Since the cache is full, and more
+      //deallocations are probably coming, we'll make some room in cache
+      //in a single, efficient multi node deallocation.
+      size_type count(n);
+      typename multiallocation_chain::iterator it(m_cached_nodes.before_begin());
+      while(count--){
+         ++it;
+      }
+      multiallocation_chain chain;
+      chain.splice_after(chain.before_begin(), m_cached_nodes, m_cached_nodes.before_begin(), it, n);
+      //Deallocate all new linked list at once
+      mp_node_pool->deallocate_nodes(boost::move(chain));
+   }
+
+   public:
+   void swap(cache_impl &other)
+   {
+      ipcdetail::do_swap(mp_node_pool, other.mp_node_pool);
+      m_cached_nodes.swap(other.m_cached_nodes);
+      ipcdetail::do_swap(m_max_cached_nodes, other.m_max_cached_nodes);
+   }
+};
+
+template<class Derived, class T, class SegmentManager>
+class array_allocation_impl
+{
+   const Derived *derived() const
+   {  return static_cast<const Derived*>(this); }
+   Derived *derived()
+   {  return static_cast<Derived*>(this); }
+
+   typedef typename SegmentManager::void_pointer         void_pointer;
+
+   public:
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<T>::type                         pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const T>::type                   const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename SegmentManager::size_type            size_type;
+   typedef typename SegmentManager::difference_type      difference_type;
+   typedef boost::container::container_detail::transform_multiallocation_chain
+      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+
+   public:
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const
+   {
+      return (size_type)this->derived()->get_segment_manager()->size(ipcdetail::to_raw_pointer(p))/sizeof(T);
+   }
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0)
+   {
+      return this->derived()->get_segment_manager()->allocation_command
+         (command, limit_size, preferred_size, received_size, ipcdetail::to_raw_pointer(reuse));
+   }
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many(size_type elem_size, size_type num_elements)
+   {
+      if(size_overflows<sizeof(T)>(elem_size)){
+         throw bad_alloc();
+      }
+      return this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements);
+   }
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
+   {
+      return this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T));
+   }
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain)
+   {  return this->derived()->get_segment_manager()->deallocate_many(boost::move(chain)); }
+
+   //!Returns the number of elements that could be
+   //!allocated. Never throws
+   size_type max_size() const
+   {  return this->derived()->get_segment_manager()->get_size()/sizeof(T);  }
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const
+   {  return pointer(boost::addressof(value));  }
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const
+   {  return const_pointer(boost::addressof(value));  }
+
+   //!Constructs an object
+   //!Throws if T's constructor throws
+   //!For backwards compatibility with libraries using C++03 allocators
+   template<class P>
+   void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
+   {  ::new((void*)ipcdetail::to_raw_pointer(ptr)) value_type(::boost::forward<P>(p));  }
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr)
+   {  BOOST_ASSERT(ptr != 0); (*ptr).~value_type();  }
+};
+
+
+template<class Derived, unsigned int Version, class T, class SegmentManager>
+class node_pool_allocation_impl
+   :  public array_allocation_impl
+      < Derived
+      , T
+      , SegmentManager>
+{
+   const Derived *derived() const
+   {  return static_cast<const Derived*>(this); }
+   Derived *derived()
+   {  return static_cast<Derived*>(this); }
+
+   typedef typename SegmentManager::void_pointer         void_pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const void>::type                cvoid_pointer;
+
+   public:
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<T>::type                         pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const T>::type                   const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename SegmentManager::size_type            size_type;
+   typedef typename SegmentManager::difference_type      difference_type;
+   typedef boost::container::container_detail::transform_multiallocation_chain
+      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+
+   template <int Dummy>
+   struct node_pool
+   {
+      typedef typename Derived::template node_pool<0>::type type;
+      static type *get(void *p)
+      {  return static_cast<type*>(p); }
+   };
+
+   public:
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0)
+   {
+      (void)hint;
+      typedef typename node_pool<0>::type node_pool_t;
+      node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+      if(size_overflows<sizeof(T)>(count)){
+         throw bad_alloc();
+      }
+      else if(Version == 1 && count == 1){
+         return pointer(static_cast<value_type*>
+         (pool->allocate_node()));
+      }
+      else{
+         return pointer(static_cast<value_type*>
+            (pool->get_segment_manager()->allocate(count*sizeof(T))));
+      }
+   }
+
+   //!Deallocate allocated memory. Never throws
+   void deallocate(const pointer &ptr, size_type count)
+   {
+      (void)count;
+      typedef typename node_pool<0>::type node_pool_t;
+      node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+      if(Version == 1 && count == 1)
+         pool->deallocate_node(ipcdetail::to_raw_pointer(ptr));
+      else
+         pool->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr));
+   }
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one()
+   {
+      typedef typename node_pool<0>::type node_pool_t;
+      node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+      return pointer(static_cast<value_type*>(pool->allocate_node()));
+   }
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements)
+   {
+      typedef typename node_pool<0>::type node_pool_t;
+      node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+      return multiallocation_chain(pool->allocate_nodes(num_elements));
+   }
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p)
+   {
+      typedef typename node_pool<0>::type node_pool_t;
+      node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
+      pool->deallocate_node(ipcdetail::to_raw_pointer(p));
+   }
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain chain)
+   {
+      node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes
+         (chain.extract_multiallocation_chain());
+   }
+
+   //!Deallocates all free blocks of the pool
+   void deallocate_free_blocks()
+   {  node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks();  }
+
+   //!Deprecated, use deallocate_free_blocks.
+   //!Deallocates all free chunks of the pool.
+   void deallocate_free_chunks()
+   {  node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks();  }
+};
+
+template<class T, class NodePool, unsigned int Version>
+class cached_allocator_impl
+   :  public array_allocation_impl
+         <cached_allocator_impl<T, NodePool, Version>, T, typename NodePool::segment_manager>
+{
+   cached_allocator_impl & operator=(const cached_allocator_impl& other);
+   typedef array_allocation_impl
+         < cached_allocator_impl
+            <T, NodePool, Version>
+         , T
+         , typename NodePool::segment_manager> base_t;
+
+   public:
+   typedef NodePool                                      node_pool_t;
+   typedef typename NodePool::segment_manager            segment_manager;
+   typedef typename segment_manager::void_pointer        void_pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const void>::type                cvoid_pointer;
+   typedef typename base_t::pointer                      pointer;
+   typedef typename base_t::size_type                    size_type;
+   typedef typename base_t::multiallocation_chain        multiallocation_chain;
+   typedef typename base_t::value_type                   value_type;
+
+   public:
+   static const std::size_t DEFAULT_MAX_CACHED_NODES = 64;
+
+   cached_allocator_impl(segment_manager *segment_mngr, size_type max_cached_nodes)
+      : m_cache(segment_mngr, max_cached_nodes)
+   {}
+
+   cached_allocator_impl(const cached_allocator_impl &other)
+      : m_cache(other.m_cache)
+   {}
+
+   //!Copy constructor from related cached_adaptive_pool_base. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2, class NodePool2>
+   cached_allocator_impl
+      (const cached_allocator_impl
+         <T2, NodePool2, Version> &other)
+      : m_cache(other.get_segment_manager(), other.get_max_cached_nodes())
+   {}
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   node_pool_t* get_node_pool() const
+   {  return m_cache.get_node_pool();   }
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const
+   {  return m_cache.get_segment_manager();   }
+
+   //!Sets the new max cached nodes value. This can provoke deallocations
+   //!if "newmax" is less than current cached nodes. Never throws
+   void set_max_cached_nodes(size_type newmax)
+   {  m_cache.set_max_cached_nodes(newmax);   }
+
+   //!Returns the max cached nodes parameter.
+   //!Never throws
+   size_type get_max_cached_nodes() const
+   {  return m_cache.get_max_cached_nodes();   }
+
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0)
+   {
+      (void)hint;
+      void * ret;
+      if(size_overflows<sizeof(T)>(count)){
+         throw bad_alloc();
+      }
+      else if(Version == 1 && count == 1){
+         ret = m_cache.cached_allocation();
+      }
+      else{
+         ret = this->get_segment_manager()->allocate(count*sizeof(T));
+      }
+      return pointer(static_cast<T*>(ret));
+   }
+
+   //!Deallocate allocated memory. Never throws
+   void deallocate(const pointer &ptr, size_type count)
+   {
+      (void)count;
+      if(Version == 1 && count == 1){
+         m_cache.cached_deallocation(ipcdetail::to_raw_pointer(ptr));
+      }
+      else{
+         this->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr));
+      }
+   }
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one()
+   {  return pointer(static_cast<value_type*>(this->m_cache.cached_allocation()));   }
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements)
+   {  return multiallocation_chain(this->m_cache.cached_allocation(num_elements));   }
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p)
+   {  this->m_cache.cached_deallocation(ipcdetail::to_raw_pointer(p)); }
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain chain)
+   {
+      typename node_pool_t::multiallocation_chain mem
+         (chain.extract_multiallocation_chain());
+      m_cache.cached_deallocation(boost::move(mem));
+   }
+
+   //!Deallocates all free blocks of the pool
+   void deallocate_free_blocks()
+   {  m_cache.get_node_pool()->deallocate_free_blocks();   }
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different shared memory segments, the result is undefined.
+   friend void swap(cached_allocator_impl &alloc1, cached_allocator_impl &alloc2)
+   {  alloc1.m_cache.swap(alloc2.m_cache);   }
+
+   void deallocate_cache()
+   {  m_cache.deallocate_all_cached_nodes(); }
+
+   //!Deprecated use deallocate_free_blocks.
+   void deallocate_free_chunks()
+   {  m_cache.get_node_pool()->deallocate_free_blocks();   }
+
+   /// @cond
+   private:
+   cache_impl<node_pool_t> m_cache;
+};
+
+//!Equality test for same type of
+//!cached_allocator_impl
+template<class T, class N, unsigned int V> inline
+bool operator==(const cached_allocator_impl<T, N, V> &alloc1,
+                const cached_allocator_impl<T, N, V> &alloc2)
+   {  return alloc1.get_node_pool() == alloc2.get_node_pool(); }
+
+//!Inequality test for same type of
+//!cached_allocator_impl
+template<class T, class N, unsigned int V> inline
+bool operator!=(const cached_allocator_impl<T, N, V> &alloc1,
+                const cached_allocator_impl<T, N, V> &alloc2)
+   {  return alloc1.get_node_pool() != alloc2.get_node_pool(); }
+
+
+//!Pooled shared memory allocator using adaptive pool. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template<class private_node_allocator_t>
+class shared_pool_impl
+   : public private_node_allocator_t
+{
+ public:
+   //!Segment manager typedef
+   typedef typename private_node_allocator_t::
+      segment_manager                           segment_manager;
+   typedef typename private_node_allocator_t::
+      multiallocation_chain                     multiallocation_chain;
+   typedef typename private_node_allocator_t::
+     size_type                                 size_type;
+
+ private:
+   typedef typename segment_manager::mutex_family::mutex_type mutex_type;
+
+ public:
+   //!Constructor from a segment manager. Never throws
+   shared_pool_impl(segment_manager *segment_mngr)
+      : private_node_allocator_t(segment_mngr)
+   {}
+
+   //!Destructor. Deallocates all allocated blocks. Never throws
+   ~shared_pool_impl()
+   {}
+
+   //!Allocates array of count elements. Can throw boost::interprocess::bad_alloc
+   void *allocate_node()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      return private_node_allocator_t::allocate_node();
+   }
+
+   //!Deallocates an array pointed by ptr. Never throws
+   void deallocate_node(void *ptr)
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::deallocate_node(ptr);
+   }
+/*
+   //!Allocates a singly linked list of n nodes ending in null pointer.
+   //!can throw boost::interprocess::bad_alloc
+   void allocate_nodes(multiallocation_chain &nodes, size_type n)
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      return private_node_allocator_t::allocate_nodes(nodes, n);
+   }
+*/
+   //!Allocates n nodes.
+   //!Can throw boost::interprocess::bad_alloc
+   multiallocation_chain allocate_nodes(const size_type n)
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      return private_node_allocator_t::allocate_nodes(n);
+   }
+
+   //!Deallocates a linked list of nodes ending in null pointer. Never throws
+   void deallocate_nodes(multiallocation_chain &nodes, size_type num)
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::deallocate_nodes(nodes, num);
+   }
+
+   //!Deallocates the nodes pointed by the multiallocation iterator. Never throws
+   void deallocate_nodes(multiallocation_chain chain)
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::deallocate_nodes(boost::move(chain));
+   }
+
+   //!Deallocates all the free blocks of memory. Never throws
+   void deallocate_free_blocks()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::deallocate_free_blocks();
+   }
+
+   //!Deallocates all used memory from the common pool.
+   //!Precondition: all nodes allocated from this pool should
+   //!already be deallocated. Otherwise, undefined behavior. Never throws
+   void purge_blocks()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::purge_blocks();
+   }
+
+   //!Increments internal reference count and returns new count. Never throws
+   size_type inc_ref_count()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      return ++m_header.m_usecount;
+   }
+
+   //!Decrements internal reference count and returns new count. Never throws
+   size_type dec_ref_count()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      BOOST_ASSERT(m_header.m_usecount > 0);
+      return --m_header.m_usecount;
+   }
+
+   //!Deprecated, use deallocate_free_blocks.
+   void deallocate_free_chunks()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::deallocate_free_blocks();
+   }
+
+   //!Deprecated, use purge_blocks.
+   void purge_chunks()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<mutex_type> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::purge_blocks();
+   }
+
+   private:
+   //!This struct includes needed data and derives from
+   //!the mutex type to allow EBO when using null_mutex
+   struct header_t : mutex_type
+   {
+      size_type m_usecount;    //Number of attached allocators
+
+      header_t()
+      :  m_usecount(0) {}
+   } m_header;
+};
+
+}  //namespace ipcdetail {
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP

+ 109 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/node_pool.hpp

@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP
+#define BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/slist.hpp>
+#include <boost/math/common_factor_ct.hpp>
+
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <boost/container/detail/node_pool_impl.hpp>
+#include <cstddef>
+
+
+//!\file
+//!Describes the real adaptive pool shared by many Interprocess adaptive pool allocators
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+
+
+//!Pooled shared memory allocator using single segregated storage. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template< class SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock >
+class private_node_pool
+   //Inherit from the implementation to avoid template bloat
+   :  public boost::container::container_detail::
+         private_node_pool_impl<typename SegmentManager::segment_manager_base_type>
+{
+   typedef boost::container::container_detail::private_node_pool_impl
+      <typename SegmentManager::segment_manager_base_type> base_t;
+   //Non-copyable
+   private_node_pool();
+   private_node_pool(const private_node_pool &);
+   private_node_pool &operator=(const private_node_pool &);
+
+   public:
+   typedef SegmentManager              segment_manager;
+   typedef typename base_t::size_type  size_type;
+
+   static const size_type nodes_per_block = NodesPerBlock;
+   //Deprecated, use nodes_per_block
+   static const size_type nodes_per_chunk = NodesPerBlock;
+
+   //!Constructor from a segment manager. Never throws
+   private_node_pool(segment_manager *segment_mngr)
+      :  base_t(segment_mngr, NodeSize, NodesPerBlock)
+   {}
+
+   //!Returns the segment manager. Never throws
+   segment_manager* get_segment_manager() const
+   {  return static_cast<segment_manager*>(base_t::get_segment_manager_base()); }
+};
+
+
+//!Pooled shared memory allocator using single segregated storage. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+//!Pooled shared memory allocator using adaptive pool. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template< class SegmentManager
+        , std::size_t NodeSize
+        , std::size_t NodesPerBlock
+        >
+class shared_node_pool
+   :  public ipcdetail::shared_pool_impl
+      < private_node_pool
+         <SegmentManager, NodeSize, NodesPerBlock>
+      >
+{
+   typedef ipcdetail::shared_pool_impl
+      < private_node_pool
+         <SegmentManager, NodeSize, NodesPerBlock>
+      > base_t;
+   public:
+   shared_node_pool(SegmentManager *segment_mgnr)
+      : base_t(segment_mgnr)
+   {}
+};
+
+}  //namespace ipcdetail {
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP

+ 50 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/detail/node_tools.hpp

@@ -0,0 +1,50 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP
+#define BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/slist.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+
+template<class VoidPointer>
+struct node_slist
+{
+   //This hook will be used to chain the individual nodes
+    typedef typename bi::make_slist_base_hook
+      <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type slist_hook_t;
+
+   //A node object will hold node_t when it's not allocated
+   struct node_t
+      :  public slist_hook_t
+   {};
+
+   typedef typename bi::make_slist
+      <node_t, bi::linear<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
+};
+
+}  //namespace ipcdetail {
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP

+ 452 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/node_allocator.hpp

@@ -0,0 +1,452 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP
+#define BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/allocators/detail/node_pool.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/allocators/detail/allocator_common.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes node_allocator pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+namespace ipcdetail{
+
+template < unsigned int Version
+         , class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         >
+class node_allocator_base
+   : public node_pool_allocation_impl
+   < node_allocator_base
+      < Version, T, SegmentManager, NodesPerBlock>
+   , Version
+   , T
+   , SegmentManager
+   >
+{
+   public:
+   typedef typename SegmentManager::void_pointer         void_pointer;
+   typedef SegmentManager                                segment_manager;
+   typedef node_allocator_base
+      <Version, T, SegmentManager, NodesPerBlock>   self_t;
+
+   /// @cond
+
+   template <int dummy>
+   struct node_pool
+   {
+      typedef ipcdetail::shared_node_pool
+      < SegmentManager, sizeof_value<T>::value, NodesPerBlock> type;
+
+      static type *get(void *p)
+      {  return static_cast<type*>(p);  }
+   };
+   /// @endcond
+
+   BOOST_STATIC_ASSERT((Version <=2));
+
+   public:
+   //-------
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<T>::type                         pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const T>::type                   const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::difference_type     difference_type;
+
+   typedef boost::interprocess::version_type<node_allocator_base, Version>   version;
+   typedef boost::container::container_detail::transform_multiallocation_chain
+      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+   //!Obtains node_allocator_base from
+   //!node_allocator_base
+   template<class T2>
+   struct rebind
+   {
+      typedef node_allocator_base<Version, T2, SegmentManager, NodesPerBlock>       other;
+   };
+
+   /// @cond
+   private:
+   //!Not assignable from related node_allocator_base
+   template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2>
+   node_allocator_base& operator=
+      (const node_allocator_base<Version2, T2, SegmentManager2, N2>&);
+
+   //!Not assignable from other node_allocator_base
+   //node_allocator_base& operator=(const node_allocator_base&);
+   /// @endcond
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   node_allocator_base(segment_manager *segment_mngr)
+      : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
+
+   //!Copy constructor from other node_allocator_base. Increments the reference
+   //!count of the associated node pool. Never throws
+   node_allocator_base(const node_allocator_base &other)
+      : mp_node_pool(other.get_node_pool())
+   {
+      node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count();
+   }
+
+   //!Copy constructor from related node_allocator_base. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   node_allocator_base
+      (const node_allocator_base<Version, T2, SegmentManager, NodesPerBlock> &other)
+      : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
+
+   //!Assignment from other node_allocator_base
+   node_allocator_base& operator=(const node_allocator_base &other)
+   {
+      node_allocator_base c(other);
+      swap(*this, c);
+      return *this;
+   }
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~node_allocator_base()
+   {  ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool)));   }
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   void* get_node_pool() const
+   {  return ipcdetail::to_raw_pointer(mp_node_pool);   }
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const
+   {  return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager();  }
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2)
+   {  ipcdetail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool);  }
+
+   /// @cond
+   private:
+   void_pointer   mp_node_pool;
+   /// @endcond
+};
+
+//!Equality test for same type
+//!of node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator==(const node_allocator_base<V, T, S, NPC> &alloc1,
+                const node_allocator_base<V, T, S, NPC> &alloc2)
+   {  return alloc1.get_node_pool() == alloc2.get_node_pool(); }
+
+//!Inequality test for same type
+//!of node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator!=(const node_allocator_base<V, T, S, NPC> &alloc1,
+                const node_allocator_base<V, T, S, NPC> &alloc2)
+   {  return alloc1.get_node_pool() != alloc2.get_node_pool(); }
+
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock = 64
+         >
+class node_allocator_v1
+   :  public node_allocator_base
+         < 1
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         >
+{
+   public:
+   typedef ipcdetail::node_allocator_base
+         < 1, T, SegmentManager, NodesPerBlock> base_t;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef node_allocator_v1<T2, SegmentManager, NodesPerBlock>  other;
+   };
+
+   node_allocator_v1(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   node_allocator_v1
+      (const node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
+      : base_t(other)
+   {}
+};
+
+}  //namespace ipcdetail{
+
+/// @endcond
+
+//!An STL node allocator that uses a segment manager as memory
+//!source. The internal pointer type will of the same type (raw, smart) as
+//!"typename SegmentManager::void_pointer" type. This allows
+//!placing the allocator in shared memory, memory mapped-files, etc...
+//!This node allocator shares a segregated storage between all instances
+//!of node_allocator with equal sizeof(T) placed in the same segment
+//!group. NodesPerBlock is the number of nodes allocated at once when the allocator
+//!needs runs out of nodes
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         >
+class node_allocator
+   /// @cond
+   :  public ipcdetail::node_allocator_base
+         < 2
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         >
+   /// @endcond
+{
+
+   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   typedef ipcdetail::node_allocator_base
+         < 2, T, SegmentManager, NodesPerBlock> base_t;
+   public:
+   typedef boost::interprocess::version_type<node_allocator, 2>   version;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef node_allocator<T2, SegmentManager, NodesPerBlock>  other;
+   };
+
+   node_allocator(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   node_allocator
+      (const node_allocator<T2, SegmentManager, NodesPerBlock> &other)
+      : base_t(other)
+   {}
+
+   #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   public:
+   typedef implementation_defined::segment_manager       segment_manager;
+   typedef segment_manager::void_pointer                 void_pointer;
+   typedef implementation_defined::pointer               pointer;
+   typedef implementation_defined::const_pointer         const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::difference_type     difference_type;
+
+   //!Obtains node_allocator from
+   //!node_allocator
+   template<class T2>
+   struct rebind
+   {
+      typedef node_allocator<T2, SegmentManager, NodesPerBlock> other;
+   };
+
+   private:
+   //!Not assignable from
+   //!related node_allocator
+   template<class T2, class SegmentManager2, std::size_t N2>
+   node_allocator& operator=
+      (const node_allocator<T2, SegmentManager2, N2>&);
+
+   //!Not assignable from
+   //!other node_allocator
+   //node_allocator& operator=(const node_allocator&);
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   node_allocator(segment_manager *segment_mngr);
+
+   //!Copy constructor from other node_allocator. Increments the reference
+   //!count of the associated node pool. Never throws
+   node_allocator(const node_allocator &other);
+
+   //!Copy constructor from related node_allocator. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   node_allocator
+      (const node_allocator<T2, SegmentManager, NodesPerBlock> &other);
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~node_allocator();
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   void* get_node_pool() const;
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const;
+
+   //!Returns the number of elements that could be allocated.
+   //!Never throws
+   size_type max_size() const;
+
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0);
+
+   //!Deallocate allocated memory.
+   //!Never throws
+   void deallocate(const pointer &ptr, size_type count);
+
+   //!Deallocates all free blocks
+   //!of the pool
+   void deallocate_free_blocks();
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2);
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const;
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const;
+
+   //!Copy construct an object.
+   //!Throws if T's copy constructor throws
+   void construct(const pointer &ptr, const_reference v);
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr);
+
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const;
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain);
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one();
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements);
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p);
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain chain);
+   #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of node_allocator
+template<class T, class S, std::size_t NPC> inline
+bool operator==(const node_allocator<T, S, NPC> &alloc1,
+                const node_allocator<T, S, NPC> &alloc2);
+
+//!Inequality test for same type
+//!of node_allocator
+template<class T, class S, std::size_t NPC> inline
+bool operator!=(const node_allocator<T, S, NPC> &alloc1,
+                const node_allocator<T, S, NPC> &alloc2);
+
+#endif
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP

+ 468 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/private_adaptive_pool.hpp

@@ -0,0 +1,468 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
+#define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+namespace ipcdetail {
+
+template < unsigned int Version
+         , class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         , std::size_t MaxFreeBlocks
+         , unsigned char OverheadPercent
+         >
+class private_adaptive_pool_base
+   : public node_pool_allocation_impl
+   < private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock
+                                , MaxFreeBlocks, OverheadPercent>
+   , Version
+   , T
+   , SegmentManager
+   >
+{
+   public:
+   //Segment manager
+   typedef SegmentManager                                segment_manager;
+   typedef typename SegmentManager::void_pointer         void_pointer;
+
+   /// @cond
+   private:
+   typedef private_adaptive_pool_base
+      < Version, T, SegmentManager, NodesPerBlock
+      , MaxFreeBlocks, OverheadPercent>                  self_t;
+   typedef ipcdetail::private_adaptive_node_pool
+      <SegmentManager
+      , sizeof_value<T>::value
+      , NodesPerBlock
+      , MaxFreeBlocks
+      , OverheadPercent
+      > node_pool_t;
+
+   BOOST_STATIC_ASSERT((Version <=2));
+
+   /// @endcond
+
+   public:
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<T>::type                         pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const T>::type                   const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::size_type           difference_type;
+   typedef boost::interprocess::version_type
+      <private_adaptive_pool_base, Version>              version;
+   typedef boost::container::container_detail::transform_multiallocation_chain
+      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+   //!Obtains node_allocator from other node_allocator
+   template<class T2>
+   struct rebind
+   {
+      typedef private_adaptive_pool_base
+         <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>   other;
+   };
+
+   /// @cond
+
+   template <int dummy>
+   struct node_pool
+   {
+      typedef ipcdetail::private_adaptive_node_pool
+      <SegmentManager
+      , sizeof_value<T>::value
+      , NodesPerBlock
+      , MaxFreeBlocks
+      , OverheadPercent
+      > type;
+
+      static type *get(void *p)
+      {  return static_cast<type*>(p);  }
+   };
+
+   private:
+   //!Not assignable from related private_adaptive_pool_base
+   template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2, std::size_t F2, unsigned char OP2>
+   private_adaptive_pool_base& operator=
+      (const private_adaptive_pool_base<Version2, T2, MemoryAlgorithm2, N2, F2, OP2>&);
+
+   //!Not assignable from other private_adaptive_pool_base
+   private_adaptive_pool_base& operator=(const private_adaptive_pool_base&);
+   /// @endcond
+
+   public:
+   //!Constructor from a segment manager
+   private_adaptive_pool_base(segment_manager *segment_mngr)
+      : m_node_pool(segment_mngr)
+   {}
+
+   //!Copy constructor from other private_adaptive_pool_base. Never throws
+   private_adaptive_pool_base(const private_adaptive_pool_base &other)
+      : m_node_pool(other.get_segment_manager())
+   {}
+
+   //!Copy constructor from related private_adaptive_pool_base. Never throws.
+   template<class T2>
+   private_adaptive_pool_base
+      (const private_adaptive_pool_base
+         <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : m_node_pool(other.get_segment_manager())
+   {}
+
+   //!Destructor, frees all used memory. Never throws
+   ~private_adaptive_pool_base()
+   {}
+
+   //!Returns the segment manager. Never throws
+   segment_manager* get_segment_manager()const
+   {  return m_node_pool.get_segment_manager(); }
+
+   //!Returns the internal node pool. Never throws
+   node_pool_t* get_node_pool() const
+   {  return const_cast<node_pool_t*>(&m_node_pool); }
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different shared memory segments, the result is undefined.
+   friend void swap(self_t &alloc1,self_t &alloc2)
+   {  alloc1.m_node_pool.swap(alloc2.m_node_pool);  }
+
+   /// @cond
+   private:
+   node_pool_t m_node_pool;
+   /// @endcond
+};
+
+//!Equality test for same type of private_adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
+                const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
+{  return &alloc1 == &alloc2; }
+
+//!Inequality test for same type of private_adaptive_pool_base
+template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
+                const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
+{  return &alloc1 != &alloc2; }
+
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock = 64
+         , std::size_t MaxFreeBlocks = 2
+         , unsigned char OverheadPercent = 5
+         >
+class private_adaptive_pool_v1
+   :  public private_adaptive_pool_base
+         < 1
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         , MaxFreeBlocks
+         , OverheadPercent
+         >
+{
+   public:
+   typedef ipcdetail::private_adaptive_pool_base
+         < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
+   };
+
+   private_adaptive_pool_v1(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   private_adaptive_pool_v1
+      (const private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : base_t(other)
+   {}
+};
+
+}  //namespace ipcdetail {
+
+/// @endcond
+
+//!An STL node allocator that uses a segment manager as memory
+//!source. The internal pointer type will of the same type (raw, smart) as
+//!"typename SegmentManager::void_pointer" type. This allows
+//!placing the allocator in shared memory, memory mapped-files, etc...
+//!This allocator has its own node pool.
+//!
+//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when
+//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
+//!that the adaptive node pool will hold. The rest of the totally free blocks will be
+//!deallocated with the segment manager.
+//!
+//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
+//!(memory usable for nodes / total memory allocated from the segment manager)
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         , std::size_t MaxFreeBlocks
+         , unsigned char OverheadPercent
+         >
+class private_adaptive_pool
+   /// @cond
+   :  public ipcdetail::private_adaptive_pool_base
+         < 2
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         , MaxFreeBlocks
+         , OverheadPercent
+         >
+   /// @endcond
+{
+
+   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   typedef ipcdetail::private_adaptive_pool_base
+         < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
+   public:
+   typedef boost::interprocess::version_type<private_adaptive_pool, 2>   version;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef private_adaptive_pool
+         <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
+   };
+
+   private_adaptive_pool(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   private_adaptive_pool
+      (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
+      : base_t(other)
+   {}
+
+   #else
+   public:
+   typedef implementation_defined::segment_manager       segment_manager;
+   typedef segment_manager::void_pointer                 void_pointer;
+   typedef implementation_defined::pointer               pointer;
+   typedef implementation_defined::const_pointer         const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::difference_type     difference_type;
+
+   //!Obtains private_adaptive_pool from
+   //!private_adaptive_pool
+   template<class T2>
+   struct rebind
+   {
+      typedef private_adaptive_pool
+         <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
+   };
+
+   private:
+   //!Not assignable from
+   //!related private_adaptive_pool
+   template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
+   private_adaptive_pool& operator=
+      (const private_adaptive_pool<T2, SegmentManager2, N2, F2>&);
+
+   //!Not assignable from
+   //!other private_adaptive_pool
+   private_adaptive_pool& operator=(const private_adaptive_pool&);
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   private_adaptive_pool(segment_manager *segment_mngr);
+
+   //!Copy constructor from other private_adaptive_pool. Increments the reference
+   //!count of the associated node pool. Never throws
+   private_adaptive_pool(const private_adaptive_pool &other);
+
+   //!Copy constructor from related private_adaptive_pool. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   private_adaptive_pool
+      (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~private_adaptive_pool();
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   node_pool_t* get_node_pool() const;
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const;
+
+   //!Returns the number of elements that could be allocated.
+   //!Never throws
+   size_type max_size() const;
+
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0);
+
+   //!Deallocate allocated memory.
+   //!Never throws
+   void deallocate(const pointer &ptr, size_type count);
+
+   //!Deallocates all free blocks
+   //!of the pool
+   void deallocate_free_blocks();
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2);
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const;
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const;
+
+   //!Copy construct an object.
+   //!Throws if T's copy constructor throws
+   void construct(const pointer &ptr, const_reference v);
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr);
+
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const;
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain);
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one();
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements);
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p);
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain chain);
+   #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of private_adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+                const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of private_adaptive_pool
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
+                const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
+

+ 445 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/allocators/private_node_allocator.hpp

@@ -0,0 +1,445 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
+#define BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/interprocess/allocators/detail/node_pool.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+//!\file
+//!Describes private_node_allocator_base pooled shared memory STL compatible allocator
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+namespace ipcdetail {
+
+template < unsigned int Version
+         , class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         >
+class private_node_allocator_base
+   : public node_pool_allocation_impl
+   < private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock>
+   , Version
+   , T
+   , SegmentManager
+   >
+{
+   public:
+   //Segment manager
+   typedef SegmentManager                                segment_manager;
+   typedef typename SegmentManager::void_pointer         void_pointer;
+
+   /// @cond
+   private:
+   typedef private_node_allocator_base
+      < Version, T, SegmentManager, NodesPerBlock>       self_t;
+   typedef ipcdetail::private_node_pool
+      <SegmentManager
+      , sizeof_value<T>::value
+      , NodesPerBlock
+      > node_pool_t;
+
+   BOOST_STATIC_ASSERT((Version <=2));
+
+   /// @endcond
+
+   public:
+
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<T>::type                         pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<const T>::type                   const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manager::difference_type     difference_type;
+   typedef boost::interprocess::version_type
+      <private_node_allocator_base, Version>              version;
+   typedef boost::container::container_detail::transform_multiallocation_chain
+      <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
+
+   //!Obtains node_allocator from other node_allocator
+   template<class T2>
+   struct rebind
+   {
+      typedef private_node_allocator_base
+         <Version, T2, SegmentManager, NodesPerBlock>   other;
+   };
+
+   /// @cond
+   template <int dummy>
+   struct node_pool
+   {
+      typedef ipcdetail::private_node_pool
+      <SegmentManager
+      , sizeof_value<T>::value
+      , NodesPerBlock
+      > type;
+
+      static type *get(void *p)
+      {  return static_cast<type*>(p);  }
+   };
+
+   private:
+   //!Not assignable from related private_node_allocator_base
+   template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2>
+   private_node_allocator_base& operator=
+      (const private_node_allocator_base<Version2, T2, MemoryAlgorithm2, N2>&);
+
+   //!Not assignable from other private_node_allocator_base
+   private_node_allocator_base& operator=(const private_node_allocator_base&);
+   /// @endcond
+
+   public:
+   //!Constructor from a segment manager
+   private_node_allocator_base(segment_manager *segment_mngr)
+      : m_node_pool(segment_mngr)
+   {}
+
+   //!Copy constructor from other private_node_allocator_base. Never throws
+   private_node_allocator_base(const private_node_allocator_base &other)
+      : m_node_pool(other.get_segment_manager())
+   {}
+
+   //!Copy constructor from related private_node_allocator_base. Never throws.
+   template<class T2>
+   private_node_allocator_base
+      (const private_node_allocator_base
+         <Version, T2, SegmentManager, NodesPerBlock> &other)
+      : m_node_pool(other.get_segment_manager())
+   {}
+
+   //!Destructor, frees all used memory. Never throws
+   ~private_node_allocator_base()
+   {}
+
+   //!Returns the segment manager. Never throws
+   segment_manager* get_segment_manager()const
+   {  return m_node_pool.get_segment_manager(); }
+
+   //!Returns the internal node pool. Never throws
+   node_pool_t* get_node_pool() const
+   {  return const_cast<node_pool_t*>(&m_node_pool); }
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different shared memory segments, the result is undefined.
+   friend void swap(self_t &alloc1,self_t &alloc2)
+   {  alloc1.m_node_pool.swap(alloc2.m_node_pool);  }
+
+   /// @cond
+   private:
+   node_pool_t m_node_pool;
+   /// @endcond
+};
+
+//!Equality test for same type of private_node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator==(const private_node_allocator_base<V, T, S, NPC> &alloc1,
+                const private_node_allocator_base<V, T, S, NPC> &alloc2)
+{  return &alloc1 == &alloc2; }
+
+//!Inequality test for same type of private_node_allocator_base
+template<unsigned int V, class T, class S, std::size_t NPC> inline
+bool operator!=(const private_node_allocator_base<V, T, S, NPC> &alloc1,
+                const private_node_allocator_base<V, T, S, NPC> &alloc2)
+{  return &alloc1 != &alloc2; }
+
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock = 64
+         >
+class private_node_allocator_v1
+   :  public private_node_allocator_base
+         < 1
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         >
+{
+   public:
+   typedef ipcdetail::private_node_allocator_base
+         < 1, T, SegmentManager, NodesPerBlock> base_t;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef private_node_allocator_v1<T2, SegmentManager, NodesPerBlock>  other;
+   };
+
+   private_node_allocator_v1(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   private_node_allocator_v1
+      (const private_node_allocator_v1<T2, SegmentManager, NodesPerBlock> &other)
+      : base_t(other)
+   {}
+};
+
+}  //namespace ipcdetail {
+
+/// @endcond
+
+//!An STL node allocator that uses a segment manager as memory
+//!source. The internal pointer type will of the same type (raw, smart) as
+//!"typename SegmentManager::void_pointer" type. This allows
+//!placing the allocator in shared memory, memory mapped-files, etc...
+//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated
+//!at once when the allocator needs runs out of nodes
+template < class T
+         , class SegmentManager
+         , std::size_t NodesPerBlock
+         >
+class private_node_allocator
+   /// @cond
+   :  public ipcdetail::private_node_allocator_base
+         < 2
+         , T
+         , SegmentManager
+         , NodesPerBlock
+         >
+   /// @endcond
+{
+
+   #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+   typedef ipcdetail::private_node_allocator_base
+         < 2, T, SegmentManager, NodesPerBlock> base_t;
+   public:
+   typedef boost::interprocess::version_type<private_node_allocator, 2>   version;
+
+   template<class T2>
+   struct rebind
+   {
+      typedef private_node_allocator
+         <T2, SegmentManager, NodesPerBlock>  other;
+   };
+
+   private_node_allocator(SegmentManager *segment_mngr)
+      : base_t(segment_mngr)
+   {}
+
+   template<class T2>
+   private_node_allocator
+      (const private_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
+      : base_t(other)
+   {}
+
+   #else
+   public:
+   typedef implementation_defined::segment_manager       segment_manager;
+   typedef segment_manager::void_pointer                 void_pointer;
+   typedef implementation_defined::pointer               pointer;
+   typedef implementation_defined::const_pointer         const_pointer;
+   typedef T                                             value_type;
+   typedef typename ipcdetail::add_reference
+                     <value_type>::type                  reference;
+   typedef typename ipcdetail::add_reference
+                     <const value_type>::type            const_reference;
+   typedef typename segment_manager::size_type           size_type;
+   typedef typename segment_manage::difference_type      difference_type;
+
+   //!Obtains private_node_allocator from
+   //!private_node_allocator
+   template<class T2>
+   struct rebind
+   {
+      typedef private_node_allocator
+         <T2, SegmentManager, NodesPerBlock> other;
+   };
+
+   private:
+   //!Not assignable from
+   //!related private_node_allocator
+   template<class T2, class SegmentManager2, std::size_t N2>
+   private_node_allocator& operator=
+      (const private_node_allocator<T2, SegmentManager2, N2>&);
+
+   //!Not assignable from
+   //!other private_node_allocator
+   private_node_allocator& operator=(const private_node_allocator&);
+
+   public:
+   //!Constructor from a segment manager. If not present, constructs a node
+   //!pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   private_node_allocator(segment_manager *segment_mngr);
+
+   //!Copy constructor from other private_node_allocator. Increments the reference
+   //!count of the associated node pool. Never throws
+   private_node_allocator(const private_node_allocator &other);
+
+   //!Copy constructor from related private_node_allocator. If not present, constructs
+   //!a node pool. Increments the reference count of the associated node pool.
+   //!Can throw boost::interprocess::bad_alloc
+   template<class T2>
+   private_node_allocator
+      (const private_node_allocator<T2, SegmentManager, NodesPerBlock> &other);
+
+   //!Destructor, removes node_pool_t from memory
+   //!if its reference count reaches to zero. Never throws
+   ~private_node_allocator();
+
+   //!Returns a pointer to the node pool.
+   //!Never throws
+   node_pool_t* get_node_pool() const;
+
+   //!Returns the segment manager.
+   //!Never throws
+   segment_manager* get_segment_manager()const;
+
+   //!Returns the number of elements that could be allocated.
+   //!Never throws
+   size_type max_size() const;
+
+   //!Allocate memory for an array of count elements.
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate(size_type count, cvoid_pointer hint = 0);
+
+   //!Deallocate allocated memory.
+   //!Never throws
+   void deallocate(const pointer &ptr, size_type count);
+
+   //!Deallocates all free blocks
+   //!of the pool
+   void deallocate_free_blocks();
+
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different memory segment, the result is undefined.
+   friend void swap(self_t &alloc1, self_t &alloc2);
+
+   //!Returns address of mutable object.
+   //!Never throws
+   pointer address(reference value) const;
+
+   //!Returns address of non mutable object.
+   //!Never throws
+   const_pointer address(const_reference value) const;
+
+   //!Copy construct an object.
+   //!Throws if T's copy constructor throws
+   void construct(const pointer &ptr, const_reference v);
+
+   //!Destroys object. Throws if object's
+   //!destructor throws
+   void destroy(const pointer &ptr);
+
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold. This size only works for memory allocated with
+   //!allocate, allocation_command and allocate_many.
+   size_type size(const pointer &p) const;
+
+   std::pair<pointer, bool>
+      allocation_command(boost::interprocess::allocation_type command,
+                         size_type limit_size,
+                         size_type preferred_size,
+                         size_type &received_size, const pointer &reuse = 0);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   multiallocation_chain allocate_many(size_type elem_size, size_type num_elements);
+
+   //!Allocates n_elements elements, each one of size elem_sizes[i]in a
+   //!contiguous block
+   //!of memory. The elements must be deallocated
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements);
+
+   //!Allocates many elements of size elem_size in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. The elements must be deallocated
+   //!with deallocate(...)
+   void deallocate_many(multiallocation_chain chain);
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
+   pointer allocate_one();
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   multiallocation_chain allocate_individual(size_type num_elements);
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p);
+
+   //!Allocates many elements of size == 1 in a contiguous block
+   //!of memory. The minimum number to be allocated is min_elements,
+   //!the preferred and maximum number is
+   //!preferred_elements. The number of actually allocated elements is
+   //!will be assigned to received_size. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   void deallocate_individual(multiallocation_chain chain);
+   #endif
+};
+
+#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
+
+//!Equality test for same type
+//!of private_node_allocator
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator==(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1,
+                const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
+
+//!Inequality test for same type
+//!of private_node_allocator
+template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
+bool operator!=(const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc1,
+                const private_node_allocator<T, S, NodesPerBlock, F, OP> &alloc2);
+
+#endif
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP
+

+ 117 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/anonymous_shared_memory.hpp

@@ -0,0 +1,117 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP
+#define BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#include <cstddef>
+
+#if (!defined(BOOST_INTERPROCESS_WINDOWS))
+#  include <fcntl.h>        //open, O_CREAT, O_*...
+#  include <sys/mman.h>     //mmap
+#  include <sys/stat.h>     //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
+#else
+#include <boost/interprocess/windows_shared_memory.hpp>
+#endif
+
+
+//!\file
+//!Describes a function that creates anonymous shared memory that can be
+//!shared between forked processes
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+namespace ipcdetail{
+
+   class raw_mapped_region_creator
+   {
+      public:
+      static mapped_region
+         create_posix_mapped_region(void *address, std::size_t size)
+      {
+         mapped_region region;
+         region.m_base = address;
+         region.m_size = size;
+         return region;
+      }
+   };
+}
+
+/// @endcond
+
+//!A function that creates an anonymous shared memory segment of size "size".
+//!If "address" is passed the function will try to map the segment in that address.
+//!Otherwise the operating system will choose the mapping address.
+//!The function returns a mapped_region holding that segment or throws
+//!interprocess_exception if the function fails.
+//static mapped_region
+static mapped_region
+anonymous_shared_memory(std::size_t size, void *address = 0)
+#if (!defined(BOOST_INTERPROCESS_WINDOWS))
+{
+   int flags;
+   int fd = -1;
+
+   #if defined(MAP_ANONYMOUS) //Use MAP_ANONYMOUS
+   flags = MAP_ANONYMOUS | MAP_SHARED;
+   #elif !defined(MAP_ANONYMOUS) && defined(MAP_ANON) //use MAP_ANON
+   flags = MAP_ANON | MAP_SHARED;
+   #else // Use "/dev/zero"
+   fd = open("/dev/zero", O_RDWR);
+   flags = MAP_SHARED;
+   if(fd == -1){
+      error_info err = system_error_code();
+      throw interprocess_exception(err);
+   }
+   #endif
+
+
+   address = mmap( address
+                  , size
+                  , PROT_READ|PROT_WRITE
+                  , flags
+                  , fd
+                  , 0);
+
+   if(address == MAP_FAILED){
+      if(fd != -1)
+         close(fd);
+      error_info err = system_error_code();
+      throw interprocess_exception(err);
+   }
+
+   if(fd != -1)
+      close(fd);
+
+   return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size);
+}
+#else
+{
+   windows_shared_memory anonymous_mapping(create_only, 0, read_write, size);
+   return mapped_region(anonymous_mapping, read_write, 0, size, address);
+}
+
+#endif
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP

+ 40 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/allocation_type.hpp

@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_ALLOCATION_TYPE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+typedef int allocation_type;
+/// @endcond
+static const allocation_type allocate_new       = boost::container::allocate_new;
+static const allocation_type expand_fwd         = boost::container::expand_fwd;
+static const allocation_type expand_bwd         = boost::container::expand_bwd;
+static const allocation_type shrink_in_place    = boost::container::shrink_in_place;
+static const allocation_type try_shrink_in_place= boost::container::try_shrink_in_place;
+static const allocation_type nothrow_allocation = boost::container::nothrow_allocation;
+static const allocation_type zero_memory        = boost::container::zero_memory;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP

+ 40 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/containers_fwd.hpp

@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP
+
+/// @cond
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//                        Standard predeclarations
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/container_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::ordered_range;
+using boost::container::ordered_unique_range;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+/// @endcond
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_CONTAINERS_FWD_HPP

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/deque.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::deque;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_DEQUE_HPP
+

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/flat_map.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::flat_map;
+using boost::container::flat_multimap;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_FLAT_MAP_HPP

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/flat_set.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::flat_set;
+using boost::container::flat_multiset;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_FLAT_SET_HPP

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/list.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/list.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::list;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_LIST_HPP
+

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/map.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_MAP_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_MAP_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/map.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::map;
+using boost::container::multimap;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_MAP_HPP

+ 34 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/pair.hpp

@@ -0,0 +1,34 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/detail/pair.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::container_detail::pair;
+using boost::container::container_detail::piecewise_construct;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_PAIR_HPP
+

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/set.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_SET_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_SET_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/set.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::set;
+using boost::container::multiset;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_SET_HPP

+ 32 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/slist.hpp

@@ -0,0 +1,32 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::slist;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_SLIST_HPP

+ 32 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/stable_vector.hpp

@@ -0,0 +1,32 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+   namespace interprocess {
+
+      using boost::container::stable_vector;
+
+   }  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_STABLE_VECTOR_HPP

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/string.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_STRING_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_STRING_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/string.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::basic_string;
+using boost::container::string;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_STRING_HPP

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/vector.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/interprocess/containers/containers_fwd.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::vector;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_VECTOR_HPP
+

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/containers/version_type.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
+#define BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using boost::container::container_detail::version_type;
+using boost::container::container_detail::version;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //   #ifndef  BOOST_INTERPROCESS_CONTAINERS_VERSION_TYPE_HPP
+

+ 77 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/creation_tags.hpp

@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP
+#define BOOST_INTERPROCESS_CREATION_TAGS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+namespace boost {
+namespace interprocess {
+
+//!Tag to indicate that the resource must
+//!be only created
+struct create_only_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened
+struct open_only_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened for reading
+struct open_read_only_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened privately for reading
+struct open_read_private_t {};
+
+//!Tag to indicate that the resource must
+//!be only opened for reading
+struct open_copy_on_write_t {};
+
+//!Tag to indicate that the resource must
+//!be created. If already created, it must be opened.
+struct open_or_create_t {};
+
+//!Value to indicate that the resource must
+//!be only created
+static const create_only_t    create_only    = create_only_t();
+
+//!Value to indicate that the resource must
+//!be only opened
+static const open_only_t      open_only      = open_only_t();
+
+//!Value to indicate that the resource must
+//!be only opened for reading
+static const open_read_only_t open_read_only = open_read_only_t();
+
+//!Value to indicate that the resource must
+//!be created. If already created, it must be opened.
+static const open_or_create_t open_or_create = open_or_create_t();
+
+//!Value to indicate that the resource must
+//!be only opened for reading
+static const open_copy_on_write_t open_copy_on_write = open_copy_on_write_t();
+
+namespace ipcdetail {
+
+enum create_enum_t
+{  DoCreate, DoOpen, DoOpenOrCreate   };
+
+}  //namespace ipcdetail {
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP
+

+ 562 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/atomic.hpp

@@ -0,0 +1,562 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2012
+// (C) Copyright Markus Schoepflin 2007
+// (C) Copyright Bryce Lelbach 2010
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
+#define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically increment an boost::uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem);
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem);
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val);
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with": what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+   (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp);
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+#include <boost/interprocess/detail/win32_api.hpp>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{  return winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1;  }
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{  return winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1;  }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{  return *mem;   }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{  winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val);  }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with": what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+   (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{  return winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp);  }
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+   (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+   boost::uint32_t prev = cmp;
+   // This version by Mans Rullgard of Pathscale
+   __asm__ __volatile__ ( "lock\n\t"
+                          "cmpxchg %2,%0"
+                        : "+m"(*mem), "+a"(prev)
+                        : "r"(with)
+                        : "cc");
+
+   return prev;
+}
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32
+   (volatile boost::uint32_t *mem, boost::uint32_t val)
+{
+   // int r = *pw;
+   // *mem += val;
+   // return r;
+   int r;
+
+   asm volatile
+   (
+      "lock\n\t"
+      "xadd %1, %0":
+      "+m"( *mem ), "=r"( r ): // outputs (%0, %1)
+      "1"( val ): // inputs (%2 == %1)
+      "memory", "cc" // clobbers
+   );
+
+   return r;
+}
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, 1);  }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, (boost::uint32_t)-1);  }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{  return *mem;   }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{  *mem = val; }
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{
+   boost::uint32_t prev, temp;
+
+   asm volatile ("1:\n\t"
+                 "lwarx  %0,0,%2\n\t"
+                 "add    %1,%0,%3\n\t"
+                 "stwcx. %1,0,%2\n\t"
+                 "bne-   1b"
+                 : "=&r" (prev), "=&r" (temp)
+                 : "b" (mem), "r" (val)
+                 : "cc", "memory");
+   return prev;
+}
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+   (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+   boost::uint32_t prev;
+
+   asm volatile ("1:\n\t"
+                 "lwarx  %0,0,%1\n\t"
+                 "cmpw   %0,%3\n\t"
+                 "bne-   2f\n\t"
+                 "stwcx. %2,0,%1\n\t"
+                 "bne-   1b\n\t"
+                 "2:"
+                 : "=&r"(prev)
+                 : "b" (mem), "r"(cmp), "r" (with)
+                 : "cc", "memory");
+   return prev;
+}
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, 1);  }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, boost::uint32_t(-1u));  }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{  return *mem;   }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{  *mem = val; }
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#elif (defined(sun) || defined(__sun))
+
+#include <atomic.h>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{   return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (int32_t)val) - val;   }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+   (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{  return atomic_cas_32(reinterpret_cast<volatile ::uint32_t*>(mem), cmp, with);  }
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{  return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), 1) - 1; }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{  return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (boost::uint32_t)-1) + 1; }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{  return *mem;   }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{  *mem = val; }
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#elif defined(__osf__) && defined(__DECCXX)
+
+#include <machine/builtins.h>
+#include <c_asm.h>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//! Atomically decrement a uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+//! Acquire, memory barrier after decrement.
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{  boost::uint32_t old_val = __ATOMIC_DECREMENT_LONG(mem); __MB(); return old_val; }
+
+//! Atomically increment a uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+//! Release, memory barrier before increment.
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{  __MB(); return __ATOMIC_INCREMENT_LONG(mem); }
+
+// Rational for the implementation of the atomic read and write functions.
+//
+// 1. The Alpha Architecture Handbook requires that access to a byte,
+// an aligned word, an aligned longword, or an aligned quadword is
+// atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.)
+//
+// 2. The CXX User's Guide states that volatile quantities are accessed
+// with single assembler instructions, and that a compilation error
+// occurs when declaring a quantity as volatile which is not properly
+// aligned.
+
+//! Atomically read an boost::uint32_t from memory
+//! Acquire, memory barrier after load.
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{  boost::uint32_t old_val = *mem; __MB(); return old_val;  }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+//! Release, memory barrier before store.
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{  __MB(); *mem = val; }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+//! Memory barrier between load and store.
+inline boost::uint32_t atomic_cas32(
+  volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+  // Note:
+  //
+  // Branch prediction prefers backward branches, and the Alpha Architecture
+  // Handbook explicitely states that the loop should not be implemented like
+  // it is below. (See chapter 4.2.5.) Therefore the code should probably look
+  // like this:
+  //
+  // return asm(
+  //   "10: ldl_l %v0,(%a0) ;"
+  //   "    cmpeq %v0,%a2,%t0 ;"
+  //   "    beq %t0,20f ;"
+  //   "    mb ;"
+  //   "    mov %a1,%t0 ;"
+  //   "    stl_c %t0,(%a0) ;"
+  //   "    beq %t0,30f ;"
+  //   "20: ret ;"
+  //   "30: br 10b;",
+  //   mem, with, cmp);
+  //
+  // But as the compiler always transforms this into the form where a backward
+  // branch is taken on failure, we can as well implement it in the straight
+  // forward form, as this is what it will end up in anyway.
+
+  return asm(
+    "10: ldl_l %v0,(%a0) ;"    // load prev value from mem and lock mem
+    "    cmpeq %v0,%a2,%t0 ;"  // compare with given value
+    "    beq %t0,20f ;"        // if not equal, we're done
+    "    mb ;"                 // memory barrier
+    "    mov %a1,%t0 ;"        // load new value into scratch register
+    "    stl_c %t0,(%a0) ;"    // store new value to locked mem (overwriting scratch)
+    "    beq %t0,10b ;"        // store failed because lock has been stolen, retry
+    "20: ",
+    mem, with, cmp);
+}
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX)
+
+#include <builtins.h>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting
+//all the functions with casts
+
+//! From XLC documenation :
+//! This function can be used with a subsequent stwcxu call to implement a
+//! read-modify-write on a specified memory location. The two functions work
+//! together to ensure that if the store is successfully performed, no other
+//! processor or mechanism can modify the target doubleword between the time
+//! lwarxu function is executed and the time the stwcxu functio ncompletes.
+//! "mem" : pointer to the object
+//! Returns the value at pointed to by mem
+inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem)
+{
+   return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem)));
+}
+
+//! "mem" : pointer to the object
+//! "val" : the value to store
+//! Returns true if the update of mem is successful and false if it is
+//!unsuccessful
+inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val)
+{
+   return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0);
+}
+
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32
+   (volatile boost::uint32_t *mem, boost::uint32_t val)
+{
+   boost::uint32_t oldValue;
+   do
+   {
+      oldValue = lwarxu(mem);
+   }while (!stwcxu(mem, oldValue+val));
+   return oldValue;
+}
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, 1);  }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, (boost::uint32_t)-1);   }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{  return *mem;   }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+   (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{
+   boost::uint32_t oldValue;
+   boost::uint32_t valueToStore;
+   do
+   {
+      oldValue = lwarxu(mem);
+   } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue));
+
+   return oldValue;
+}
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{  *mem = val; }
+
+}  //namespace ipcdetail
+}  //namespace interprocess
+}  //namespace boost
+
+#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//! Atomically add 'val' to an boost::uint32_t
+//! "mem": pointer to the object
+//! "val": amount to add
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_add32
+   (volatile boost::uint32_t *mem, boost::uint32_t val)
+{  return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val);   }
+
+//! Atomically increment an apr_uint32_t by 1
+//! "mem": pointer to the object
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, 1);  }
+
+//! Atomically decrement an boost::uint32_t by 1
+//! "mem": pointer to the atomic value
+//! Returns the old value pointed to by mem
+inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
+{  return atomic_add32(mem, (boost::uint32_t)-1);   }
+
+//! Atomically read an boost::uint32_t from memory
+inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
+{  return *mem;   }
+
+//! Compare an boost::uint32_t's value with "cmp".
+//! If they are the same swap the value with "with"
+//! "mem": pointer to the value
+//! "with" what to swap it with
+//! "cmp": the value to compare it to
+//! Returns the old value of *mem
+inline boost::uint32_t atomic_cas32
+   (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
+{  return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with);   }
+
+//! Atomically set an boost::uint32_t in memory
+//! "mem": pointer to the object
+//! "param": val value that the object will assume
+inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
+{  *mem = val; }
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#else
+
+#error No atomic operations implemented for this platform, sorry!
+
+#endif
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+inline bool atomic_add_unless32
+   (volatile boost::uint32_t *mem, boost::uint32_t value, boost::uint32_t unless_this)
+{
+   boost::uint32_t old, c(atomic_read32(mem));
+   while(c != unless_this && (old = atomic_cas32(mem, c + value, c)) != c){
+      c = old;
+   }
+   return c != unless_this;
+}
+
+}  //namespace ipcdetail
+}  //namespace interprocess
+}  //namespace boost
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP

+ 29 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/cast_tags.hpp

@@ -0,0 +1,29 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
+#define BOOST_INTERPROCESS_CAST_TAGS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+namespace boost { namespace interprocess { namespace ipcdetail {
+
+struct static_cast_tag {};
+struct const_cast_tag {};
+struct dynamic_cast_tag {};
+struct reinterpret_cast_tag {};
+
+}}}  //namespace boost { namespace interprocess { namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
+

+ 48 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/config_begin.hpp

@@ -0,0 +1,48 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_INTERPROCESS_CONFIG_INCLUDED
+#define BOOST_INTERPROCESS_CONFIG_INCLUDED
+#include <boost/config.hpp>
+#endif
+
+#ifdef BOOST_MSVC
+   #ifndef _CRT_SECURE_NO_DEPRECATE
+   #define  BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
+   #define _CRT_SECURE_NO_DEPRECATE
+   #endif
+   #pragma warning (push)
+   #pragma warning (disable : 4702) // unreachable code
+   #pragma warning (disable : 4706) // assignment within conditional expression
+   #pragma warning (disable : 4127) // conditional expression is constant
+   #pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
+   #pragma warning (disable : 4284) // odd return type for operator->
+   #pragma warning (disable : 4244) // possible loss of data
+   #pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
+   #pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
+   #pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
+   #pragma warning (disable : 4355) // "this" : used in base member initializer list
+   #pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
+   #pragma warning (disable : 4511) // copy constructor could not be generated
+   #pragma warning (disable : 4512) // assignment operator could not be generated
+   #pragma warning (disable : 4514) // unreferenced inline removed
+   #pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
+   #pragma warning (disable : 4522) // "class" : multiple assignment operators specified
+   #pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
+   #pragma warning (disable : 4710) // function not inlined
+   #pragma warning (disable : 4711) // function selected for automatic inline expansion
+   #pragma warning (disable : 4786) // identifier truncated in debug info
+   #pragma warning (disable : 4996) // "function": was declared deprecated
+   #pragma warning (disable : 4197) // top-level volatile in cast is ignored
+   #pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
+                                    //    with /GR-; unpredictable behavior may result
+   #pragma warning (disable : 4673) //  throwing '' the following types will not be considered at the catch site
+   #pragma warning (disable : 4671) //  the copy constructor is inaccessible
+   #pragma warning (disable : 4250) //  inherits 'x' via dominance
+#endif

+ 17 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/config_end.hpp

@@ -0,0 +1,17 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#if defined BOOST_MSVC
+   #pragma warning (pop)
+   #ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
+   #undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
+   #undef _CRT_SECURE_NO_DEPRECATE
+   #endif
+#endif
+

+ 298 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/file_locking_helpers.hpp

@@ -0,0 +1,298 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
+#define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <sstream>
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <cstddef>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+#include <fcntl.h>
+#include <io.h>
+#include <sys/locking.h>
+
+#else //defined(BOOST_INTERPROCESS_WINDOWS)
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#endif   //defined(BOOST_INTERPROCESS_WINDOWS)
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+
+struct locking_file_serial_id
+{
+   int fd;
+   unsigned long dwVolumeSerialNumber;
+   unsigned long nFileIndexHigh;
+   unsigned long nFileIndexLow;
+   //This reference count counts the number of modules attached
+   //to the shared memory and lock file. This serves to unlink
+   //the locking file and shared memory when all modules are
+   //done with the global memory (shared memory)
+   volatile boost::uint32_t modules_attached_to_gmem_count;
+};
+
+inline bool lock_locking_file(int fd)
+{
+   int ret = 0;
+   while(ret != 0 && errno == EDEADLK){
+      ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/);
+   }
+   return 0 == ret;
+}
+
+inline bool try_lock_locking_file(int fd)
+{
+   return 0 == _locking(fd, _LK_NBLCK , 1);
+}
+
+inline int open_or_create_and_lock_file(const char *name)
+{
+   permissions p;
+   p.set_unrestricted();
+   while(1){
+      file_handle_t handle = create_or_open_file(name, read_write, p);
+      int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
+      if(fd < 0){
+         close_file(handle);
+         return fd;
+      }
+      if(!try_lock_locking_file(fd)){
+         _close(fd);
+         return -1;
+      }
+      struct _stat s;
+      if(0 == _stat(name, &s)){
+         return fd;
+      }
+      else{
+         _close(fd);
+      }
+   }
+}
+
+inline int try_open_and_lock_file(const char *name)
+{
+   file_handle_t handle = open_existing_file(name, read_write);
+   int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
+   if(fd < 0){
+      close_file(handle);
+      return fd;
+   }
+   if(!try_lock_locking_file(fd)){
+      _close(fd);
+      return -1;
+   }
+   return fd;
+}
+
+inline void close_lock_file(int fd)
+{  _close(fd); }
+
+inline bool is_valid_fd(int fd)
+{
+   struct _stat s;
+   return EBADF != _fstat(fd, &s);
+}
+
+inline bool is_normal_file(int fd)
+{
+   if(_isatty(fd))
+      return false;
+   struct _stat s;
+   if(0 != _fstat(fd, &s))
+      return false;
+   return 0 != (s.st_mode & _S_IFREG);
+}
+
+inline std::size_t get_size(int fd)
+{
+   struct _stat s;
+   if(0 != _fstat(fd, &s))
+      return 0u;
+   return (std::size_t)s.st_size;
+}
+
+inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
+{
+   winapi::interprocess_by_handle_file_information info;
+   if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
+      return false;
+   id.fd = fd;
+   id.dwVolumeSerialNumber = info.dwVolumeSerialNumber;
+   id.nFileIndexHigh = info.nFileIndexHigh;
+   id.nFileIndexLow = info.nFileIndexLow;
+   id.modules_attached_to_gmem_count = 1; //Initialize attached count
+   return true;
+}
+
+inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
+{
+   winapi::interprocess_by_handle_file_information info;
+   if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
+      return false;
+
+   return   id.dwVolumeSerialNumber == info.dwVolumeSerialNumber  &&
+            id.nFileIndexHigh       == info.nFileIndexHigh        &&
+            id.nFileIndexLow        == info.nFileIndexLow;
+}
+
+#else //UNIX
+
+struct locking_file_serial_id
+{
+   int fd;
+   dev_t st_dev;
+   ino_t st_ino;
+   //This reference count counts the number of modules attached
+   //to the shared memory and lock file. This serves to unlink
+   //the locking file and shared memory when all modules are
+   //done with the global memory (shared memory)
+   volatile boost::uint32_t modules_attached_to_gmem_count;
+};
+
+inline bool lock_locking_file(int fd)
+{
+   int ret = 0;
+   while(ret != 0 && errno != EINTR){
+      struct flock lock;
+      lock.l_type = F_WRLCK;
+      lock.l_whence = SEEK_SET;
+      lock.l_start = 0;
+      lock.l_len = 1;
+      ret = fcntl (fd, F_SETLKW, &lock);
+   }
+   return 0 == ret;
+}
+
+inline bool try_lock_locking_file(int fd)
+{
+   struct flock lock;
+   lock.l_type = F_WRLCK;
+   lock.l_whence = SEEK_SET;
+   lock.l_start = 0;
+   lock.l_len = 1;
+   return 0 == fcntl (fd, F_SETLK, &lock);
+}
+
+inline int open_or_create_and_lock_file(const char *name)
+{
+   permissions p;
+   p.set_unrestricted();
+   while(1){
+      int fd = create_or_open_file(name, read_write, p);
+      if(fd < 0){
+         return fd;
+      }
+      if(!try_lock_locking_file(fd)){
+         close(fd);
+         return -1;
+      }
+      struct stat s;
+      if(0 == stat(name, &s)){
+         return fd;
+      }
+      else{
+         close(fd);
+      }
+   }
+}
+
+inline int try_open_and_lock_file(const char *name)
+{
+   int fd = open_existing_file(name, read_write);
+   if(fd < 0){
+      return fd;
+   }
+   if(!try_lock_locking_file(fd)){
+      close(fd);
+      return -1;
+   }
+   return fd;
+}
+
+inline void close_lock_file(int fd)
+{  close(fd); }
+
+inline bool is_valid_fd(int fd)
+{
+   struct stat s;
+   return EBADF != fstat(fd, &s);
+}
+
+inline bool is_normal_file(int fd)
+{
+   struct stat s;
+   if(0 != fstat(fd, &s))
+      return false;
+   return 0 != (s.st_mode & S_IFREG);
+}
+
+inline std::size_t get_size(int fd)
+{
+   struct stat s;
+   if(0 != fstat(fd, &s))
+      return 0u;
+   return (std::size_t)s.st_size;
+}
+
+inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
+{
+   struct stat s;
+   if(0 != fstat(fd, &s))
+      return false;
+   id.fd = fd;
+   id.st_dev = s.st_dev;
+   id.st_ino = s.st_ino;
+   id.modules_attached_to_gmem_count = 1; //Initialize attached count
+   return true;
+}
+
+inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
+{
+   struct stat info;
+   if(0 != fstat(fd, &info))
+      return false;
+
+   return   id.st_dev == info.st_dev  &&
+            id.st_ino == info.st_ino;
+}
+
+#endif  
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP

+ 202 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/file_wrapper.hpp

@@ -0,0 +1,202 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
+#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+class file_wrapper
+{
+   /// @cond
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper)
+   /// @endcond
+   public:
+
+   //!Default constructor.
+   //!Represents an empty file_wrapper.
+   file_wrapper();
+
+   //!Creates a file object with name "name" and mode "mode", with the access mode "mode"
+   //!If the file previously exists, throws an error.
+   file_wrapper(create_only_t, const char *name, mode_t mode, const permissions &perm = permissions())
+   {  this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm);  }
+
+   //!Tries to create a file with name "name" and mode "mode", with the
+   //!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
+   //!Otherwise throws an error.
+   file_wrapper(open_or_create_t, const char *name, mode_t mode, const permissions &perm  = permissions())
+   {  this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm);  }
+
+   //!Tries to open a file with name "name", with the access mode "mode".
+   //!If the file does not previously exist, it throws an error.
+   file_wrapper(open_only_t, const char *name, mode_t mode)
+   {  this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions());  }
+
+   //!Moves the ownership of "moved"'s file to *this.
+   //!After the call, "moved" does not represent any file.
+   //!Does not throw
+   file_wrapper(BOOST_RV_REF(file_wrapper) moved)
+      :  m_handle(file_handle_t(ipcdetail::invalid_file()))
+   {  this->swap(moved);   }
+
+   //!Moves the ownership of "moved"'s file to *this.
+   //!After the call, "moved" does not represent any file.
+   //!Does not throw
+   file_wrapper &operator=(BOOST_RV_REF(file_wrapper) moved)
+   {
+      file_wrapper tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Swaps to file_wrappers.
+   //!Does not throw
+   void swap(file_wrapper &other);
+
+   //!Erases a file from the system.
+   //!Returns false on error. Never throws
+   static bool remove(const char *name);
+
+   //!Sets the size of the file
+   void truncate(offset_t length);
+
+   //!Closes the
+   //!file
+   ~file_wrapper();
+
+   //!Returns the name of the file
+   //!used in the constructor
+   const char *get_name() const;
+
+   //!Returns the name of the file
+   //!used in the constructor
+   bool get_size(offset_t &size) const;
+
+   //!Returns access mode
+   //!used in the constructor
+   mode_t get_mode() const;
+
+   //!Get mapping handle
+   //!to use with mapped_region
+   mapping_handle_t get_mapping_handle() const;
+
+   private:
+   //!Closes a previously opened file mapping. Never throws.
+   void priv_close();
+   //!Closes a previously opened file mapping. Never throws.
+   bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm);
+
+   file_handle_t  m_handle;
+   mode_t      m_mode;
+   std::string       m_filename;
+};
+
+inline file_wrapper::file_wrapper()
+   :  m_handle(file_handle_t(ipcdetail::invalid_file()))
+{}
+
+inline file_wrapper::~file_wrapper()
+{  this->priv_close(); }
+
+inline const char *file_wrapper::get_name() const
+{  return m_filename.c_str(); }
+
+inline bool file_wrapper::get_size(offset_t &size) const
+{  return get_file_size((file_handle_t)m_handle, size);  }
+
+inline void file_wrapper::swap(file_wrapper &other)
+{
+   std::swap(m_handle,  other.m_handle);
+   std::swap(m_mode,    other.m_mode);
+   m_filename.swap(other.m_filename);
+}
+
+inline mapping_handle_t file_wrapper::get_mapping_handle() const
+{  return mapping_handle_from_file_handle(m_handle);  }
+
+inline mode_t file_wrapper::get_mode() const
+{  return m_mode; }
+
+inline bool file_wrapper::priv_open_or_create
+   (ipcdetail::create_enum_t type,
+    const char *filename,
+    mode_t mode,
+    const permissions &perm = permissions())
+{
+   m_filename = filename;
+
+   if(mode != read_only && mode != read_write){
+      error_info err(mode_error);
+      throw interprocess_exception(err);
+   }
+
+   //Open file existing native API to obtain the handle
+   switch(type){
+      case ipcdetail::DoOpen:
+         m_handle = open_existing_file(filename, mode);
+      break;
+      case ipcdetail::DoCreate:
+         m_handle = create_new_file(filename, mode, perm);
+      break;
+      case ipcdetail::DoOpenOrCreate:
+         m_handle = create_or_open_file(filename, mode, perm);
+      break;
+      default:
+         {
+            error_info err = other_error;
+            throw interprocess_exception(err);
+         }
+   }
+
+   //Check for error
+   if(m_handle == invalid_file()){
+      throw interprocess_exception(error_info(system_error_code()));
+   }
+
+   m_mode = mode;
+   return true;
+}
+
+inline bool file_wrapper::remove(const char *filename)
+{  return delete_file(filename); }
+
+inline void file_wrapper::truncate(offset_t length)
+{
+   if(!truncate_file(m_handle, length)){
+      error_info err(system_error_code());
+      throw interprocess_exception(err);
+   }
+}
+
+inline void file_wrapper::priv_close()
+{
+   if(m_handle != invalid_file()){
+      close_file(m_handle);
+      m_handle = invalid_file();
+   }
+}
+
+}  //namespace ipcdetail{
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP

+ 73 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/in_place_interface.hpp

@@ -0,0 +1,73 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
+#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <typeinfo>  //typeid
+
+//!\file
+//!Describes an abstract interface for placement construction and destruction.
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+struct in_place_interface
+{
+   in_place_interface(std::size_t alignm, std::size_t sz, const char *tname)
+   :  alignment(alignm), size(sz), type_name(tname)
+   {}
+
+   std::size_t alignment;
+   std::size_t size;
+   const char *type_name;
+
+   virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) = 0;
+   virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) = 0;
+   virtual ~in_place_interface(){}
+};
+
+template<class T>
+struct placement_destroy :  public in_place_interface
+{
+   placement_destroy()
+	   :  in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name())
+   {}
+
+   virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed)
+   {
+      T* memory = static_cast<T*>(mem);
+      for(destroyed = 0; destroyed < num; ++destroyed)
+         (memory++)->~T();
+   }
+
+   virtual void construct_n(void *, std::size_t, std::size_t &) {}
+
+   private:
+   void destroy(void *mem)
+   {  static_cast<T*>(mem)->~T();   }
+};
+
+}
+}
+}   //namespace boost { namespace interprocess { namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP

+ 48 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/intermodule_singleton.hpp

@@ -0,0 +1,48 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP
+#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#ifdef BOOST_INTERPROCESS_WINDOWS
+   #include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
+#endif
+#include <boost/interprocess/detail/portable_intermodule_singleton.hpp>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+//Now this class is a singleton, initializing the singleton in
+//the first get() function call if LazyInit is false. If true
+//then the singleton will be initialized when loading the module.
+template<typename C, bool LazyInit = true, bool Phoenix = true>
+class intermodule_singleton
+   #ifdef BOOST_INTERPROCESS_WINDOWS
+   : public windows_intermodule_singleton<C, LazyInit, Phoenix>
+   #else
+   : public portable_intermodule_singleton<C, LazyInit, Phoenix>
+   #endif
+{};
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif

+ 495 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/intermodule_singleton_common.hpp

@@ -0,0 +1,495 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
+#define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/assert.hpp>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <sstream>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+namespace intermodule_singleton_helpers {
+
+inline void get_pid_creation_time_str(std::string &s)
+{
+   std::stringstream stream;
+   stream << get_current_process_id() << '_';
+   stream.precision(6);
+   stream << std::fixed << get_current_process_creation_time();
+   s = stream.str();
+}
+
+inline const char *get_map_base_name()
+{  return "bip.gmem.map.";  }
+
+inline void get_map_name(std::string &map_name)
+{
+   get_pid_creation_time_str(map_name);
+   map_name.insert(0, get_map_base_name());
+}
+
+inline std::size_t get_map_size()
+{  return 65536;  }
+
+template<class ThreadSafeGlobalMap>
+struct thread_safe_global_map_dependant;
+
+}  //namespace intermodule_singleton_helpers {
+
+//This class contains common code for all singleton types, so that we instantiate this
+//code just once per module. This class also holds a thread soafe global map
+//to be used by all instances protected with a reference count
+template<class ThreadSafeGlobalMap>
+class intermodule_singleton_common
+{
+   public:
+   typedef void*(singleton_constructor_t)(ThreadSafeGlobalMap &);
+   typedef void (singleton_destructor_t)(void *, ThreadSafeGlobalMap &);
+
+   static const ::boost::uint32_t Uninitialized       = 0u;
+   static const ::boost::uint32_t Initializing        = 1u;
+   static const ::boost::uint32_t Initialized         = 2u;
+   static const ::boost::uint32_t Broken              = 3u;
+   static const ::boost::uint32_t Destroyed           = 4u;
+
+   //Initialize this_module_singleton_ptr, creates the global map if needed and also creates an unique
+   //opaque type in global map through a singleton_constructor_t function call,
+   //initializing the passed pointer to that unique instance.
+   //
+   //We have two concurrency types here. a)the global map/singleton creation must
+   //be safe between threads of this process but in different modules/dlls. b)
+   //the pointer to the singleton is per-module, so we have to protect this
+   //initization between threads of the same module.
+   //
+   //All static variables declared here are shared between inside a module
+   //so atomic operations will synchronize only threads of the same module.
+   static void initialize_singleton_logic
+      (void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_constructor_t constructor, bool phoenix)
+   {
+      //If current module is not initialized enter to lock free logic
+      if(atomic_read32(&this_module_singleton_initialized) != Initialized){
+         //Now a single thread of the module will succeed in this CAS.
+         //trying to pass from Uninitialized to Initializing
+         ::boost::uint32_t previous_module_singleton_initialized = atomic_cas32
+            (&this_module_singleton_initialized, Initializing, Uninitialized);
+         //If the thread succeeded the CAS (winner) it will compete with other
+         //winner threads from other modules to create the global map
+         if(previous_module_singleton_initialized == Destroyed){
+            //Trying to resurrect a dead Phoenix singleton. Just try to
+            //mark it as uninitialized and start again
+            if(phoenix){
+               atomic_cas32(&this_module_singleton_initialized, Uninitialized, Destroyed);
+               previous_module_singleton_initialized = atomic_cas32
+                  (&this_module_singleton_initialized, Initializing, Uninitialized);
+            }
+            //Trying to resurrect a non-Phoenix dead singleton is an error
+            else{
+               throw interprocess_exception("Boost.Interprocess: Dead reference on non-Phoenix singleton of type");
+            }
+         }
+         if(previous_module_singleton_initialized == Uninitialized){
+            try{
+               //Now initialize the global map, this function must solve concurrency
+               //issues between threads of several modules
+               initialize_global_map_handle();
+               //Now try to create the singleton in global map.
+               //This function solves concurrency issues
+               //between threads of several modules
+               void *tmp = constructor(get_map());
+               //Increment the module reference count that reflects how many
+               //singletons this module holds, so that we can safely destroy
+               //module global map object when no singleton is left
+               atomic_inc32(&this_module_singleton_count);
+               //Insert a barrier before assigning the pointer to
+               //make sure this assignment comes after the initialization
+               atomic_write32(&this_module_singleton_initialized, Initializing);
+               //Assign the singleton address to the module-local pointer
+               ptr = tmp;
+               //Memory barrier inserted, all previous operations should complete
+               //before this one. Now marked as initialized
+               atomic_write32(&this_module_singleton_initialized, Initialized);
+            }
+            catch(...){
+               //Mark singleton failed to initialize
+               atomic_write32(&this_module_singleton_initialized, Broken);
+               throw;
+            }
+         }
+         //If previous state was initializing, this means that another winner thread is
+         //trying to initialize the singleton. Just wait until completes its work.
+         else if(previous_module_singleton_initialized == Initializing){
+            while(1){
+               previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
+               if(previous_module_singleton_initialized >= Initialized){
+                  //Already initialized, or exception thrown by initializer thread
+                  break;
+               }
+               else if(previous_module_singleton_initialized == Initializing){
+                  thread_yield();
+               }
+               else{
+                  //This can't be happening!
+                  BOOST_ASSERT(0);
+               }
+            }
+         }
+         else if(previous_module_singleton_initialized == Initialized){
+            //Nothing to do here, the singleton is ready
+         }
+         //If previous state was greater than initialized, then memory is broken
+         //trying to initialize the singleton.
+         else{//(previous_module_singleton_initialized > Initialized)
+            throw interprocess_exception("boost::interprocess::intermodule_singleton initialization failed");
+         }
+      }
+      BOOST_ASSERT(ptr != 0);
+   }
+
+   static void finalize_singleton_logic(void *&ptr, volatile boost::uint32_t &this_module_singleton_initialized, singleton_destructor_t destructor)
+   {
+      //Protect destruction against lazy singletons not initialized in this execution
+      if(ptr){
+         //Note: this destructor might provoke a Phoenix singleton
+         //resurrection. This means that this_module_singleton_count
+         //might change after this call.
+         destructor(ptr, get_map());
+         ptr = 0;
+
+         //Memory barrier to make sure pointer is nulled.
+         //Mark this singleton as destroyed.
+         atomic_write32(&this_module_singleton_initialized, Destroyed);
+
+         //If this is the last singleton of this module
+         //apply map destruction.
+         //Note: singletons are destroyed when the module is unloaded
+         //so no threads should be executing or holding references
+         //to this module
+         if(1 == atomic_dec32(&this_module_singleton_count)){
+            destroy_global_map_handle();
+         }
+      }
+   }
+
+   private:
+   static ThreadSafeGlobalMap &get_map()
+   {
+      return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem[0]));
+   }
+
+   static void initialize_global_map_handle()
+   {
+      //Obtain unique map name and size
+      while(1){
+         //Try to pass map state to initializing
+         ::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
+         if(tmp == Initialized || tmp == Broken){
+            break;
+         }
+         else if(tmp == Destroyed){
+            tmp = atomic_cas32(&this_module_map_initialized, Uninitialized, Destroyed);
+            continue;
+         }
+         //If some other thread is doing the work wait
+         else if(tmp == Initializing){
+            thread_yield();
+         }
+         else{ //(tmp == Uninitialized)
+            //If not initialized try it again?
+            try{
+               //Remove old global map from the system
+               intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
+               //in-place construction of the global map class
+               intermodule_singleton_helpers::thread_safe_global_map_dependant
+                  <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map()));
+               //Use global map's internal lock to initialize the lock file
+               //that will mark this gmem as "in use".
+               typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
+                  lock_file_logic f(get_map());
+               //If function failed (maybe a competing process has erased the shared
+               //memory between creation and file locking), retry with a new instance.
+               if(f.retry()){
+                  get_map().~ThreadSafeGlobalMap();
+                  atomic_write32(&this_module_map_initialized, Destroyed);
+               }
+               else{
+                  //Locking succeeded, so this global map module-instance is ready
+                  atomic_write32(&this_module_map_initialized, Initialized);
+                  break;
+               }
+            }
+            catch(...){
+               //
+               throw;
+            }
+         }
+      }
+   }
+
+   static void destroy_global_map_handle()
+   {
+      if(!atomic_read32(&this_module_singleton_count)){
+         //This module is being unloaded, so destroy
+         //the global map object of this module
+         //and unlink the global map if it's the last
+         typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::
+            unlink_map_logic f(get_map());
+         (get_map()).~ThreadSafeGlobalMap();
+         atomic_write32(&this_module_map_initialized, Destroyed);
+         //Do some cleanup for other processes old gmem instances
+         intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem();
+      }
+   }
+
+   //Static data, zero-initalized without any dependencies
+   //this_module_singleton_count is the number of singletons used by this module
+   static volatile boost::uint32_t this_module_singleton_count;
+
+   //this_module_map_initialized is the state of this module's map class object.
+   //Values: Uninitialized, Initializing, Initialized, Broken
+   static volatile boost::uint32_t this_module_map_initialized;
+
+   //Raw memory to construct the global map manager
+   static struct mem_holder_t
+   {
+      ::boost::detail::max_align aligner;
+      char map_mem [sizeof(ThreadSafeGlobalMap)];
+   } mem_holder;
+};
+
+template<class ThreadSafeGlobalMap>
+volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_singleton_count;
+
+template<class ThreadSafeGlobalMap>
+volatile boost::uint32_t intermodule_singleton_common<ThreadSafeGlobalMap>::this_module_map_initialized;
+
+template<class ThreadSafeGlobalMap>
+typename intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder_t
+   intermodule_singleton_common<ThreadSafeGlobalMap>::mem_holder;
+
+//A reference count to be stored in global map holding the number
+//of singletons (one per module) attached to the instance pointed by
+//the internal ptr.
+struct ref_count_ptr
+{
+   ref_count_ptr(void *p, boost::uint32_t count)
+      : ptr(p), singleton_ref_count(count)
+   {}
+   void *ptr;
+   //This reference count serves to count the number of attached
+   //modules to this singleton
+   volatile boost::uint32_t singleton_ref_count;
+};
+
+
+//Now this class is a singleton, initializing the singleton in
+//the first get() function call if LazyInit is false. If true
+//then the singleton will be initialized when loading the module.
+template<typename C, bool LazyInit, bool Phoenix, class ThreadSafeGlobalMap>
+class intermodule_singleton_impl
+{
+   public:
+
+   static C& get()   //Let's make inlining easy
+   {
+      if(!this_module_singleton_ptr){
+         if(lifetime.dummy_function()){  //This forces lifetime instantiation, for reference counted destruction
+            atentry_work();
+         }
+      }
+      return *static_cast<C*>(this_module_singleton_ptr);
+   }
+
+   private:
+
+   static void atentry_work()
+   {
+      intermodule_singleton_common<ThreadSafeGlobalMap>::initialize_singleton_logic
+         (this_module_singleton_ptr, this_module_singleton_initialized, singleton_constructor, Phoenix);
+   }
+
+   static void atexit_work()
+   {
+      intermodule_singleton_common<ThreadSafeGlobalMap>::finalize_singleton_logic
+         (this_module_singleton_ptr, this_module_singleton_initialized, singleton_destructor);
+   }
+
+   //These statics will be zero-initialized without any constructor call dependency
+   //this_module_singleton_ptr will be a module-local pointer to the singleton
+   static void*                      this_module_singleton_ptr;
+
+   //this_module_singleton_count will be used to synchronize threads of the same module
+   //for access to a singleton instance, and to flag the state of the
+   //singleton.
+   static volatile boost::uint32_t   this_module_singleton_initialized;
+
+   //This class destructor will trigger singleton destruction
+   struct lifetime_type_lazy
+   {
+      bool dummy_function()
+      {  return m_dummy == 0; }
+
+      ~lifetime_type_lazy()
+      {
+         if(!Phoenix){
+            atexit_work();
+         }
+      }
+
+      //Dummy volatile so that the compiler can't resolve its value at compile-time
+      //and can't avoid lifetime_type instantiation if dummy_function() is called.
+      static volatile int m_dummy;
+   };
+
+   struct lifetime_type_static
+      : public lifetime_type_lazy
+   {
+      lifetime_type_static()
+      {  atentry_work();  }
+   };
+
+   typedef typename if_c
+      <LazyInit, lifetime_type_lazy, lifetime_type_static>::type lifetime_type;
+
+   static lifetime_type lifetime;
+
+   //A functor to be executed inside global map lock that just
+   //searches for the singleton in map and if not present creates a new one.
+   //If singleton constructor throws, the exception is propagated
+   struct init_atomic_func
+   {
+      init_atomic_func(ThreadSafeGlobalMap &m)
+         : m_map(m)
+      {}
+
+      void operator()()
+      {
+         ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
+            <ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
+         if(!rcount){
+            C *p = new C;
+            try{
+               ref_count_ptr val(p, 0u);
+               rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
+                           <ThreadSafeGlobalMap>::insert(m_map, typeid(C).name(), val);
+            }
+            catch(...){
+               intermodule_singleton_helpers::thread_safe_global_map_dependant
+                           <ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
+               delete p;
+               throw;
+            }
+         }
+         if(Phoenix){
+            std::atexit(&atexit_work);
+         }
+         atomic_inc32(&rcount->singleton_ref_count);
+         ret_ptr = rcount->ptr;
+      }
+      void *data() const
+         { return ret_ptr;  }
+
+      private:
+      ThreadSafeGlobalMap &m_map;
+      void *ret_ptr;
+   };
+
+   //A functor to be executed inside global map lock that just
+   //deletes the singleton in map if the attached count reaches to zero
+   struct fini_atomic_func
+   {
+      fini_atomic_func(ThreadSafeGlobalMap &m)
+         : m_map(m)
+      {}
+
+      void operator()()
+      {
+         ref_count_ptr *rcount = intermodule_singleton_helpers::thread_safe_global_map_dependant
+            <ThreadSafeGlobalMap>::find(m_map, typeid(C).name());
+            //The object must exist
+         BOOST_ASSERT(rcount);
+         BOOST_ASSERT(rcount->singleton_ref_count > 0);
+         //Check if last reference
+         if(atomic_dec32(&rcount->singleton_ref_count) == 1){
+            //If last, destroy the object
+            BOOST_ASSERT(rcount->ptr != 0);
+            C *pc = static_cast<C*>(rcount->ptr);
+            //Now destroy map entry
+            bool destroyed = intermodule_singleton_helpers::thread_safe_global_map_dependant
+                        <ThreadSafeGlobalMap>::erase(m_map, typeid(C).name());
+            (void)destroyed;  BOOST_ASSERT(destroyed == true);
+            delete pc;
+         }
+      }
+      void *data() const
+         { return ret_ptr;  }
+
+      private:
+      ThreadSafeGlobalMap &m_map;
+      void *ret_ptr;
+   };
+
+   //A wrapper to execute init_atomic_func
+   static void *singleton_constructor(ThreadSafeGlobalMap &map)
+   {
+      init_atomic_func f(map);
+      intermodule_singleton_helpers::thread_safe_global_map_dependant
+                  <ThreadSafeGlobalMap>::atomic_func(map, f);
+      return f.data();
+   }
+
+   //A wrapper to execute fini_atomic_func
+   static void singleton_destructor(void *p, ThreadSafeGlobalMap &map)
+   {  (void)p;
+      fini_atomic_func f(map);
+      intermodule_singleton_helpers::thread_safe_global_map_dependant
+                  <ThreadSafeGlobalMap>::atomic_func(map, f);
+   }
+};
+
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+volatile int intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type_lazy::m_dummy = 0;
+
+//These will be zero-initialized by the loader
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+void *intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_ptr = 0;
+
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+volatile boost::uint32_t intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::this_module_singleton_initialized = 0;
+
+template <typename C, bool L, bool P, class ThreadSafeGlobalMap>
+typename intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime_type
+   intermodule_singleton_impl<C, L, P, ThreadSafeGlobalMap>::lifetime;
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP

+ 31 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/interprocess_tester.hpp

@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
+#define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+class interprocess_tester
+{
+   public:
+   template<class T>
+   static void dont_close_on_destruction(T &t)
+   {  t.dont_close_on_destruction(); }
+};
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
+

File diff suppressed because it is too large
+ 1040 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/intersegment_ptr.hpp


+ 115 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_global_memory.hpp

@@ -0,0 +1,115 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP
+#define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/offset_ptr.hpp>
+#include <boost/interprocess/sync/spin/mutex.hpp>
+#include <boost/interprocess/sync/spin/recursive_mutex.hpp>
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> 
+#include <boost/interprocess/indexes/iset_index.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+struct intermodule_singleton_mutex_family
+{
+   typedef boost::interprocess::ipcdetail::spin_mutex              mutex_type;
+   typedef boost::interprocess::ipcdetail::spin_recursive_mutex    recursive_mutex_type;
+};
+
+struct intermodule_types
+{
+   //We must use offset_ptr since a loaded DLL can map the singleton holder shared memory
+   //at a different address than other DLLs or the main executable
+   typedef rbtree_best_fit<intermodule_singleton_mutex_family, offset_ptr<void> > mem_algo;
+   template<class Device, bool FileBased>
+   struct open_or_create
+   {
+      typedef managed_open_or_create_impl
+            <Device, mem_algo::Alignment, FileBased> type;
+   };
+};
+
+//we must implement our own managed shared memory to avoid circular dependencies
+template<class Device, bool FileBased>
+class basic_managed_global_memory
+   : public basic_managed_memory_impl
+      < char
+      , intermodule_types::mem_algo
+      , iset_index
+      , intermodule_types::open_or_create<Device, FileBased>::type::ManagedOpenOrCreateUserOffset
+      >
+   , private intermodule_types::open_or_create<Device, FileBased>::type
+{
+   /// @cond
+   typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t;
+
+   typedef basic_managed_memory_impl
+      < char
+      , intermodule_types::mem_algo
+      , iset_index
+      , base2_t::ManagedOpenOrCreateUserOffset
+      > base_t;
+
+   typedef create_open_func<base_t>        create_open_func_t;
+
+   basic_managed_global_memory *get_this_pointer()
+   {  return this;   }
+
+   public:
+   typedef typename base_t::size_type              size_type;
+
+   private:
+   typedef typename base_t::char_ptr_holder_t   char_ptr_holder_t;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory)
+   /// @endcond
+
+   public: //functions
+
+   basic_managed_global_memory (open_or_create_t open_or_create,
+                              const char *name, size_type size,
+                              const void *addr = 0, const permissions& perm = permissions())
+      : base_t()
+      , base2_t(open_or_create, name, size, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                DoOpenOrCreate), perm)
+   {}
+
+   basic_managed_global_memory (open_only_t open_only, const char* name,
+                                const void *addr = 0)
+      : base_t()
+      , base2_t(open_only, name, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                DoOpen))
+   {}
+};
+
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP

+ 750 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_memory_impl.hpp

@@ -0,0 +1,750 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
+#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/segment_manager.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+//
+#include <boost/detail/no_exceptions_support.hpp>
+//
+#include <utility>
+#include <fstream>
+#include <new>
+#include <boost/assert.hpp>
+
+//!\file
+//!Describes a named shared memory allocation user class.
+//!
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template<class BasicManagedMemoryImpl>
+class create_open_func;
+
+template<
+         class CharType,
+         class MemoryAlgorithm,
+         template<class IndexConfig> class IndexType
+        >
+struct segment_manager_type
+{
+   typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
+};
+
+//!This class is designed to be a base class to classes that manage
+//!creation of objects in a fixed size memory buffer. Apart
+//!from allocating raw memory, the user can construct named objects. To
+//!achieve this, this class uses the reserved space provided by the allocation
+//!algorithm to place a named_allocator_algo, who takes care of name mappings.
+//!The class can be customized with the char type used for object names
+//!and the memory allocation algorithm to be used.*/
+template <  class CharType
+         ,  class MemoryAlgorithm
+         ,  template<class IndexConfig> class IndexType
+         ,  std::size_t Offset = 0
+         >
+class basic_managed_memory_impl
+{
+   //Non-copyable
+   basic_managed_memory_impl(const basic_managed_memory_impl &);
+   basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
+
+   template<class BasicManagedMemoryImpl>
+   friend class create_open_func;
+
+   public:
+   typedef typename segment_manager_type
+      <CharType, MemoryAlgorithm, IndexType>::type    segment_manager;
+   typedef CharType                                   char_type;
+   typedef MemoryAlgorithm                            memory_algorithm;
+   typedef typename MemoryAlgorithm::mutex_family     mutex_family;
+   typedef CharType                                   char_t;
+   typedef typename MemoryAlgorithm::size_type        size_type;
+   typedef typename MemoryAlgorithm::difference_type  difference_type;
+   typedef difference_type                            handle_t;
+   typedef typename segment_manager::
+      const_named_iterator                            const_named_iterator;
+   typedef typename segment_manager::
+      const_unique_iterator                           const_unique_iterator;
+
+   /// @cond
+
+   typedef typename
+           segment_manager::char_ptr_holder_t         char_ptr_holder_t;
+   //Experimental. Don't use.
+
+   typedef typename segment_manager::multiallocation_chain  multiallocation_chain;
+
+   /// @endcond
+
+   static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
+
+   private:
+   typedef basic_managed_memory_impl
+               <CharType, MemoryAlgorithm, IndexType, Offset> self_t;
+   protected:
+   template<class ManagedMemory>
+   static bool grow(const char *filename, size_type extra_bytes)
+   {
+      typedef typename ManagedMemory::device_type device_type;
+      //Increase file size
+      try{
+         offset_t old_size;
+         {
+            device_type f(open_or_create, filename, read_write);
+            if(!f.get_size(old_size))
+               return false;
+            f.truncate(old_size + extra_bytes);
+         }
+         ManagedMemory managed_memory(open_only, filename);
+         //Grow always works
+         managed_memory.self_t::grow(extra_bytes);
+      }
+      catch(...){
+         return false;
+      }
+      return true;
+   }
+
+   template<class ManagedMemory>
+   static bool shrink_to_fit(const char *filename)
+   {
+      typedef typename ManagedMemory::device_type device_type;
+      size_type new_size;
+      try{
+         ManagedMemory managed_memory(open_only, filename);
+         managed_memory.get_size();
+         managed_memory.self_t::shrink_to_fit();
+         new_size = managed_memory.get_size();
+      }
+      catch(...){
+         return false;
+      }
+
+      //Decrease file size
+      {
+         device_type f(open_or_create, filename, read_write);
+         f.truncate(new_size);
+      }
+      return true;
+   }
+
+   //!Constructor. Allocates basic resources. Never throws.
+   basic_managed_memory_impl()
+      : mp_header(0){}
+
+   //!Destructor. Calls close. Never throws.
+   ~basic_managed_memory_impl()
+   {  this->close_impl(); }
+
+   //!Places segment manager in the reserved space. This can throw.
+   bool  create_impl   (void *addr, size_type size)
+   {
+      if(mp_header)  return false;
+
+      //Check if there is enough space
+      if(size < segment_manager::get_min_size())
+         return false;
+
+      //This function should not throw. The index construction can
+      //throw if constructor allocates memory. So we must catch it.
+      BOOST_TRY{
+         //Let's construct the allocator in memory
+         mp_header       = new(addr) segment_manager(size);
+      }
+      BOOST_CATCH(...){
+         return false;
+      }
+      BOOST_CATCH_END
+      return true;
+   }
+
+   //!Connects to a segment manager in the reserved buffer. Never throws.
+   bool  open_impl     (void *addr, size_type)
+   {
+      if(mp_header)  return false;
+      mp_header = static_cast<segment_manager*>(addr);
+      return true;
+   }
+
+   //!Frees resources. Never throws.
+   bool close_impl()
+   {
+      bool ret = mp_header != 0;
+      mp_header = 0;
+      return ret;
+   }
+
+   //!Frees resources and destroys common resources. Never throws.
+   bool destroy_impl()
+   {
+      if(mp_header == 0)
+         return false;
+      mp_header->~segment_manager();
+      this->close_impl();
+         return true;
+   }
+
+   //!
+   void grow(size_type extra_bytes)
+   {  mp_header->grow(extra_bytes); }
+
+   void shrink_to_fit()
+   {  mp_header->shrink_to_fit(); }
+
+   public:
+
+   //!Returns segment manager. Never throws.
+   segment_manager *get_segment_manager() const
+   {   return mp_header; }
+
+   //!Returns the base address of the memory in this process. Never throws.
+   void *   get_address   () const
+   {   return reinterpret_cast<char*>(mp_header) - Offset; }
+
+   //!Returns the size of memory segment. Never throws.
+   size_type   get_size   () const
+   {   return mp_header->get_size() + Offset;  }
+
+   //!Returns the number of free bytes of the memory
+   //!segment
+   size_type get_free_memory() const
+   {  return mp_header->get_free_memory();  }
+
+   //!Returns the result of "all_memory_deallocated()" function
+   //!of the used memory algorithm
+   bool all_memory_deallocated()
+   {   return mp_header->all_memory_deallocated(); }
+
+   //!Returns the result of "check_sanity()" function
+   //!of the used memory algorithm
+   bool check_sanity()
+   {   return mp_header->check_sanity(); }
+
+   //!Writes to zero free memory (memory not yet allocated) of
+   //!the memory algorithm
+   void zero_free_memory()
+   {   mp_header->zero_free_memory(); }
+
+   //!Transforms an absolute address into an offset from base address.
+   //!The address must belong to the memory segment. Never throws.
+   handle_t get_handle_from_address   (const void *ptr) const
+   {
+      return (handle_t)(reinterpret_cast<const char*>(ptr) -
+             reinterpret_cast<const char*>(this->get_address()));
+   }
+
+   //!Returns true if the address belongs to the managed memory segment
+   bool belongs_to_segment (const void *ptr) const
+   {
+      return ptr >= this->get_address() &&
+             ptr <  (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
+   }
+
+   //!Transforms previously obtained offset into an absolute address in the
+   //!process space of the current process. Never throws.*/
+   void *    get_address_from_handle (handle_t offset) const
+   {  return reinterpret_cast<char*>(this->get_address()) + offset; }
+
+   //!Searches for nbytes of free memory in the segment, marks the
+   //!memory as used and return the pointer to the memory. If no
+   //!memory is available throws a boost::interprocess::bad_alloc exception
+   void* allocate             (size_type nbytes)
+   {   return mp_header->allocate(nbytes);   }
+
+   //!Searches for nbytes of free memory in the segment, marks the
+   //!memory as used and return the pointer to the memory. If no memory
+   //!is available returns 0. Never throws.
+   void* allocate             (size_type nbytes, std::nothrow_t nothrow)
+   {   return mp_header->allocate(nbytes, nothrow);  }
+
+   //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
+   //!must be power of two. If no memory
+   //!is available returns 0. Never throws.
+   void * allocate_aligned (size_type nbytes, size_type alignment, std::nothrow_t nothrow)
+   {   return mp_header->allocate_aligned(nbytes, alignment, nothrow);  }
+
+   template<class T>
+   std::pair<T *, bool>
+      allocation_command  (boost::interprocess::allocation_type command,   size_type limit_size,
+                           size_type preferred_size,size_type &received_size,
+                           T *reuse_ptr = 0)
+   {
+      return mp_header->allocation_command
+         (command, limit_size, preferred_size, received_size, reuse_ptr);
+   }
+
+   //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
+   //!must be power of two. If no
+   //!memory is available throws a boost::interprocess::bad_alloc exception
+   void * allocate_aligned(size_type nbytes, size_type alignment)
+   {   return mp_header->allocate_aligned(nbytes, alignment);  }
+
+   /// @cond
+
+   //Experimental. Don't use.
+
+   //!Allocates n_elements of elem_size bytes.
+   multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements)
+   {  return mp_header->allocate_many(elem_bytes, num_elements); }
+
+   //!Allocates n_elements, each one of elem_sizes[i] bytes.
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
+   {  return mp_header->allocate_many(elem_sizes, n_elements); }
+
+   //!Allocates n_elements of elem_size bytes.
+   multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements, std::nothrow_t nothrow)
+   {  return mp_header->allocate_many(elem_bytes, num_elements, nothrow); }
+
+   //!Allocates n_elements, each one of elem_sizes[i] bytes.
+   multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, std::nothrow_t nothrow)
+   {  return mp_header->allocate_many(elem_sizes, n_elements, nothrow); }
+
+   //!Allocates n_elements, each one of elem_sizes[i] bytes.
+   void deallocate_many(multiallocation_chain chain)
+   {  return mp_header->deallocate_many(boost::move(chain)); }
+
+   /// @endcond
+
+   //!Marks previously allocated memory as free. Never throws.
+   void  deallocate           (void *addr)
+   {   if (mp_header) mp_header->deallocate(addr);  }
+
+   //!Tries to find a previous named allocation address. Returns a memory
+   //!buffer and the object count. If not found returned pointer is 0.
+   //!Never throws.
+   template <class T>
+   std::pair<T*, size_type> find  (char_ptr_holder_t name)
+   {   return mp_header->template find<T>(name); }
+
+   //!Creates a named object or array in memory
+   //!
+   //!Allocates and constructs a T object or an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. If an array is being constructed all objects are
+   //!created using the same parameters given to this function.
+   //!
+   //!-> If the name was previously used, returns 0.
+   //!
+   //!-> Throws boost::interprocess::bad_alloc if there is no available memory
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and if an
+   //!array was being constructed, destructors of created objects are called
+   //!before freeing the memory.
+   template <class T>
+   typename segment_manager::template construct_proxy<T>::type
+      construct(char_ptr_holder_t name)
+   {   return mp_header->template construct<T>(name);  }
+
+   //!Finds or creates a named object or array in memory
+   //!
+   //!Tries to find an object with the given name in memory. If
+   //!found, returns the pointer to this pointer. If the object is not found,
+   //!allocates and constructs a T object or an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. If an array is being constructed all objects are
+   //!created using the same parameters given to this function.
+   //!
+   //!-> Throws boost::interprocess::bad_alloc if there is no available memory
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and if an
+   //!array was being constructed, destructors of created objects are called
+   //!before freeing the memory.
+   template <class T>
+   typename segment_manager::template construct_proxy<T>::type
+      find_or_construct(char_ptr_holder_t name)
+   {   return mp_header->template find_or_construct<T>(name);  }
+
+   //!Creates a named object or array in memory
+   //!
+   //!Allocates and constructs a T object or an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. If an array is being constructed all objects are
+   //!created using the same parameters given to this function.
+   //!
+   //!-> If the name was previously used, returns 0.
+   //!
+   //!-> Returns 0 if there is no available memory
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and if an
+   //!array was being constructed, destructors of created objects are called
+   //!before freeing the memory.
+   template <class T>
+   typename segment_manager::template construct_proxy<T>::type
+      construct(char_ptr_holder_t name, std::nothrow_t nothrow)
+   {   return mp_header->template construct<T>(name, nothrow);  }
+
+   //!Finds or creates a named object or array in memory
+   //!
+   //!Tries to find an object with the given name in memory. If
+   //!found, returns the pointer to this pointer. If the object is not found,
+   //!allocates and constructs a T object or an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. If an array is being constructed all objects are
+   //!created using the same parameters given to this function.
+   //!
+   //!-> Returns 0 if there is no available memory
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and if an
+   //!array was being constructed, destructors of created objects are called
+   //!before freeing the memory.
+   template <class T>
+   typename segment_manager::template construct_proxy<T>::type
+      find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow)
+   {   return mp_header->template find_or_construct<T>(name, nothrow);  }
+
+   //!Creates a named array from iterators in memory
+   //!
+   //!Allocates and constructs an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. Each element in the array is created using the
+   //!objects returned when dereferencing iterators as parameters
+   //!and incrementing all iterators for each element.
+   //!
+   //!-> If the name was previously used, returns 0.
+   //!
+   //!-> Throws boost::interprocess::bad_alloc if there is no available memory
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and
+   //!destructors of created objects are called before freeing the memory.
+   template <class T>
+   typename segment_manager::template construct_iter_proxy<T>::type
+      construct_it(char_ptr_holder_t name)
+   {   return mp_header->template construct_it<T>(name);  }
+
+   //!Finds or creates a named array from iterators in memory
+   //!
+   //!Tries to find an object with the given name in memory. If
+   //!found, returns the pointer to this pointer. If the object is not found,
+   //!allocates and constructs an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. Each element in the array is created using the
+   //!objects returned when dereferencing iterators as parameters
+   //!and incrementing all iterators for each element.
+   //!
+   //!-> If the name was previously used, returns 0.
+   //!
+   //!-> Throws boost::interprocess::bad_alloc if there is no available memory
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and
+   //!destructors of created objects are called before freeing the memory.
+   template <class T>
+   typename segment_manager::template construct_iter_proxy<T>::type
+      find_or_construct_it(char_ptr_holder_t name)
+   {   return mp_header->template find_or_construct_it<T>(name);  }
+
+   //!Creates a named array from iterators in memory
+   //!
+   //!Allocates and constructs an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. Each element in the array is created using the
+   //!objects returned when dereferencing iterators as parameters
+   //!and incrementing all iterators for each element.
+   //!
+   //!-> If the name was previously used, returns 0.
+   //!
+   //!-> If there is no available memory, returns 0.
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and
+   //!destructors of created objects are called before freeing the memory.*/
+   template <class T>
+   typename segment_manager::template construct_iter_proxy<T>::type
+      construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
+   {   return mp_header->template construct_it<T>(name, nothrow);  }
+
+   //!Finds or creates a named array from iterators in memory
+   //!
+   //!Tries to find an object with the given name in memory. If
+   //!found, returns the pointer to this pointer. If the object is not found,
+   //!allocates and constructs an array of T in memory,
+   //!associates this with the given name and returns a pointer to the
+   //!created object. Each element in the array is created using the
+   //!objects returned when dereferencing iterators as parameters
+   //!and incrementing all iterators for each element.
+   //!
+   //!-> If the name was previously used, returns 0.
+   //!
+   //!-> If there is no available memory, returns 0.
+   //!
+   //!-> If T's constructor throws, the function throws that exception.
+   //!
+   //!Memory is freed automatically if T's constructor throws and
+   //!destructors of created objects are called before freeing the memory.*/
+   template <class T>
+   typename segment_manager::template construct_iter_proxy<T>::type
+      find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
+   {   return mp_header->template find_or_construct_it<T>(name, nothrow);  }
+
+   //!Calls a functor and guarantees that no new construction, search or
+   //!destruction will be executed by any process while executing the object
+   //!function call. If the functor throws, this function throws.
+   template <class Func>
+   void atomic_func(Func &f)
+   {   mp_header->atomic_func(f);  }
+
+   //!Tries to call a functor guaranteeing that no new construction, search or
+   //!destruction will be executed by any process while executing the object
+   //!function call. If the atomic function can't be immediatelly executed
+   //!because the internal mutex is already locked, returns false.
+   //!If the functor throws, this function throws.
+   template <class Func>
+   bool try_atomic_func(Func &f)
+   {   return mp_header->try_atomic_func(f); }
+
+   //!Destroys a named memory object or array.
+   //!
+   //!Finds the object with the given name, calls its destructors,
+   //!frees used memory and returns true.
+   //!
+   //!-> If the object is not found, it returns false.
+   //!
+   //!Exception Handling:
+   //!
+   //!When deleting a dynamically object or array, the Standard
+   //!does not guarantee that dynamically allocated memory, will be released.
+   //!Also, when deleting arrays, the Standard doesn't require calling
+   //!destructors for the rest of the objects if for one of them the destructor
+   //!terminated with an exception.
+   //!
+   //!Destroying an object:
+   //!
+   //!If the destructor throws, the memory will be freed and that exception
+   //!will be thrown.
+   //!
+   //!Destroying an array:
+   //!
+   //!When destroying an array, if a destructor throws, the rest of
+   //!destructors are called. If any of these throws, the exceptions are
+   //!ignored. The name association will be erased, memory will be freed and
+   //!the first exception will be thrown. This guarantees the unlocking of
+   //!mutexes and other resources.
+   //!
+   //!For all theses reasons, classes with throwing destructors are not
+   //!recommended.
+   template <class T>
+   bool destroy(const CharType *name)
+   {   return mp_header->template destroy<T>(name); }
+
+   //!Destroys the unique instance of type T
+   //!
+   //!Calls the destructor, frees used memory and returns true.
+   //!
+   //!Exception Handling:
+   //!
+   //!When deleting a dynamically object, the Standard does not
+   //!guarantee that dynamically allocated memory will be released.
+   //!
+   //!Destroying an object:
+   //!
+   //!If the destructor throws, the memory will be freed and that exception
+   //!will be thrown.
+   //!
+   //!For all theses reasons, classes with throwing destructors are not
+   //!recommended for  memory.
+   template <class T>
+   bool destroy(const unique_instance_t *const )
+   {   return mp_header->template destroy<T>(unique_instance);  }
+
+   //!Destroys the object (named, unique, or anonymous)
+   //!
+   //!Calls the destructor, frees used memory and returns true.
+   //!
+   //!Exception Handling:
+   //!
+   //!When deleting a dynamically object, the Standard does not
+   //!guarantee that dynamically allocated memory will be released.
+   //!
+   //!Destroying an object:
+   //!
+   //!If the destructor throws, the memory will be freed and that exception
+   //!will be thrown.
+   //!
+   //!For all theses reasons, classes with throwing destructors are not
+   //!recommended for  memory.
+   template <class T>
+   void destroy_ptr(const T *ptr)
+   {  mp_header->template destroy_ptr<T>(ptr); }
+
+   //!Returns the name of an object created with construct/find_or_construct
+   //!functions. Does not throw
+   template<class T>
+   static const char_type *get_instance_name(const T *ptr)
+   {  return segment_manager::get_instance_name(ptr);   }
+
+   //!Returns is the type an object created with construct/find_or_construct
+   //!functions. Does not throw.
+   template<class T>
+   static instance_type get_instance_type(const T *ptr)
+   {  return segment_manager::get_instance_type(ptr); }
+
+   //!Returns the length of an object created with construct/find_or_construct
+   //!functions (1 if is a single element, >=1 if it's an array). Does not throw.
+   template<class T>
+   static size_type get_instance_length(const T *ptr)
+   {  return segment_manager::get_instance_length(ptr); }
+
+   //!Preallocates needed index resources to optimize the
+   //!creation of "num" named objects in the  memory segment.
+   //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
+   void reserve_named_objects(size_type num)
+   {  mp_header->reserve_named_objects(num);  }
+
+   //!Preallocates needed index resources to optimize the
+   //!creation of "num" unique objects in the  memory segment.
+   //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
+   void reserve_unique_objects(size_type num)
+   {  mp_header->reserve_unique_objects(num);  }
+
+   //!Calls shrink_to_fit in both named and unique object indexes
+   //to try to free unused memory from those indexes.
+   void shrink_to_fit_indexes()
+   {  mp_header->shrink_to_fit_indexes();  }
+
+   //!Returns the number of named objects stored
+   //!in the managed segment.
+   size_type get_num_named_objects()
+   {  return mp_header->get_num_named_objects();  }
+
+   //!Returns the number of unique objects stored
+   //!in the managed segment.
+   size_type get_num_unique_objects()
+   {  return mp_header->get_num_unique_objects();  }
+
+   //!Returns a constant iterator to the index storing the
+   //!named allocations. NOT thread-safe. Never throws.
+   const_named_iterator named_begin() const
+   {  return mp_header->named_begin(); }
+
+   //!Returns a constant iterator to the end of the index
+   //!storing the named allocations. NOT thread-safe. Never throws.
+   const_named_iterator named_end() const
+   {  return mp_header->named_end(); }
+
+   //!Returns a constant iterator to the index storing the
+   //!unique allocations. NOT thread-safe. Never throws.
+   const_unique_iterator unique_begin() const
+   {  return mp_header->unique_begin(); }
+
+   //!Returns a constant iterator to the end of the index
+   //!storing the unique allocations. NOT thread-safe. Never throws.
+   const_unique_iterator unique_end() const
+   {  return mp_header->unique_end(); }
+
+   //!This is the default allocator to allocate types T
+   //!from this managed segment
+   template<class T>
+   struct allocator
+   {
+      typedef typename segment_manager::template allocator<T>::type type;
+   };
+
+   //!Returns an instance of the default allocator for type T
+   //!initialized that allocates memory from this segment manager.
+   template<class T>
+   typename allocator<T>::type
+      get_allocator()
+   {   return mp_header->template get_allocator<T>(); }
+
+   //!This is the default deleter to delete types T
+   //!from this managed segment.
+   template<class T>
+   struct deleter
+   {
+      typedef typename segment_manager::template deleter<T>::type type;
+   };
+
+   //!Returns an instance of the default allocator for type T
+   //!initialized that allocates memory from this segment manager.
+   template<class T>
+   typename deleter<T>::type
+      get_deleter()
+   {   return mp_header->template get_deleter<T>(); }
+
+   /// @cond
+   //!Tries to find a previous named allocation address. Returns a memory
+   //!buffer and the object count. If not found returned pointer is 0.
+   //!Never throws.
+   template <class T>
+   std::pair<T*, size_type> find_no_lock  (char_ptr_holder_t name)
+   {   return mp_header->template find_no_lock<T>(name); }
+   /// @endcond
+
+   protected:
+   //!Swaps the segment manager's managed by this managed memory segment.
+   //!NOT thread-safe. Never throws.
+   void swap(basic_managed_memory_impl &other)
+   {  std::swap(mp_header, other.mp_header); }
+
+   private:
+   segment_manager *mp_header;
+};
+
+template<class BasicManagedMemoryImpl>
+class create_open_func
+{
+   public:
+   create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
+      : m_frontend(frontend), m_type(type){}
+
+   bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const
+   {
+      if(((m_type == DoOpen)   &&  created) ||
+         ((m_type == DoCreate) && !created))
+         return false;
+
+      if(created)
+         return m_frontend->create_impl(addr, size);
+      else
+         return m_frontend->open_impl  (addr, size);
+   }
+
+   private:
+   BasicManagedMemoryImpl *m_frontend;
+   create_enum_t           m_type;
+};
+
+}  //namespace ipcdetail {
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
+

+ 408 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_multi_shared_memory.hpp

@@ -0,0 +1,408 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
+#define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/interprocess/detail/multi_segment_services.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/containers/list.hpp>//list
+#include <boost/interprocess/mapped_region.hpp> //mapped_region
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> //managed_open_or_create_impl
+#include <new>
+#include <boost/interprocess/containers/string.hpp>
+#include <boost/interprocess/streams/vectorstream.hpp>
+#include <memory>
+#include <boost/assert.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+
+//!\file
+//!Describes a named shared memory object allocation user class.
+
+namespace boost {
+
+namespace interprocess {
+
+//TODO: We must somehow obtain the permissions of the first segment
+//to apply them to subsequent segments
+//-Use GetSecurityInfo?
+//-Change everything to use only a shared memory object expanded via truncate()?
+
+//!A basic shared memory named object creation class. Initializes the
+//!shared memory segment. Inherits all basic functionality from
+//!basic_managed_memory_impl<CharType, MemoryAlgorithm, IndexType>
+template
+      <
+         class CharType,
+         class MemoryAlgorithm,
+         template<class IndexConfig> class IndexType
+      >
+class basic_managed_multi_shared_memory
+   :  public ipcdetail::basic_managed_memory_impl
+         <CharType, MemoryAlgorithm, IndexType>
+{
+
+   typedef basic_managed_multi_shared_memory
+               <CharType, MemoryAlgorithm, IndexType>    self_t;
+   typedef ipcdetail::basic_managed_memory_impl
+      <CharType, MemoryAlgorithm, IndexType>             base_t;
+
+   typedef typename MemoryAlgorithm::void_pointer        void_pointer;
+   typedef typename ipcdetail::
+      managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment>  managed_impl;
+   typedef typename void_pointer::segment_group_id       segment_group_id;
+   typedef typename base_t::size_type                   size_type;
+
+   ////////////////////////////////////////////////////////////////////////
+   //
+   //               Some internal helper structs/functors
+   //
+   ////////////////////////////////////////////////////////////////////////
+   //!This class defines an operator() that creates a shared memory
+   //!of the requested size. The rest of the parameters are
+   //!passed in the constructor. The class a template parameter
+   //!to be used with create_from_file/create_from_istream functions
+   //!of basic_named_object classes
+
+//   class segment_creator
+//   {
+//      public:
+//      segment_creator(shared_memory &shmem,
+//                      const char *mem_name,
+//                      const void *addr)
+//      : m_shmem(shmem), m_mem_name(mem_name), m_addr(addr){}
+//
+//      void *operator()(size_type size)
+//      {
+//         if(!m_shmem.create(m_mem_name, size, m_addr))
+//            return 0;
+//         return m_shmem.get_address();
+//      }
+//      private:
+//      shared_memory &m_shmem;
+//      const char *m_mem_name;
+//      const void *m_addr;
+//   };
+
+   class group_services
+      :  public multi_segment_services
+   {
+      public:
+      typedef std::pair<void *, size_type>                  result_type;
+      typedef basic_managed_multi_shared_memory             frontend_t;
+      typedef typename
+         basic_managed_multi_shared_memory::void_pointer    void_pointer;
+      typedef typename void_pointer::segment_group_id       segment_group_id;
+      group_services(frontend_t *const frontend)
+         :  mp_frontend(frontend), m_group(0), m_min_segment_size(0){}
+
+      virtual std::pair<void *, size_type> create_new_segment(size_type alloc_size)
+      {  (void)alloc_size;
+         /*
+         //We should allocate an extra byte so that the
+         //[base_addr + alloc_size] byte belongs to this segment
+         alloc_size += 1;
+
+         //If requested size is less than minimum, update that
+         alloc_size = (m_min_segment_size > alloc_size) ?
+                       m_min_segment_size : alloc_size;
+         if(mp_frontend->priv_new_segment(create_open_func::DoCreate,
+                                          alloc_size, 0, permissions())){
+            typename shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin();
+            return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1);
+         }*/
+         return result_type(static_cast<void *>(0), 0);
+      }
+
+      virtual bool update_segments ()
+      {  return true;   }
+
+      virtual ~group_services(){}
+
+      void set_group(segment_group_id group)
+         {  m_group = group;  }
+
+      segment_group_id get_group() const
+         {  return m_group;  }
+
+      void set_min_segment_size(size_type min_segment_size)
+         {  m_min_segment_size = min_segment_size;  }
+
+      size_type get_min_segment_size() const
+         {  return m_min_segment_size;  }
+
+      private:
+
+      frontend_t * const   mp_frontend;
+      segment_group_id     m_group;
+      size_type            m_min_segment_size;
+   };
+
+   //!Functor to execute atomically when opening or creating a shared memory
+   //!segment.
+   struct create_open_func
+   {
+      enum type_t {  DoCreate, DoOpen, DoOpenOrCreate  };
+      typedef typename
+         basic_managed_multi_shared_memory::void_pointer   void_pointer;
+
+      create_open_func(self_t * const    frontend,
+                       type_t type, size_type segment_number)
+         : mp_frontend(frontend), m_type(type), m_segment_number(segment_number){}
+
+      bool operator()(void *addr, size_type size, bool created) const
+      {
+         if(((m_type == DoOpen)   &&  created) ||
+            ((m_type == DoCreate) && !created))
+            return false;
+         segment_group_id group = mp_frontend->m_group_services.get_group();
+         bool mapped       = false;
+         bool impl_done    = false;
+
+         //Associate this newly created segment as the
+         //segment id = 0 of this group
+         void_pointer::insert_mapping
+            ( group
+            , static_cast<char*>(addr) - managed_impl::ManagedOpenOrCreateUserOffset
+            , size + managed_impl::ManagedOpenOrCreateUserOffset);
+         //Check if this is the master segment
+         if(!m_segment_number){
+            //Create or open the Interprocess machinery
+            if((impl_done = created ?
+               mp_frontend->create_impl(addr, size) : mp_frontend->open_impl(addr, size))){
+               return true;
+            }
+         }
+         else{
+            return true;
+         }
+
+         //This is the cleanup part
+         //---------------
+         if(impl_done){
+            mp_frontend->close_impl();
+         }
+         if(mapped){
+            bool ret = void_pointer::erase_last_mapping(group);
+            BOOST_ASSERT(ret);(void)ret;
+         }
+         return false;
+      }
+      self_t * const    mp_frontend;
+      type_t            m_type;
+      size_type       m_segment_number;
+   };
+
+   //!Functor to execute atomically when closing a shared memory segment.
+   struct close_func
+   {
+      typedef typename
+         basic_managed_multi_shared_memory::void_pointer   void_pointer;
+
+      close_func(self_t * const frontend)
+         : mp_frontend(frontend){}
+
+      void operator()(const mapped_region &region, bool last) const
+      {
+         if(last) mp_frontend->destroy_impl();
+         else     mp_frontend->close_impl();
+      }
+      self_t * const    mp_frontend;
+   };
+
+   //Friend declarations
+   friend struct basic_managed_multi_shared_memory::create_open_func;
+   friend struct basic_managed_multi_shared_memory::close_func;
+   friend class basic_managed_multi_shared_memory::group_services;
+
+   typedef list<managed_impl> shmem_list_t;
+
+   basic_managed_multi_shared_memory *get_this_pointer()
+      {  return this;   }
+
+ public:
+
+   basic_managed_multi_shared_memory(create_only_t,
+                                     const char *name,
+                                     size_type size,
+                                     const permissions &perm = permissions())
+      :  m_group_services(get_this_pointer())
+   {
+      priv_open_or_create(create_open_func::DoCreate,name, size, perm);
+   }
+
+   basic_managed_multi_shared_memory(open_or_create_t,
+                                     const char *name,
+                                     size_type size,
+                                     const permissions &perm = permissions())
+      :  m_group_services(get_this_pointer())
+   {
+      priv_open_or_create(create_open_func::DoOpenOrCreate, name, size, perm);
+   }
+
+   basic_managed_multi_shared_memory(open_only_t, const char *name)
+      :  m_group_services(get_this_pointer())
+   {
+      priv_open_or_create(create_open_func::DoOpen, name, 0, permissions());
+   }
+
+   ~basic_managed_multi_shared_memory()
+      {  this->priv_close(); }
+
+   private:
+   bool  priv_open_or_create(typename create_open_func::type_t type,
+                             const char *name,
+                             size_type size,
+                             const permissions &perm)
+   {
+      if(!m_shmem_list.empty())
+         return false;
+      typename void_pointer::segment_group_id group = 0;
+      BOOST_TRY{
+         m_root_name = name;
+         //Insert multi segment services and get a group identifier
+         group = void_pointer::new_segment_group(&m_group_services);
+         size = void_pointer::round_size(size);
+         m_group_services.set_group(group);
+         m_group_services.set_min_segment_size(size);
+
+         if(group){
+            if(this->priv_new_segment(type, size, 0, perm)){
+               return true;
+            }
+         }
+      }
+      BOOST_CATCH(const std::bad_alloc&){
+      }
+      BOOST_CATCH_END
+      if(group){
+         void_pointer::delete_group(group);
+      }
+      return false;
+   }
+
+   bool  priv_new_segment(typename create_open_func::type_t type,
+                          size_type size,
+                          const void *addr,
+                          const permissions &perm)
+   {
+      BOOST_TRY{
+         //Get the number of groups of this multi_segment group
+         size_type segment_id  = m_shmem_list.size();
+         //Format the name of the shared memory: append segment number.
+         boost::interprocess::basic_ovectorstream<boost::interprocess::string> formatter;
+         //Pre-reserve string size
+         size_type str_size = m_root_name.length()+10;
+         if(formatter.vector().size() < str_size){
+            //This can throw.
+            formatter.reserve(str_size);
+         }
+         //Format segment's name
+         formatter << m_root_name
+                   << static_cast<unsigned int>(segment_id) << std::ends;
+         //This functor will be executed when constructing
+         create_open_func func(this, type, segment_id);
+         const char *name = formatter.vector().c_str();
+         //This can throw.
+         managed_impl mshm;
+
+         switch(type){
+            case create_open_func::DoCreate:
+            {
+               managed_impl shm(create_only, name, size, read_write, addr, func, perm);
+               mshm = boost::move(shm);
+            }
+            break;
+
+            case create_open_func::DoOpen:
+            {
+               managed_impl shm(open_only, name,read_write, addr, func);
+               mshm = boost::move(shm);
+            }
+            break;
+
+            case create_open_func::DoOpenOrCreate:
+            {
+               managed_impl shm(open_or_create, name, size, read_write, addr, func, perm);
+               mshm = boost::move(shm);
+            }
+            break;
+
+            default:
+               return false;
+            break;
+         }
+
+         //This can throw.
+         m_shmem_list.push_back(boost::move(mshm));
+         return true;
+      }
+      BOOST_CATCH(const std::bad_alloc&){
+      }
+      BOOST_CATCH_END
+      return false;
+   }
+
+   //!Frees resources. Never throws.
+   void priv_close()
+   {
+      if(!m_shmem_list.empty()){
+         bool ret;
+         //Obtain group identifier
+         segment_group_id group = m_group_services.get_group();
+         //Erase main segment and its resources
+         //typename shmem_list_t::iterator  itbeg = m_shmem_list.begin(),
+         //                        itend = m_shmem_list.end(),
+         //                        it    = itbeg;
+         //(*itbeg)->close_with_func(close_func(this));
+         //Delete group. All mappings are erased too.
+         ret = void_pointer::delete_group(group);
+         (void)ret;
+         BOOST_ASSERT(ret);
+         m_shmem_list.clear();
+      }
+   }
+
+   private:
+   shmem_list_t   m_shmem_list;
+   group_services m_group_services;
+   std::string    m_root_name;
+};
+
+typedef basic_managed_multi_shared_memory
+   < char
+   , rbtree_best_fit<mutex_family, intersegment_ptr<void> >
+   , iset_index>
+   managed_multi_shared_memory;
+
+}  //namespace interprocess {
+
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
+

+ 484 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/managed_open_or_create_impl.hpp

@@ -0,0 +1,484 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
+#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/interprocess_tester.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/move/move.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+namespace ipcdetail{ class interprocess_tester; }
+
+
+template<class DeviceAbstraction>
+struct managed_open_or_create_impl_device_id_t
+{
+   typedef const char *type;
+};
+
+#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+
+class xsi_shared_memory_file_wrapper;
+class xsi_key;
+
+template<>
+struct managed_open_or_create_impl_device_id_t<xsi_shared_memory_file_wrapper>
+{
+   typedef xsi_key type;
+};
+
+#endif   //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+
+/// @endcond
+
+namespace ipcdetail {
+
+
+template <bool StoreDevice, class DeviceAbstraction>
+class managed_open_or_create_impl_device_holder
+{
+   public:
+   DeviceAbstraction &get_device()
+   {  static DeviceAbstraction dev; return dev; }
+
+   const DeviceAbstraction &get_device() const
+   {  static DeviceAbstraction dev; return dev; }
+};
+
+template <class DeviceAbstraction>
+class managed_open_or_create_impl_device_holder<true, DeviceAbstraction>
+{
+   public:
+   DeviceAbstraction &get_device()
+   {  return dev; }
+
+   const DeviceAbstraction &get_device() const
+   {  return dev; }
+
+   private:
+   DeviceAbstraction dev;
+};
+
+template<class DeviceAbstraction, std::size_t MemAlignment = 0, bool FileBased = true, bool StoreDevice = true>
+class managed_open_or_create_impl
+   : public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction>
+{
+   //Non-copyable
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl)
+
+   typedef typename managed_open_or_create_impl_device_id_t<DeviceAbstraction>::type device_id_t;
+   typedef managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> DevHolder;
+   enum
+   {
+      UninitializedSegment,
+      InitializingSegment,
+      InitializedSegment,
+      CorruptedSegment
+   };
+
+   public:
+   static const std::size_t
+      ManagedOpenOrCreateUserOffset =
+         ct_rounded_size
+            < sizeof(boost::uint32_t)
+            , MemAlignment ? (MemAlignment) :
+               (::boost::alignment_of< ::boost::detail::max_align >::value)
+            >::value;
+
+   managed_open_or_create_impl()
+   {}
+
+   managed_open_or_create_impl(create_only_t,
+                 const device_id_t & id,
+                 std::size_t size,
+                 mode_t mode,
+                 const void *addr,
+                 const permissions &perm)
+   {
+      priv_open_or_create
+         ( DoCreate
+         , id
+         , size
+         , mode
+         , addr
+         , perm
+         , null_mapped_region_function());
+   }
+
+   managed_open_or_create_impl(open_only_t,
+                 const device_id_t & id,
+                 mode_t mode,
+                 const void *addr)
+   {
+      priv_open_or_create
+         ( DoOpen
+         , id
+         , 0
+         , mode
+         , addr
+         , permissions()
+         , null_mapped_region_function());
+   }
+
+
+   managed_open_or_create_impl(open_or_create_t,
+                 const device_id_t & id,
+                 std::size_t size,
+                 mode_t mode,
+                 const void *addr,
+                 const permissions &perm)
+   {
+      priv_open_or_create
+         ( DoOpenOrCreate
+         , id
+         , size
+         , mode
+         , addr
+         , perm
+         , null_mapped_region_function());
+   }
+
+   template <class ConstructFunc>
+   managed_open_or_create_impl(create_only_t,
+                 const device_id_t & id,
+                 std::size_t size,
+                 mode_t mode,
+                 const void *addr,
+                 const ConstructFunc &construct_func,
+                 const permissions &perm)
+   {
+      priv_open_or_create
+         (DoCreate
+         , id
+         , size
+         , mode
+         , addr
+         , perm
+         , construct_func);
+   }
+
+   template <class ConstructFunc>
+   managed_open_or_create_impl(open_only_t,
+                 const device_id_t & id,
+                 mode_t mode,
+                 const void *addr,
+                 const ConstructFunc &construct_func)
+   {
+      priv_open_or_create
+         ( DoOpen
+         , id
+         , 0
+         , mode
+         , addr
+         , permissions()
+         , construct_func);
+   }
+
+   template <class ConstructFunc>
+   managed_open_or_create_impl(open_or_create_t,
+                 const device_id_t & id,
+                 std::size_t size,
+                 mode_t mode,
+                 const void *addr,
+                 const ConstructFunc &construct_func,
+                 const permissions &perm)
+   {
+      priv_open_or_create
+         ( DoOpenOrCreate
+         , id
+         , size
+         , mode
+         , addr
+         , perm
+         , construct_func);
+   }
+
+   managed_open_or_create_impl(BOOST_RV_REF(managed_open_or_create_impl) moved)
+   {  this->swap(moved);   }
+
+   managed_open_or_create_impl &operator=(BOOST_RV_REF(managed_open_or_create_impl) moved)
+   {
+      managed_open_or_create_impl tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   ~managed_open_or_create_impl()
+   {}
+
+   std::size_t get_user_size()  const
+   {  return m_mapped_region.get_size() - ManagedOpenOrCreateUserOffset; }
+
+   void *get_user_address()  const
+   {  return static_cast<char*>(m_mapped_region.get_address()) + ManagedOpenOrCreateUserOffset;  }
+
+   std::size_t get_real_size()  const
+   {  return m_mapped_region.get_size(); }
+
+   void *get_real_address()  const
+   {  return m_mapped_region.get_address();  }
+
+   void swap(managed_open_or_create_impl &other)
+   {
+      this->m_mapped_region.swap(other.m_mapped_region);
+   }
+
+   bool flush()
+   {  return m_mapped_region.flush();  }
+
+   const mapped_region &get_mapped_region() const
+   {  return m_mapped_region;  }
+
+
+   DeviceAbstraction &get_device()
+   {  return this->DevHolder::get_device(); }
+
+   const DeviceAbstraction &get_device() const
+   {  return this->DevHolder::get_device(); }
+
+   private:
+
+   //These are templatized to allow explicit instantiations
+   template<bool dummy>
+   static void truncate_device(DeviceAbstraction &, offset_t, false_)
+   {} //Empty
+
+   template<bool dummy>
+   static void truncate_device(DeviceAbstraction &dev, offset_t size, true_)
+   {  dev.truncate(size);  }
+
+
+   template<bool dummy>
+   static bool check_offset_t_size(std::size_t , false_)
+   { return true; } //Empty
+
+   template<bool dummy>
+   static bool check_offset_t_size(std::size_t size, true_)
+   { return size == std::size_t(offset_t(size)); }
+
+   //These are templatized to allow explicit instantiations
+   template<bool dummy>
+   static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t size, const permissions &perm, false_ file_like)
+   {
+      (void)file_like;
+      DeviceAbstraction tmp(create_only, id, read_write, size, perm);
+      tmp.swap(dev);
+   }
+
+   template<bool dummy>
+   static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t, const permissions &perm, true_ file_like)
+   {
+      (void)file_like;
+      DeviceAbstraction tmp(create_only, id, read_write, perm);
+      tmp.swap(dev);
+   }
+
+   template <class ConstructFunc> inline
+   void priv_open_or_create
+      (create_enum_t type,
+       const device_id_t & id,
+       std::size_t size,
+       mode_t mode, const void *addr,
+       const permissions &perm,
+       ConstructFunc construct_func)
+   {
+      typedef bool_<FileBased> file_like_t;
+      (void)mode;
+      error_info err;
+      bool created = false;
+      bool ronly   = false;
+      bool cow     = false;
+      DeviceAbstraction dev;
+
+      if(type != DoOpen && size < ManagedOpenOrCreateUserOffset){
+         throw interprocess_exception(error_info(size_error));
+      }
+      //Check size can be represented by offset_t (used by truncate)
+      if(type != DoOpen && !check_offset_t_size<FileBased>(size, file_like_t())){
+         throw interprocess_exception(error_info(size_error));
+      }
+      if(type == DoOpen && mode == read_write){
+         DeviceAbstraction tmp(open_only, id, read_write);
+         tmp.swap(dev);
+         created = false;
+      }
+      else if(type == DoOpen && mode == read_only){
+         DeviceAbstraction tmp(open_only, id, read_only);
+         tmp.swap(dev);
+         created = false;
+         ronly   = true;
+      }
+      else if(type == DoOpen && mode == copy_on_write){
+         DeviceAbstraction tmp(open_only, id, read_only);
+         tmp.swap(dev);
+         created = false;
+         cow     = true;
+      }
+      else if(type == DoCreate){
+         create_device<FileBased>(dev, id, size, perm, file_like_t());
+         created = true;
+      }
+      else if(type == DoOpenOrCreate){
+         //This loop is very ugly, but brute force is sometimes better
+         //than diplomacy. If someone knows how to open or create a
+         //file and know if we have really created it or just open it
+         //drop me a e-mail!
+         bool completed = false;
+         while(!completed){
+            try{
+               create_device<FileBased>(dev, id, size, perm, file_like_t());
+               created     = true;
+               completed   = true;
+            }
+            catch(interprocess_exception &ex){
+               if(ex.get_error_code() != already_exists_error){
+                  throw;
+               }
+               else{
+                  try{
+                     DeviceAbstraction tmp(open_only, id, read_write);
+                     dev.swap(tmp);
+                     created     = false;
+                     completed   = true;
+                  }
+                  catch(interprocess_exception &ex){
+                     if(ex.get_error_code() != not_found_error){
+                        throw;
+                     }
+                  }
+                  catch(...){
+                     throw;
+                  }
+               }
+            }
+            catch(...){
+               throw;
+            }
+            thread_yield();
+         }
+      }
+
+      if(created){
+         try{
+            //If this throws, we are lost
+            truncate_device<FileBased>(dev, size, file_like_t());
+
+            //If the following throws, we will truncate the file to 1
+            mapped_region        region(dev, read_write, 0, 0, addr);
+            boost::uint32_t *patomic_word = 0;  //avoid gcc warning
+            patomic_word = static_cast<boost::uint32_t*>(region.get_address());
+            boost::uint32_t previous = atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment);
+
+            if(previous == UninitializedSegment){
+               try{
+                  construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
+                                , size - ManagedOpenOrCreateUserOffset, true);
+                  //All ok, just move resources to the external mapped region
+                  m_mapped_region.swap(region);
+               }
+               catch(...){
+                  atomic_write32(patomic_word, CorruptedSegment);
+                  throw;
+               }
+               atomic_write32(patomic_word, InitializedSegment);
+            }
+            else if(previous == InitializingSegment || previous == InitializedSegment){
+               throw interprocess_exception(error_info(already_exists_error));
+            }
+            else{
+               throw interprocess_exception(error_info(corrupted_error));
+            }
+         }
+         catch(...){
+            try{
+               truncate_device<FileBased>(dev, 1u, file_like_t());
+            }
+            catch(...){
+            }
+            throw;
+         }
+      }
+      else{
+         if(FileBased){
+            offset_t filesize = 0;
+            while(filesize == 0){
+               if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
+                  throw interprocess_exception(error_info(system_error_code()));
+               }
+               thread_yield();
+            }
+            if(filesize == 1){
+               throw interprocess_exception(error_info(corrupted_error));
+            }
+         }
+
+         mapped_region  region(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr);
+
+         boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
+         boost::uint32_t value = atomic_read32(patomic_word);
+
+         while(value == InitializingSegment || value == UninitializedSegment){
+            thread_yield();
+            value = atomic_read32(patomic_word);
+         }
+
+         if(value != InitializedSegment)
+            throw interprocess_exception(error_info(corrupted_error));
+
+         construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
+                        , region.get_size() - ManagedOpenOrCreateUserOffset
+                        , false);
+         //All ok, just move resources to the external mapped region
+         m_mapped_region.swap(region);
+      }
+      if(StoreDevice){
+         this->DevHolder::get_device() = boost::move(dev);
+      }
+   }
+
+   private:
+   friend class interprocess_tester;
+   void dont_close_on_destruction()
+   {  interprocess_tester::dont_close_on_destruction(m_mapped_region);  }
+
+   mapped_region     m_mapped_region;
+};
+
+template<class DeviceAbstraction>
+inline void swap(managed_open_or_create_impl<DeviceAbstraction> &x
+                ,managed_open_or_create_impl<DeviceAbstraction> &y)
+{  x.swap(y);  }
+
+}  //namespace ipcdetail {
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL

+ 110 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/math_functions.hpp

@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Stephen Cleary 2000.
+// (C) Copyright Ion Gaztanaga 2007-2012.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+// This file is a slightly modified file from Boost.Pool
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
+#define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
+
+#include <climits>
+#include <boost/static_assert.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+// Greatest common divisor and least common multiple
+
+//
+// gcd is an algorithm that calculates the greatest common divisor of two
+//  integers, using Euclid's algorithm.
+//
+// Pre: A > 0 && B > 0
+// Recommended: A > B
+template <typename Integer>
+inline Integer gcd(Integer A, Integer B)
+{
+   do
+   {
+      const Integer tmp(B);
+      B = A % B;
+      A = tmp;
+   } while (B != 0);
+
+   return A;
+}
+
+//
+// lcm is an algorithm that calculates the least common multiple of two
+//  integers.
+//
+// Pre: A > 0 && B > 0
+// Recommended: A > B
+template <typename Integer>
+inline Integer lcm(const Integer & A, const Integer & B)
+{
+   Integer ret = A;
+   ret /= gcd(A, B);
+   ret *= B;
+   return ret;
+}
+
+template <typename Integer>
+inline Integer log2_ceil(const Integer & A)
+{
+   Integer i = 0;
+   Integer power_of_2 = 1;
+
+   while(power_of_2 < A){
+      power_of_2 <<= 1;
+      ++i;
+   }
+   return i;
+}
+
+template <typename Integer>
+inline Integer upper_power_of_2(const Integer & A)
+{
+   Integer power_of_2 = 1;
+
+   while(power_of_2 < A){
+      power_of_2 <<= 1;
+   }
+   return power_of_2;
+}
+
+//This function uses binary search to discover the
+//highest set bit of the integer
+inline std::size_t floor_log2 (std::size_t x)
+{
+   const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
+   const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
+   BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true));
+
+   std::size_t n = x;
+   std::size_t log2 = 0;
+
+   for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
+      std::size_t tmp = n >> shift;
+      if (tmp)
+         log2 += shift, n = tmp;
+   }
+
+   return log2;
+}
+
+} // namespace ipcdetail
+} // namespace interprocess
+} // namespace boost
+
+#endif

+ 40 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/min_max.hpp

@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
+#define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+namespace boost {
+namespace interprocess {
+
+template<class T>
+const T &max_value(const T &a, const T &b)
+{  return a > b ? a : b;   }
+
+template<class T>
+const T &min_value(const T &a, const T &b)
+{  return a < b ? a : b;   }
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
+

+ 28 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/move.hpp

@@ -0,0 +1,28 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2010-2012.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP
+#define BOOST_INTERPROCESS_DETAIL_MOVE_HPP
+
+#include <boost/move/move.hpp>
+
+namespace boost {
+namespace interprocess {
+
+using ::boost::move;
+using ::boost::forward;
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP

+ 152 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/mpl.hpp

@@ -0,0 +1,152 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
+#define BOOST_INTERPROCESS_DETAIL_MPL_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <cstddef>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template <class T, T val>
+struct integral_constant
+{
+   static const T value = val;
+   typedef integral_constant<T,val> type;
+};
+
+template< bool C_ >
+struct bool_ : integral_constant<bool, C_>
+{
+   static const bool value = C_;
+};
+
+typedef bool_<true>        true_;
+typedef bool_<false>       false_;
+
+typedef true_  true_type;
+typedef false_ false_type;
+
+typedef char yes_type;
+struct no_type
+{
+   char padding[8];
+};
+
+template <bool B, class T = void>
+struct enable_if_c {
+  typedef T type;
+};
+
+template <class T>
+struct enable_if_c<false, T> {};
+
+template <class Cond, class T = void>
+struct enable_if : public enable_if_c<Cond::value, T> {};
+
+template <class Cond, class T = void>
+struct disable_if : public enable_if_c<!Cond::value, T> {};
+
+template <class T, class U>
+class is_convertible
+{
+   typedef char true_t;
+   class false_t { char dummy[2]; };
+   static true_t dispatch(U);
+   static false_t dispatch(...);
+   static T trigger();
+   public:
+   static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
+};
+
+template<
+      bool C
+    , typename T1
+    , typename T2
+    >
+struct if_c
+{
+    typedef T1 type;
+};
+
+template<
+      typename T1
+    , typename T2
+    >
+struct if_c<false,T1,T2>
+{
+    typedef T2 type;
+};
+
+template<
+      typename T1
+    , typename T2
+    , typename T3
+    >
+struct if_
+{
+   typedef typename if_c<0 != T1::value, T2, T3>::type type;
+};
+
+
+template <class Pair>
+struct select1st
+//   : public std::unary_function<Pair, typename Pair::first_type>
+{
+   template<class OtherPair>
+   const typename Pair::first_type& operator()(const OtherPair& x) const
+   {  return x.first;   }
+
+   const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
+   {  return x;   }
+};
+
+// identity is an extension: it is not part of the standard.
+template <class T>
+struct identity
+//   : public std::unary_function<T,T>
+{
+   typedef T type;
+   const T& operator()(const T& x) const
+   { return x; }
+};
+
+template<std::size_t S>
+struct ls_zeros
+{
+   static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
+};
+
+template<>
+struct ls_zeros<0>
+{
+   static const std::size_t value = 0;
+};
+
+template<>
+struct ls_zeros<1>
+{
+   static const std::size_t value = 0;
+};
+
+}  //namespace ipcdetail {
+}  //namespace interprocess {
+}  //namespace boost {
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
+

+ 46 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/multi_segment_services.hpp

@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
+#define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+
+/*!\file
+   Describes a named shared memory allocation user class.
+*/
+
+namespace boost {
+
+namespace interprocess {
+
+class multi_segment_services
+{
+   public:
+   virtual std::pair<void *, std::size_t> create_new_segment(std::size_t mem) = 0;
+   virtual bool                           update_segments   () = 0;
+   virtual ~multi_segment_services() = 0;
+};
+
+inline multi_segment_services::~multi_segment_services()
+{}
+
+
+}} //namespace boost {  namespace interprocess {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifdef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP

+ 349 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/named_proxy.hpp

@@ -0,0 +1,349 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
+#define BOOST_INTERPROCESS_NAMED_PROXY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <new>
+#include <iterator>
+#include <boost/interprocess/detail/in_place_interface.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#include <boost/interprocess/detail/preprocessor.hpp>
+#else
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/variadic_templates_tools.hpp>
+#endif   //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+//!\file
+//!Describes a proxy class that implements named allocation syntax.
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+template<class T, bool is_iterator, class ...Args>
+struct CtorNArg : public placement_destroy<T>
+{
+   typedef bool_<is_iterator> IsIterator;
+   typedef CtorNArg<T, is_iterator, Args...> self_t;
+   typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
+
+   self_t& operator++()
+   {
+      this->do_increment(IsIterator(), index_tuple_t());
+      return *this;
+   }
+
+   self_t  operator++(int) {  return ++*this;   *this;  }
+
+   CtorNArg(Args && ...args)
+      :  args_(args...)
+   {}
+
+   virtual void construct_n(void *mem
+                     , std::size_t num
+                     , std::size_t &constructed)
+   {
+      T* memory      = static_cast<T*>(mem);
+      for(constructed = 0; constructed < num; ++constructed){
+         this->construct(memory++, IsIterator(), index_tuple_t());
+         this->do_increment(IsIterator(), index_tuple_t());
+      }
+   }
+
+   private:
+   template<int ...IdxPack>
+   void construct(void *mem, true_, const index_tuple<IdxPack...>&)
+   {  new((void*)mem)T(*boost::forward<Args>(get<IdxPack>(args_))...); }
+
+   template<int ...IdxPack>
+   void construct(void *mem, false_, const index_tuple<IdxPack...>&)
+   {  new((void*)mem)T(boost::forward<Args>(get<IdxPack>(args_))...); }
+
+   template<int ...IdxPack>
+   void do_increment(true_, const index_tuple<IdxPack...>&)
+   {
+      this->expansion_helper(++get<IdxPack>(args_)...);
+   }
+
+   template<class ...ExpansionArgs>
+   void expansion_helper(ExpansionArgs &&...)
+   {}
+
+   template<int ...IdxPack>
+   void do_increment(false_, const index_tuple<IdxPack...>&)
+   {}
+
+   tuple<Args&...> args_;
+};
+
+//!Describes a proxy class that implements named
+//!allocation syntax.
+template
+   < class SegmentManager  //segment manager to construct the object
+   , class T               //type of object to build
+   , bool is_iterator      //passing parameters are normal object or iterators?
+   >
+class named_proxy
+{
+   typedef typename SegmentManager::char_type char_type;
+   const char_type *    mp_name;
+   SegmentManager *     mp_mngr;
+   mutable std::size_t  m_num;
+   const bool           m_find;
+   const bool           m_dothrow;
+
+   public:
+   named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
+      :  mp_name(name), mp_mngr(mngr), m_num(1)
+      ,  m_find(find),  m_dothrow(dothrow)
+   {}
+
+   template<class ...Args>
+   T *operator()(Args &&...args) const
+   {
+      CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...>
+         (boost::forward<Args>(args)...);
+      return mp_mngr->template
+         generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
+   }
+
+   //This operator allows --> named_new("Name")[3]; <-- syntax
+   const named_proxy &operator[](std::size_t num) const
+   {  m_num *= num; return *this;  }
+};
+
+#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+//!Function object that makes placement new
+//!without arguments
+template<class T>
+struct Ctor0Arg   :  public placement_destroy<T>
+{
+   typedef Ctor0Arg self_t;
+
+   Ctor0Arg(){}
+
+   self_t& operator++()       {  return *this;  }
+   self_t  operator++(int)    {  return *this;  }
+
+   void construct(void *mem)
+   {  new((void*)mem)T;  }
+
+   virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
+   {
+      T* memory = static_cast<T*>(mem);
+      for(constructed = 0; constructed < num; ++constructed)
+         new((void*)memory++)T;
+   }
+};
+
+////////////////////////////////////////////////////////////////
+//    What the macro should generate (n == 2):
+//
+//    template<class T, bool is_iterator, class P1, class P2>
+//    struct Ctor2Arg
+//      :  public placement_destroy<T>
+//    {
+//       typedef bool_<is_iterator> IsIterator;
+//       typedef Ctor2Arg self_t;
+//
+//       void do_increment(false_)
+//       { ++m_p1; ++m_p2;  }
+//
+//       void do_increment(true_){}
+//
+//       self_t& operator++()
+//       {
+//          this->do_increment(IsIterator());
+//          return *this;
+//       }
+//
+//       self_t  operator++(int) {  return ++*this;   *this;  }
+//
+//       Ctor2Arg(const P1 &p1, const P2 &p2)
+//          : p1((P1 &)p_1), p2((P2 &)p_2) {}
+//
+//       void construct(void *mem)
+//       {  new((void*)object)T(m_p1, m_p2); }
+//
+//       virtual void construct_n(void *mem
+//                                , std::size_t num
+//                                , std::size_t &constructed)
+//       {
+//          T* memory      = static_cast<T*>(mem);
+//          for(constructed = 0; constructed < num; ++constructed){
+//             this->construct(memory++, IsIterator());
+//             this->do_increment(IsIterator());
+//          }
+//       }
+//
+//       private:
+//       void construct(void *mem, true_)
+//       {  new((void*)mem)T(*m_p1, *m_p2); }
+//
+//       void construct(void *mem, false_)
+//       {  new((void*)mem)T(m_p1, m_p2); }
+//
+//       P1 &m_p1; P2 &m_p2;
+//    };
+////////////////////////////////////////////////////////////////
+
+//Note:
+//We define template parameters as const references to
+//be able to bind temporaries. After that we will un-const them.
+//This cast is ugly but it is necessary until "perfect forwarding"
+//is achieved in C++0x. Meanwhile, if we want to be able to
+//bind lvalues with non-const references, we have to be ugly
+#define BOOST_PP_LOCAL_MACRO(n)                                            \
+   template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) >  \
+   struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg)                         \
+      :  public placement_destroy<T>                                       \
+   {                                                                       \
+      typedef bool_<is_iterator> IsIterator;                               \
+      typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t;             \
+                                                                           \
+      void do_increment(true_)                                             \
+         { BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INC, _); }         \
+                                                                           \
+      void do_increment(false_){}                                          \
+                                                                           \
+      self_t& operator++()                                                 \
+      {                                                                    \
+         this->do_increment(IsIterator());                                 \
+         return *this;                                                     \
+      }                                                                    \
+                                                                           \
+      self_t  operator++(int) {  return ++*this;   *this;  }               \
+                                                                           \
+      BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg)                             \
+         ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) )        \
+         : BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_INIT, _) {}       \
+                                                                           \
+      virtual void construct_n(void *mem                                   \
+                        , std::size_t num                                  \
+                        , std::size_t &constructed)                        \
+      {                                                                    \
+         T* memory      = static_cast<T*>(mem);                            \
+         for(constructed = 0; constructed < num; ++constructed){           \
+            this->construct(memory++, IsIterator());                       \
+            this->do_increment(IsIterator());                              \
+         }                                                                 \
+      }                                                                    \
+                                                                           \
+      private:                                                             \
+      void construct(void *mem, true_)                                     \
+      {                                                                    \
+         new((void*)mem) T                                                 \
+         (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _));   \
+      }                                                                    \
+                                                                           \
+      void construct(void *mem, false_)                                    \
+      {                                                                    \
+         new((void*)mem) T                                                 \
+            (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _));   \
+      }                                                                    \
+                                                                           \
+      BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_PP_PARAM_DEFINE, _)            \
+   };                                                                      \
+//!
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+#include BOOST_PP_LOCAL_ITERATE()
+
+//!Describes a proxy class that implements named
+//!allocation syntax.
+template
+   < class SegmentManager  //segment manager to construct the object
+   , class T               //type of object to build
+   , bool is_iterator      //passing parameters are normal object or iterators?
+   >
+class named_proxy
+{
+   typedef typename SegmentManager::char_type char_type;
+   const char_type *    mp_name;
+   SegmentManager *     mp_mngr;
+   mutable std::size_t  m_num;
+   const bool           m_find;
+   const bool           m_dothrow;
+
+   public:
+   named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
+      :  mp_name(name), mp_mngr(mngr), m_num(1)
+      ,  m_find(find),  m_dothrow(dothrow)
+   {}
+
+   //!makes a named allocation and calls the
+   //!default constructor
+   T *operator()() const
+   {
+      Ctor0Arg<T> ctor_obj;
+      return mp_mngr->template
+         generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
+   }
+   //!
+
+   #define BOOST_PP_LOCAL_MACRO(n)                                               \
+      template<BOOST_PP_ENUM_PARAMS(n, class P)>                                 \
+      T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\
+      {                                                                          \
+         typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg)                        \
+            <T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)>                         \
+            ctor_obj_t;                                                          \
+         ctor_obj_t ctor_obj                                                     \
+            (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _));          \
+         return mp_mngr->template generic_construct<T>                           \
+            (mp_name, m_num, m_find, m_dothrow, ctor_obj);                       \
+      }                                                                          \
+   //!
+
+   #define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS )
+   #include BOOST_PP_LOCAL_ITERATE()
+
+   ////////////////////////////////////////////////////////////////////////
+   //             What the macro should generate (n == 2)
+   ////////////////////////////////////////////////////////////////////////
+   //
+   // template <class P1, class P2>
+   // T *operator()(P1 &p1, P2 &p2) const
+   // {
+   //    typedef Ctor2Arg
+   //       <T, is_iterator, P1, P2>
+   //       ctor_obj_t;
+   //    ctor_obj_t ctor_obj(p1, p2);
+   //
+   //    return mp_mngr->template generic_construct<T>
+   //       (mp_name, m_num, m_find, m_dothrow, ctor_obj);
+   // }
+   //
+   //////////////////////////////////////////////////////////////////////////
+
+   //This operator allows --> named_new("Name")[3]; <-- syntax
+   const named_proxy &operator[](std::size_t num) const
+      {  m_num *= num; return *this;  }
+};
+
+#endif   //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+}}}   //namespace boost { namespace interprocess { namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP

+ 696 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/os_file_functions.hpp

@@ -0,0 +1,696 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
+#define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/permissions.hpp>
+
+#include <string>
+#include <limits>
+#include <climits>
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+#  include <boost/interprocess/detail/win32_api.hpp>
+#else
+#  ifdef BOOST_HAS_UNISTD_H
+#     include <fcntl.h>
+#     include <unistd.h>
+#     include <sys/types.h>
+#     include <sys/stat.h>
+#     include <errno.h>
+#     include <cstdio>
+#     include <dirent.h>
+#     if 0
+#        include <sys/file.h>
+#     endif
+#  else
+#    error Unknown platform
+#  endif
+#endif
+
+#include <cstring>
+#include <cstdlib>
+
+namespace boost {
+namespace interprocess {
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef void *             file_handle_t;
+typedef long long          offset_t;
+typedef struct mapping_handle_impl_t{
+   void *   handle;
+   bool     is_shm;
+}  mapping_handle_t;
+
+typedef enum { read_only      = winapi::generic_read
+             , read_write     = winapi::generic_read | winapi::generic_write
+             , copy_on_write
+             , read_private
+             , invalid_mode   = 0xffff
+             } mode_t;
+
+typedef enum { file_begin     = winapi::file_begin
+             , file_end       = winapi::file_end
+             , file_current   = winapi::file_current
+             } file_pos_t;
+
+namespace ipcdetail{
+
+inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
+{
+   mapping_handle_t ret;
+   ret.handle = hnd;
+   ret.is_shm = false;
+   return ret;
+}
+
+inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
+{
+   mapping_handle_t ret;
+   ret.handle = hnd;
+   ret.is_shm = true;
+   return ret;
+}
+
+inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
+{  return hnd.handle; }
+
+inline bool create_directory(const char *path)
+{  return winapi::create_directory(path); }
+
+inline const char *get_temporary_path()
+{  return std::getenv("TMP"); }
+
+
+inline file_handle_t create_new_file
+   (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+   unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
+   return winapi::create_file
+      ( name, (unsigned int)mode, winapi::create_new, attr
+      , (winapi::interprocess_security_attributes*)perm.get_permissions());
+}
+
+inline file_handle_t create_or_open_file
+   (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+   unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
+   return winapi::create_file
+      ( name, (unsigned int)mode, winapi::open_always, attr
+      , (winapi::interprocess_security_attributes*)perm.get_permissions());
+}
+
+inline file_handle_t open_existing_file
+   (const char *name, mode_t mode, bool temporary = false)
+{
+   unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
+   return winapi::create_file
+      (name, (unsigned int)mode, winapi::open_existing, attr, 0);
+}
+
+inline bool delete_file(const char *name)
+{  return winapi::unlink_file(name);   }
+
+inline bool truncate_file (file_handle_t hnd, std::size_t size)
+{
+   offset_t filesize;
+   if(!winapi::get_file_size(hnd, filesize))
+      return false;
+
+   const offset_t max_filesize = (std::numeric_limits<offset_t>::max)();
+   //Avoid unused variable warnings in 32 bit systems
+   (void)max_filesize;
+   if( sizeof(std::size_t) >= sizeof(offset_t) && size > std::size_t(max_filesize) ){
+      winapi::set_last_error(winapi::error_file_too_large);
+      return false;
+   }
+
+   if(offset_t(size) > filesize){
+      if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
+         return false;
+      }
+      //We will write zeros in the end of the file
+      //since set_end_of_file does not guarantee this
+      for(std::size_t remaining = size - filesize, write_size = 0
+         ;remaining > 0
+         ;remaining -= write_size){
+         const std::size_t DataSize = 512;
+         static char data [DataSize];
+         write_size = DataSize < remaining ? DataSize : remaining;
+         unsigned long written;
+         winapi::write_file(hnd, data, (unsigned long)write_size, &written, 0);
+         if(written != write_size){
+            return false;
+         }
+      }
+   }
+   else{
+      if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
+         return false;
+      }
+      if(!winapi::set_end_of_file(hnd)){
+         return false;
+      }
+   }
+   return true;
+}
+
+inline bool get_file_size(file_handle_t hnd, offset_t &size)
+{  return winapi::get_file_size(hnd, size);  }
+
+inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
+{  return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); }
+
+inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
+{  return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
+
+inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
+{
+   unsigned long written;
+   return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0);
+}
+
+inline file_handle_t invalid_file()
+{  return winapi::invalid_handle_value;  }
+
+inline bool close_file(file_handle_t hnd)
+{  return 0 != winapi::close_handle(hnd);   }
+
+inline bool acquire_file_lock(file_handle_t hnd)
+{
+   static winapi::interprocess_overlapped overlapped;
+   const unsigned long len = ((unsigned long)-1);
+//   winapi::interprocess_overlapped overlapped;
+//   std::memset(&overlapped, 0, sizeof(overlapped));
+   return winapi::lock_file_ex
+      (hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped);
+}
+
+inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
+{
+   const unsigned long len = ((unsigned long)-1);
+   winapi::interprocess_overlapped overlapped;
+   std::memset(&overlapped, 0, sizeof(overlapped));
+   if(!winapi::lock_file_ex
+      (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately,
+       0, len, len, &overlapped)){
+      return winapi::get_last_error() == winapi::error_lock_violation ?
+               acquired = false, true : false;
+
+   }
+   return (acquired = true);
+}
+
+inline bool release_file_lock(file_handle_t hnd)
+{
+   const unsigned long len = ((unsigned long)-1);
+   winapi::interprocess_overlapped overlapped;
+   std::memset(&overlapped, 0, sizeof(overlapped));
+   return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped);
+}
+
+inline bool acquire_file_lock_sharable(file_handle_t hnd)
+{
+   const unsigned long len = ((unsigned long)-1);
+   winapi::interprocess_overlapped overlapped;
+   std::memset(&overlapped, 0, sizeof(overlapped));
+   return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped);
+}
+
+inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
+{
+   const unsigned long len = ((unsigned long)-1);
+   winapi::interprocess_overlapped overlapped;
+   std::memset(&overlapped, 0, sizeof(overlapped));
+   if(!winapi::lock_file_ex
+      (hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){
+      return winapi::get_last_error() == winapi::error_lock_violation ?
+               acquired = false, true : false;
+   }
+   return (acquired = true);
+}
+
+inline bool release_file_lock_sharable(file_handle_t hnd)
+{  return release_file_lock(hnd);   }
+
+inline bool delete_subdirectories_recursive
+   (const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
+{
+   bool               bSubdirectory = false;       // Flag, indicating whether
+                                                   // subdirectories have been found
+   void *             hFile;                       // Handle to directory
+   std::string        strFilePath;                 // Filepath
+   std::string        strPattern;                  // Pattern
+   winapi::win32_find_data_t  FileInformation;     // File information
+
+   //Find all files and directories
+   strPattern = refcstrRootDirectory + "\\*.*";
+   hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
+   if(hFile != winapi::invalid_handle_value){
+      do{
+         //If it's not "." or ".." or the pointed root_level dont_delete_this erase it
+         if(FileInformation.cFileName[0] != '.' &&
+            !(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
+            strFilePath.erase();
+            strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
+
+            //If it's a directory, go recursive
+            if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
+               // Delete subdirectory
+               if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1))
+                  return false;
+            }
+            //If it's a file, just delete it
+            else{
+               // Set file attributes
+               //if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
+               //return winapi::get_last_error();
+               // Delete file
+               winapi::delete_file(strFilePath.c_str());
+            }
+         }
+      //Go to the next file
+      } while(winapi::find_next_file(hFile, &FileInformation) == 1);
+
+      // Close handle
+      winapi::find_close(hFile);
+
+      //See if the loop has ended with an error or just because we've traversed all the files
+      if(winapi::get_last_error() != winapi::error_no_more_files){
+         return false;
+      }
+      else
+      {
+         //Erase empty subdirectories or original refcstrRootDirectory
+         if(!bSubdirectory && count)
+         {
+            // Set directory attributes
+            //if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0)
+               //return ::GetLastError();
+            // Delete directory
+            if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0)
+               return false;
+         }
+      }
+   }
+   return true;
+}
+
+//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
+inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
+{
+   return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
+}
+
+
+template<class Function>
+inline bool for_each_file_in_dir(const char *dir, Function f)
+{
+   void *             hFile;                       // Handle to directory
+   winapi::win32_find_data_t  FileInformation;     // File information
+
+   //Get base directory
+   std::string str(dir);
+   const std::size_t base_root_dir_len = str.size();
+
+   //Find all files and directories
+   str  +=  "\\*.*";
+   hFile = winapi::find_first_file(str.c_str(), &FileInformation);
+   if(hFile != winapi::invalid_handle_value){
+      do{   //Now loop every file
+         str.erase(base_root_dir_len);
+         //If it's not "." or ".." skip it
+         if(FileInformation.cFileName[0] != '.'){
+            str += "\\";   str += FileInformation.cFileName;
+            //If it's a file, apply erase logic
+            if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){
+               f(str.c_str(), FileInformation.cFileName);
+            }
+         }
+      //Go to the next file
+      } while(winapi::find_next_file(hFile, &FileInformation) == 1);
+
+      // Close handle and see if the loop has ended with an error
+      winapi::find_close(hFile);
+      if(winapi::get_last_error() != winapi::error_no_more_files){
+         return false;
+      }
+   }
+   return true;
+}
+
+
+#else    //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef int       file_handle_t;
+typedef off_t     offset_t;
+
+typedef struct mapping_handle_impl_t
+{
+   file_handle_t  handle;
+   bool           is_xsi;
+}  mapping_handle_t;
+
+typedef enum { read_only      = O_RDONLY
+             , read_write     = O_RDWR
+             , copy_on_write
+             , read_private
+             , invalid_mode   = 0xffff
+             } mode_t;
+
+typedef enum { file_begin     = SEEK_SET
+             , file_end       = SEEK_END
+             , file_current   = SEEK_CUR
+             } file_pos_t;
+
+namespace ipcdetail{
+
+inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
+{
+   mapping_handle_t ret;
+   ret.handle = hnd;
+   ret.is_xsi = false;
+   return ret;
+}
+
+inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
+{  return hnd.handle; }
+
+inline bool create_directory(const char *path)
+{  return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
+
+inline const char *get_temporary_path()
+{
+   const char *names[] = {"/tmp", "TMPDIR", "TMP", "TEMP" };
+   const int names_size = sizeof(names)/sizeof(names[0]);
+   struct stat data;
+   for(int i = 0; i != names_size; ++i){
+      if(::stat(names[i], &data) == 0){
+         return names[i];
+      }
+   }
+   return "/tmp";
+}
+
+inline file_handle_t create_new_file
+   (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+   (void)temporary;
+   int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
+   if(ret >= 0){
+      ::fchmod(ret, perm.get_permissions());
+   }
+   return ret;
+}
+
+inline file_handle_t create_or_open_file
+   (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
+{
+   (void)temporary;
+   int ret = -1;
+   //We need a loop to change permissions correctly using fchmod, since
+   //with "O_CREAT only" ::open we don't know if we've created or opened the file.
+   while(1){
+      ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
+      if(ret >= 0){
+         ::fchmod(ret, perm.get_permissions());
+         break;
+      }
+      else if(errno == EEXIST){
+         if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){
+            break;
+         }
+      }
+   }
+   return ret;
+}
+
+inline file_handle_t open_existing_file
+   (const char *name, mode_t mode, bool temporary = false)
+{
+   (void)temporary;
+   return ::open(name, (int)mode);
+}
+
+inline bool delete_file(const char *name)
+{  return ::unlink(name) == 0;   }
+
+inline bool truncate_file (file_handle_t hnd, std::size_t size)
+{
+   if(sizeof(off_t) == sizeof(std::size_t)){
+      if(size > ((~std::size_t(0)) >> 1)){
+         errno = EINVAL;
+         return false;
+      }
+   }
+   return 0 == ::ftruncate(hnd, off_t(size));
+}
+
+inline bool get_file_size(file_handle_t hnd, offset_t &size)
+{
+   struct stat data;
+   bool ret = 0 == ::fstat(hnd, &data);
+   if(ret){
+      size = data.st_size;
+   }
+   return ret;
+}
+
+inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
+{  return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
+
+inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
+{
+   off = ::lseek(hnd, 0, SEEK_CUR);
+   return off != ((off_t)-1);
+}
+
+inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
+{  return (ssize_t(numdata)) == ::write(hnd, data, numdata);  }
+
+inline file_handle_t invalid_file()
+{  return -1;  }
+
+inline bool close_file(file_handle_t hnd)
+{  return ::close(hnd) == 0;   }
+
+inline bool acquire_file_lock(file_handle_t hnd)
+{
+   struct ::flock lock;
+   lock.l_type    = F_WRLCK;
+   lock.l_whence  = SEEK_SET;
+   lock.l_start   = 0;
+   lock.l_len     = 0;
+   return -1 != ::fcntl(hnd, F_SETLKW, &lock);
+}
+
+inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
+{
+   struct ::flock lock;
+   lock.l_type    = F_WRLCK;
+   lock.l_whence  = SEEK_SET;
+   lock.l_start   = 0;
+   lock.l_len     = 0;
+   int ret = ::fcntl(hnd, F_SETLK, &lock);
+   if(ret == -1){
+      return (errno == EAGAIN || errno == EACCES) ?
+               acquired = false, true : false;
+   }
+   return (acquired = true);
+}
+
+inline bool release_file_lock(file_handle_t hnd)
+{
+   struct ::flock lock;
+   lock.l_type    = F_UNLCK;
+   lock.l_whence  = SEEK_SET;
+   lock.l_start   = 0;
+   lock.l_len     = 0;
+   return -1 != ::fcntl(hnd, F_SETLK, &lock);
+}
+
+inline bool acquire_file_lock_sharable(file_handle_t hnd)
+{
+   struct ::flock lock;
+   lock.l_type    = F_RDLCK;
+   lock.l_whence  = SEEK_SET;
+   lock.l_start   = 0;
+   lock.l_len     = 0;
+   return -1 != ::fcntl(hnd, F_SETLKW, &lock);
+}
+
+inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
+{
+   struct flock lock;
+   lock.l_type    = F_RDLCK;
+   lock.l_whence  = SEEK_SET;
+   lock.l_start   = 0;
+   lock.l_len     = 0;
+   int ret = ::fcntl(hnd, F_SETLK, &lock);
+   if(ret == -1){
+      return (errno == EAGAIN || errno == EACCES) ?
+               acquired = false, true : false;
+   }
+   return (acquired = true);
+}
+
+inline bool release_file_lock_sharable(file_handle_t hnd)
+{  return release_file_lock(hnd);   }
+
+#if 0
+inline bool acquire_file_lock(file_handle_t hnd)
+{  return 0 == ::flock(hnd, LOCK_EX); }
+
+inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
+{
+   int ret = ::flock(hnd, LOCK_EX | LOCK_NB);
+   acquired = ret == 0;
+   return (acquired || errno == EWOULDBLOCK);
+}
+
+inline bool release_file_lock(file_handle_t hnd)
+{  return 0 == ::flock(hnd, LOCK_UN); }
+
+inline bool acquire_file_lock_sharable(file_handle_t hnd)
+{  return 0 == ::flock(hnd, LOCK_SH); }
+
+inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
+{
+   int ret = ::flock(hnd, LOCK_SH | LOCK_NB);
+   acquired = ret == 0;
+   return (acquired || errno == EWOULDBLOCK);
+}
+
+inline bool release_file_lock_sharable(file_handle_t hnd)
+{  return 0 == ::flock(hnd, LOCK_UN); }
+#endif
+
+inline bool delete_subdirectories_recursive
+   (const std::string &refcstrRootDirectory, const char *dont_delete_this)
+{
+   DIR *d = opendir(refcstrRootDirectory.c_str());
+   if(!d) {
+      return false;
+   }
+
+   struct dir_close
+   {
+      DIR *d_;
+      dir_close(DIR *d) : d_(d) {}
+      ~dir_close() { ::closedir(d_); }
+   } dc(d); (void)dc;
+
+   struct ::dirent *de;
+   struct ::stat st;
+   std::string fn;
+
+   while((de=::readdir(d))) {
+      if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
+            || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
+         continue;
+      }
+      if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
+         continue;
+      }
+      fn = refcstrRootDirectory;
+      fn += '/';
+      fn += de->d_name;
+
+      if(std::remove(fn.c_str())) {
+         if(::stat(fn.c_str(), & st)) {
+            return false;
+         }
+         if(S_ISDIR(st.st_mode)) {
+            if(!delete_subdirectories_recursive(fn, 0) ){
+               return false;
+            }
+         } else {
+            return false;
+         }
+      }
+   }
+   return std::remove(refcstrRootDirectory.c_str()) ? false : true;
+}
+
+template<class Function>
+inline bool for_each_file_in_dir(const char *dir, Function f)
+{
+   std::string refcstrRootDirectory(dir);
+
+   DIR *d = opendir(refcstrRootDirectory.c_str());
+   if(!d) {
+      return false;
+   }
+
+   struct dir_close
+   {
+      DIR *d_;
+      dir_close(DIR *d) : d_(d) {}
+      ~dir_close() { ::closedir(d_); }
+   } dc(d); (void)dc;
+
+   struct ::dirent *de;
+   struct ::stat st;
+   std::string fn;
+
+   while((de=::readdir(d))) {
+      if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
+            || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
+         continue;
+      }
+      fn = refcstrRootDirectory;
+      fn += '/';
+      fn += de->d_name;
+
+      if(::stat(fn.c_str(), & st)) {
+         return false;
+      }
+      //If it's a file, apply erase logic
+      if(!S_ISDIR(st.st_mode)) {
+         f(fn.c_str(), de->d_name);
+      }
+   }
+   return true;
+}
+
+
+//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
+inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
+{
+   return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this );
+}
+
+#endif   //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+inline bool open_or_create_directory(const char *dir_name)
+{
+   //If fails, check that it's because it already exists
+   if(!create_directory(dir_name)){
+      error_info info(system_error_code());
+      if(info.get_error_code() != already_exists_error){
+         return false;
+      }
+   }
+   return true;
+}
+
+
+}  //namespace ipcdetail{
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP

+ 211 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/os_thread_functions.hpp

@@ -0,0 +1,211 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
+#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/streams/bufferstream.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+#  include <boost/interprocess/detail/win32_api.hpp>
+#else
+#  ifdef BOOST_HAS_UNISTD_H
+#     include <pthread.h>
+#     include <unistd.h>
+#     include <sched.h>
+#     include <time.h>
+#  else
+#     error Unknown platform
+#  endif
+#endif
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef unsigned long OS_process_id_t;
+typedef unsigned long OS_thread_id_t;
+typedef OS_thread_id_t OS_systemwide_thread_id_t;
+
+//process
+inline OS_process_id_t get_current_process_id()
+{  return winapi::get_current_process_id();  }
+
+inline OS_process_id_t get_invalid_process_id()
+{  return OS_process_id_t(0);  }
+
+//thread
+inline OS_thread_id_t get_current_thread_id()
+{  return winapi::get_current_thread_id();  }
+
+inline OS_thread_id_t get_invalid_thread_id()
+{  return OS_thread_id_t(0xffffffff);  }
+
+inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
+{  return id1 == id2;  }
+
+inline void thread_yield()
+{  winapi::sched_yield();  }
+
+inline void thread_sleep(unsigned int ms)
+{  winapi::Sleep(ms);  }
+
+//systemwide thread
+inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
+{
+   return get_current_thread_id();
+}
+
+inline void systemwide_thread_id_copy
+   (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
+{
+   to = from;
+}
+
+inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
+{
+   return equal_thread_id(id1, id2);
+}
+
+inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
+{
+   return get_invalid_thread_id();
+}
+
+inline long double get_current_process_creation_time()
+{
+   winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
+
+   get_process_times
+      ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
+
+   typedef long double ldouble_t;
+   const ldouble_t resolution = (100.0l/1000000000.0l);
+   return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
+              CreationTime.dwLowDateTime*resolution;
+}
+
+
+#else    //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef pthread_t OS_thread_id_t;
+typedef pid_t     OS_process_id_t;
+
+struct OS_systemwide_thread_id_t
+{
+   OS_systemwide_thread_id_t()
+      :  pid(), tid()
+   {}
+
+   OS_systemwide_thread_id_t(pid_t p, pthread_t t)
+      :  pid(p), tid(t)
+   {}
+
+   OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
+      :  pid(x.pid), tid(x.tid)
+   {}
+
+   OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
+      :  pid(x.pid), tid(x.tid)
+   {}
+
+   OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
+   {  pid = x.pid;   tid = x.tid;   return *this;   }
+
+   OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
+   {  pid = x.pid;   tid = x.tid;   return *this;  }
+
+   void operator=(const OS_systemwide_thread_id_t &x) volatile
+   {  pid = x.pid;   tid = x.tid;   }
+
+   pid_t       pid;
+   pthread_t   tid;
+};
+
+inline void systemwide_thread_id_copy
+   (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
+{
+   to.pid = from.pid;
+   to.tid = from.tid;
+}
+
+//process
+inline OS_process_id_t get_current_process_id()
+{  return ::getpid();  }
+
+inline OS_process_id_t get_invalid_process_id()
+{  return pid_t(0);  }
+
+//thread
+inline OS_thread_id_t get_current_thread_id()
+{  return ::pthread_self();  }
+
+inline OS_thread_id_t get_invalid_thread_id()
+{
+   static pthread_t invalid_id;
+   return invalid_id;
+}
+
+inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
+{  return 0 != pthread_equal(id1, id2);  }
+
+inline void thread_yield()
+{  ::sched_yield();  }
+
+inline void thread_sleep(unsigned int ms)
+{
+   const struct timespec rqt = { ms/1000u, (ms%1000u)*1000000u  };
+   ::nanosleep(&rqt, 0);
+}
+
+//systemwide thread
+inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
+{
+   return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
+}
+
+inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
+{
+   return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
+}
+
+inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
+{
+   return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
+}
+
+inline long double get_current_process_creation_time()
+{ return 0.0L; }
+
+#endif   //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
+
+inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
+{
+   bufferstream bstream(pid_str, sizeof(pid_str));
+   bstream << pid << std::ends;
+}
+
+inline void get_pid_str(pid_str_t &pid_str)
+{  get_pid_str(pid_str, get_current_process_id());  }
+
+}  //namespace ipcdetail{
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP

+ 74 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/pointer_type.hpp

@@ -0,0 +1,74 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Gennaro Prota 2003 - 2004.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
+#define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+struct two {char _[2];};
+
+namespace pointer_type_imp {
+
+template <class U> static two  test(...);
+template <class U> static char test(typename U::pointer* = 0);
+
+}  //namespace pointer_type_imp {
+
+template <class T>
+struct has_pointer_type
+{
+    static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
+};
+
+namespace pointer_type_imp {
+
+template <class T, class D, bool = has_pointer_type<D>::value>
+struct pointer_type
+{
+    typedef typename D::pointer type;
+};
+
+template <class T, class D>
+struct pointer_type<T, D, false>
+{
+    typedef T* type;
+};
+
+}  //namespace pointer_type_imp {
+
+template <class T, class D>
+struct pointer_type
+{
+    typedef typename pointer_type_imp::pointer_type<T,
+        typename remove_reference<D>::type>::type type;
+};
+
+}  //namespace ipcdetail {
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
+

+ 356 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/portable_intermodule_singleton.hpp

@@ -0,0 +1,356 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
+#define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/managed_global_memory.hpp>
+#include <boost/interprocess/detail/intermodule_singleton_common.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_thread_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/file_locking_helpers.hpp>
+#include <boost/assert.hpp>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+typedef basic_managed_global_memory<shared_memory_object, true>    managed_global_memory;
+
+namespace intermodule_singleton_helpers {
+
+static void create_tmp_subdir_and_get_pid_based_filepath
+   (const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false)
+{
+   //Let's create a lock file for each process gmem that will mark if
+   //the process is alive or not
+   create_tmp_and_clean_old(s);
+   s += "/";
+   s += subdir_name;
+   if(!open_or_create_directory(s.c_str())){
+      throw interprocess_exception(error_info(system_error_code()));
+   }
+   s += "/";
+   s += file_prefix;
+   if(creation_time){
+      std::string sstamp;
+      get_pid_creation_time_str(sstamp);
+      s += sstamp;
+   }
+   else{
+      pid_str_t pid_str;
+      get_pid_str(pid_str, pid);
+      s += pid_str;
+   }
+}
+
+static bool check_if_filename_complies_with_pid
+   (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false)
+{
+   //Check if filename complies with lock file name pattern
+   std::string fname(filename);
+   std::string fprefix(prefix);
+   if(fname.size() <= fprefix.size()){
+      return false;
+   }
+   fname.resize(fprefix.size());
+   if(fname != fprefix){
+      return false;
+   }
+
+   //If not our lock file, delete it if we can lock it
+   fname = filename;
+   fname.erase(0, fprefix.size());
+   pid_str_t pid_str;
+   get_pid_str(pid_str, pid);
+   file_suffix = pid_str;
+   if(creation_time){
+      std::size_t p = fname.find('_');
+      if (p == std::string::npos){
+         return false;
+      }
+      std::string save_suffix(fname);
+      fname.erase(p);
+      fname.swap(file_suffix);
+      bool ret = (file_suffix == fname);
+      file_suffix.swap(save_suffix);
+      return ret;
+   }
+   else{
+      fname.swap(file_suffix);
+      return (file_suffix == fname);
+   }
+}
+
+template<>
+struct thread_safe_global_map_dependant<managed_global_memory>
+{
+   private:
+   static const int GMemMarkToBeRemoved = -1;
+   static const int GMemNotPresent      = -2;
+
+   static const char *get_lock_file_subdir_name()
+   {  return "gmem";  }
+
+   static const char *get_lock_file_base_name()
+   {  return "lck";  }
+
+   static void create_and_get_singleton_lock_file_path(std::string &s)
+   {
+      create_tmp_subdir_and_get_pid_based_filepath
+         (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true);
+   }
+
+   struct gmem_erase_func
+   {
+      gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, managed_global_memory & shm)
+         :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm)
+      {}
+
+      void operator()()
+      {
+         locking_file_serial_id *pserial_id = shm_.find<locking_file_serial_id>("lock_file_fd").first;
+         if(pserial_id){
+            pserial_id->fd = GMemMarkToBeRemoved;
+         }
+         delete_file(singleton_lock_file_path_);
+         shared_memory_object::remove(shm_name_);
+      }
+
+      const char * const shm_name_;
+      const char * const singleton_lock_file_path_;
+      managed_global_memory & shm_;
+   };
+
+   //This function applies shared memory erasure logic based on the passed lock file.
+   static void apply_gmem_erase_logic(const char *filepath, const char *filename)
+   {
+      int fd = GMemMarkToBeRemoved;
+      try{
+         std::string str;
+         //If the filename is current process lock file, then avoid it
+         if(check_if_filename_complies_with_pid
+            (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){
+            return;
+         }
+         //Open and lock the other process' lock file
+         fd = try_open_and_lock_file(filepath);
+         if(fd < 0){
+            return;
+         }
+         //If done, then the process is dead so take global shared memory name
+         //(the name is based on the lock file name) and try to apply erasure logic
+         str.insert(0, get_map_base_name());
+         try{
+            managed_global_memory shm(open_only, str.c_str());
+            gmem_erase_func func(str.c_str(), filepath, shm);
+            shm.try_atomic_func(func);
+         }
+         catch(interprocess_exception &e){
+            //If shared memory is not found erase the lock file
+            if(e.get_error_code() == not_found_error){
+               delete_file(filepath);
+            }
+         }
+      }
+      catch(...){
+
+      }
+      if(fd >= 0){
+         close_lock_file(fd);
+      }
+   }
+
+   public:
+
+   static bool remove_old_gmem()
+   {
+      std::string refcstrRootDirectory;
+      tmp_folder(refcstrRootDirectory);
+      refcstrRootDirectory += "/";
+      refcstrRootDirectory += get_lock_file_subdir_name();
+      return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic);
+   }
+
+   struct lock_file_logic
+   {
+      lock_file_logic(managed_global_memory &shm)
+         : mshm(shm)
+      {  shm.atomic_func(*this); }
+
+      void operator()(void)
+      {
+         retry_with_new_map = false;
+
+         //First find the file locking descriptor id
+         locking_file_serial_id *pserial_id =
+            mshm.find<locking_file_serial_id>("lock_file_fd").first;
+
+         int fd;
+         //If not found schedule a creation
+         if(!pserial_id){
+            fd = GMemNotPresent;
+         }
+         //Else get it
+         else{
+            fd = pserial_id->fd;
+         }
+         //If we need to create a new one, do it
+         if(fd == GMemNotPresent){
+            std::string lck_str;
+            //Create a unique current pid based lock file path
+            create_and_get_singleton_lock_file_path(lck_str);
+            //Open or create and lock file
+            int fd = open_or_create_and_lock_file(lck_str.c_str());
+            //If failed, write a bad file descriptor to notify other modules that
+            //something was wrong and unlink shared memory. Mark the function object
+            //to tell caller to retry with another shared memory
+            if(fd < 0){
+               this->register_lock_file(GMemMarkToBeRemoved);
+               std::string s;
+               get_map_name(s);
+               shared_memory_object::remove(s.c_str());
+               retry_with_new_map = true;
+            }
+            //If successful, register the file descriptor
+            else{
+               this->register_lock_file(fd);
+            }
+         }
+         //If the fd was invalid (maybe a previous try failed) notify caller that
+         //should retry creation logic, since this shm might have been already
+         //unlinked since the shm was removed
+         else if (fd == GMemMarkToBeRemoved){
+            retry_with_new_map = true;
+         }
+         //If the stored fd is not valid (a open fd, a normal file with the
+         //expected size, or does not have the same file id number,
+         //then it's an old shm from an old process with the same pid.
+         //If that's the case, mark it as invalid
+         else if(!is_valid_fd(fd) ||
+               !is_normal_file(fd) ||
+               0 != get_size(fd) ||
+               !compare_file_serial(fd, *pserial_id)){
+            pserial_id->fd = GMemMarkToBeRemoved;
+            std::string s;
+            get_map_name(s);
+            shared_memory_object::remove(s.c_str());
+            retry_with_new_map = true;
+         }
+         else{
+            //If the lock file is ok, increment reference count of
+            //attached modules to shared memory
+            atomic_inc32(&pserial_id->modules_attached_to_gmem_count);
+         }
+      }
+
+      bool retry() const { return retry_with_new_map; }
+
+      private:
+      locking_file_serial_id * register_lock_file(int fd)
+      {
+         locking_file_serial_id *pinfo = mshm.construct<locking_file_serial_id>("lock_file_fd")();
+         fill_file_serial_id(fd, *pinfo);
+         return pinfo;
+      }
+
+      managed_global_memory &mshm;
+      bool retry_with_new_map;
+   };
+
+   static void construct_map(void *addr)
+   {
+      std::string s;
+      intermodule_singleton_helpers::get_map_name(s);
+      const char *MapName = s.c_str();
+      const std::size_t MapSize = intermodule_singleton_helpers::get_map_size();;
+      ::new (addr)managed_global_memory(open_or_create, MapName, MapSize);
+   }
+
+   struct unlink_map_logic
+   {
+      unlink_map_logic(managed_global_memory &mshm)
+         : mshm_(mshm)
+      {  mshm.atomic_func(*this);  }
+
+      void operator()()
+      {
+         locking_file_serial_id *pserial_id =
+            mshm_.find<locking_file_serial_id>
+               ("lock_file_fd").first;
+         BOOST_ASSERT(0 != pserial_id);
+         if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){
+            int fd = pserial_id->fd;
+            if(fd > 0){
+               pserial_id->fd = GMemMarkToBeRemoved;
+               std::string s;
+               create_and_get_singleton_lock_file_path(s);
+               delete_file(s.c_str());
+               close_lock_file(fd);
+               intermodule_singleton_helpers::get_map_name(s);
+               shared_memory_object::remove(s.c_str());
+            }
+         }
+      }
+
+      private:
+      managed_global_memory &mshm_;
+   };
+
+   static ref_count_ptr *find(managed_global_memory &map, const char *name)
+   {
+      return map.find<ref_count_ptr>(name).first;
+   }
+
+   static ref_count_ptr *insert(managed_global_memory &map, const char *name, const ref_count_ptr &ref)
+   {
+      return map.construct<ref_count_ptr>(name)(ref);
+   }
+
+   static bool erase(managed_global_memory &map, const char *name)
+   {
+      return map.destroy<ref_count_ptr>(name);
+   }
+
+   template<class F>
+   static void atomic_func(managed_global_memory &map, F &f)
+   {
+      map.atomic_func(f);
+   }
+};
+
+}  //namespace intermodule_singleton_helpers {
+
+template<typename C, bool LazyInit = true, bool Phoenix = true>
+class portable_intermodule_singleton
+   : public intermodule_singleton_impl<C, LazyInit, Phoenix, managed_global_memory>
+{};
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP

+ 42 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/posix_time_types_wrk.hpp

@@ -0,0 +1,42 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
+#define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
+
+//workaround to avoid winsock redefines when using date-time
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif   //#ifndef WIN32_LEAN_AND_MEAN
+#endif   //#ifdef _WIN32
+
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
+
+namespace boost {
+namespace interprocess {
+
+typedef boost::date_time::microsec_clock<boost::posix_time::ptime> microsec_clock;
+
+}
+}
+
+#ifdef _WIN32
+#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif   //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif   //#ifdef _WIN32
+
+#endif   //#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
+

+ 203 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/preprocessor.hpp

@@ -0,0 +1,203 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
+#define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#error "This file is not needed when perfect forwarding is available"
+#endif
+
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#define BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS 10
+
+//Note:
+//We define template parameters as const references to
+//be able to bind temporaries. After that we will un-const them.
+//This cast is ugly but it is necessary until "perfect forwarding"
+//is achieved in C++0x. Meanwhile, if we want to be able to
+//bind rvalues with non-const references, we have to be ugly
+#ifndef BOOST_NO_RVALUE_REFERENCES
+   #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
+   BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
+   //!
+#else
+   #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
+   const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
+   //!
+#endif
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+   #define BOOST_INTERPROCESS_PP_PARAM(U, u) \
+   U && u \
+   //!
+#else
+   #define BOOST_INTERPROCESS_PP_PARAM(U, u) \
+   const U & u \
+   //!
+#endif
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+
+   #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+     BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ))  \
+   //!
+
+#else //#ifndef BOOST_NO_RVALUE_REFERENCES
+
+   #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \
+     BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
+   //!
+#endif
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+
+   #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+      namespace boost {
+      namespace interprocess {
+      namespace ipcdetail {
+         template<class T>
+         struct ref_holder;
+
+         template<class T>
+         struct ref_holder<T &>
+         {
+            ref_holder(T &t)
+               : t_(t)
+            {}
+            T &t_;
+            T & get() {  return t_;   }
+            T & get_lvalue() {  return t_;   }
+         };
+
+         template<class T>
+         struct ref_holder<const T>
+         {
+            ref_holder(const T &t)
+               : t_(t)
+            {}
+            const T &t_;
+            const T & get() {  return t_;   }
+            const T & get_lvalue() {  return t_;   }
+         };
+
+         template<class T>
+         struct ref_holder<const T &&>
+         {
+            ref_holder(const T &t)
+               : t_(t)
+            {}
+            const T &t_;
+            const T & get() {  return t_;   }
+            const T & get_lvalue() {  return t_;   }
+         };
+
+         template<class T>
+         struct ref_holder
+         {
+            ref_holder(T &&t)
+               : t_(t)
+            {}
+            T &t_;
+            T && get() {  return ::boost::move(t_);   }
+            T & get_lvalue() {  return t_;   }
+         };
+
+         template<class T>
+         struct ref_holder<T &&>
+         {
+            ref_holder(T &&t)
+               : t(t)
+            {}
+            T &t;
+            T && get()  { return ::boost::move(t_); }
+            T & get_lvalue() {  return t_;   }
+         };
+
+      }  //namespace ipcdetail {
+      }  //namespace interprocess {
+      }  //namespace boost {
+
+      #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data)  \
+         ::boost::interprocess::ipcdetail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n);  \
+      //!
+
+      #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data)   \
+         BOOST_PP_CAT(++m_p, n).get_lvalue()                \
+      //!
+
+   #else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
+
+      #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data)\
+      BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n);           \
+      //!
+
+      #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data)   \
+         BOOST_PP_CAT(++m_p, n)                             \
+      //!
+
+   #endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#else
+   #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data)   \
+   BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n);               \
+   //!
+
+   #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data)      \
+      BOOST_PP_CAT(++m_p, n)                                \
+   //!
+
+#endif
+
+#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
+::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
+//!
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+   #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \
+   //!
+
+   #define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
+   BOOST_PP_CAT(*m_p, n).get_lvalue()                          \
+   //!
+
+#else
+
+   #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data)       \
+   ::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
+   //!
+
+   #define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data)    \
+   BOOST_PP_CAT(*m_p, n)                                          \
+   //!
+
+
+#endif   //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#else
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#error "This file is not needed when perfect forwarding is available"
+#endif
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP

+ 33 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/ptime_wrk.hpp

@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
+#define BOOST_INTERPROCESS_PTIME_WRK_HPP
+
+//workaround to avoid winsock redefines when using date-time
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif   //#ifndef WIN32_LEAN_AND_MEAN
+#endif   //#ifdef _WIN32
+
+#include <boost/date_time/posix_time/ptime.hpp>
+
+#ifdef _WIN32
+#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif   //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
+#endif   //#ifdef _WIN32
+
+#endif   //#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
+

+ 439 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/robust_emulation.hpp

@@ -0,0 +1,439 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2010-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_ROBUST_EMULATION_HPP
+#define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <string>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+namespace robust_emulation_helpers {
+
+template<class T>
+class mutex_traits
+{
+   public:
+   static void take_ownership(T &t)
+   {  t.take_ownership(); }
+};
+
+inline void remove_if_can_lock_file(const char *file_path)
+{
+   file_handle_t fhnd = open_existing_file(file_path, read_write);
+
+   if(fhnd != invalid_file()){
+      bool acquired;
+      if(try_acquire_file_lock(fhnd, acquired) && acquired){
+         delete_file(file_path);
+      }
+      close_file(fhnd);
+   }
+}
+
+inline const char *robust_lock_subdir_path()
+{  return "robust"; }
+
+inline const char *robust_lock_prefix()
+{  return "lck"; }
+
+inline void robust_lock_path(std::string &s)
+{
+   tmp_folder(s);
+   s += "/";
+   s += robust_lock_subdir_path();
+}
+
+inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid)
+{
+   intermodule_singleton_helpers::create_tmp_subdir_and_get_pid_based_filepath
+      (robust_lock_subdir_path(), robust_lock_prefix(), pid, s);
+}
+
+//This class will be a intermodule_singleton. The constructor will create
+//a lock file, the destructor will erase it.
+//
+//We should take in care that another process might be erasing unlocked
+//files while creating this one, so there are some race conditions we must
+//take in care to guarantee some robustness.
+class robust_mutex_lock_file
+{
+   file_handle_t fd;
+   std::string fname;
+   public:
+   robust_mutex_lock_file()
+   {
+      permissions p;
+      p.set_unrestricted();
+      //Remove old lock files of other processes
+      remove_old_robust_lock_files();
+      //Create path and obtain lock file path for this process
+      create_and_get_robust_lock_file_path(fname, get_current_process_id());
+
+      //Now try to open or create the lock file
+      fd = create_or_open_file(fname.c_str(), read_write, p);
+      //If we can't open or create it, then something unrecoverable has happened
+      if(fd == invalid_file()){
+         throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: could not open or create file");
+      }
+
+      //Now we must take in care a race condition with another process
+      //calling "remove_old_robust_lock_files()". No other threads from this
+      //process will be creating the lock file because intermodule_singleton
+      //guarantees this. So let's loop acquiring the lock and checking if we
+      //can't exclusively create the file (if the file is erased by another process
+      //then this exclusive open would fail). If the file can't be exclusively created
+      //then we have correctly open/create and lock the file. If the file can
+      //be exclusively created, then close previous locked file and try again.
+      while(1){
+         bool acquired;
+         if(!try_acquire_file_lock(fd, acquired) || !acquired ){
+            throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: try_acquire_file_lock");
+         }
+         //Creating exclusively must fail with already_exists_error
+         //to make sure we've locked the file and no one has
+         //deleted it between creation and locking
+         file_handle_t fd2 = create_new_file(fname.c_str(), read_write, p);
+         if(fd2 != invalid_file()){
+            close_file(fd);
+            fd = fd2;
+            continue;
+         }
+         //If exclusive creation fails with expected error go ahead
+         else if(error_info(system_error_code()).get_error_code() == already_exists_error){ //must already exist
+            //Leak descriptor to mantain the file locked until the process dies
+            break;
+         }
+         //If exclusive creation fails with unexpected error throw an unrecoverable error
+         else{
+            close_file(fd);
+            throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error");
+         }
+      }
+   }
+
+   ~robust_mutex_lock_file()
+   {
+      //The destructor is guaranteed by intermodule_singleton to be
+      //executed serialized between all threads from current process,
+      //so we just need to close and unlink the file.
+      close_file(fd);
+      //If some other process deletes the file before us after
+      //closing it there should not be any problem.
+      delete_file(fname.c_str());
+   }
+
+   private:
+   //This functor is execute for all files in the lock file directory
+   class other_process_lock_remover
+   {
+      public:
+      void operator()(const char *filepath, const char *filename)
+      {
+         std::string pid_str;
+         //If the lock file is not our own lock file, then try to do the cleanup
+         if(!intermodule_singleton_helpers::check_if_filename_complies_with_pid
+            (filename, robust_lock_prefix(), get_current_process_id(), pid_str)){
+            remove_if_can_lock_file(filepath);
+         }
+      }
+   };
+
+   bool remove_old_robust_lock_files()
+   {
+      std::string refcstrRootDirectory;
+      robust_lock_path(refcstrRootDirectory);
+      return for_each_file_in_dir(refcstrRootDirectory.c_str(), other_process_lock_remover());
+   }
+};
+
+}  //namespace robust_emulation_helpers {
+
+//This is the mutex class. Mutex should follow mutex concept
+//with an additonal "take_ownership()" function to take ownership of the
+//mutex when robust_spin_mutex determines the previous owner was dead.
+template<class Mutex>
+class robust_spin_mutex
+{
+   public:
+   static const boost::uint32_t correct_state = 0;
+   static const boost::uint32_t fixing_state  = 1;
+   static const boost::uint32_t broken_state  = 2;
+
+   typedef robust_emulation_helpers::mutex_traits<Mutex> mutex_traits_t;
+
+   robust_spin_mutex();
+   void lock();
+   bool try_lock();
+   bool timed_lock(const boost::posix_time::ptime &abs_time);
+   void unlock();
+   void consistent();
+   bool previous_owner_dead();
+
+   private:
+   static const unsigned int spin_threshold = 100u;
+   bool lock_own_unique_file();
+   bool robust_check();
+   bool check_if_owner_dead_and_take_ownership_atomically();
+   bool is_owner_dead(boost::uint32_t owner);
+   void owner_to_filename(boost::uint32_t owner, std::string &s);
+   //The real mutex
+   Mutex mtx;
+   //The pid of the owner
+   volatile boost::uint32_t owner;
+   //The state of the mutex (correct, fixing, broken)
+   volatile boost::uint32_t state;
+};
+
+template<class Mutex>
+inline robust_spin_mutex<Mutex>::robust_spin_mutex()
+   : mtx(), owner(get_invalid_process_id()), state(correct_state)
+{}
+
+template<class Mutex>
+inline void robust_spin_mutex<Mutex>::lock()
+{
+   //If the mutex is broken (recovery didn't call consistent()),
+   //then throw an exception
+   if(atomic_read32(&this->state) == broken_state){
+      throw interprocess_exception(lock_error, "Broken id");
+   }
+
+   //This function provokes intermodule_singleton instantiation
+   if(!this->lock_own_unique_file()){
+      throw interprocess_exception(lock_error, "Broken id");
+   }
+
+   //Now the logic. Try to lock, if successful mark the owner
+   //if it fails, start recovery logic
+   unsigned int spin_count = 0;
+   while(1){
+      if (mtx.try_lock()){
+         atomic_write32(&this->owner, get_current_process_id());
+         break;
+      }
+      else{
+         //Do the dead owner checking each spin_threshold lock tries
+         ipcdetail::thread_yield();
+         ++spin_count;
+         if(spin_count > spin_threshold){
+            //Check if owner dead and take ownership if possible
+            if(!this->robust_check()){
+               spin_count = 0;
+            }
+            else{
+               break;
+            }
+         }
+      }
+   }
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::try_lock()
+{
+   //Same as lock() but without spinning
+   if(atomic_read32(&this->state) == broken_state){
+      throw interprocess_exception(lock_error, "Broken id");
+   }
+
+   if(!this->lock_own_unique_file()){
+      throw interprocess_exception(lock_error, "Broken id");
+   }
+
+   if (mtx.try_lock()){
+      atomic_write32(&this->owner, get_current_process_id());
+      return true;
+   }
+   else{
+      if(!this->robust_check()){
+         return false;
+      }
+      else{
+         return true;
+      }
+   }
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::timed_lock
+   (const boost::posix_time::ptime &abs_time)
+{
+   //Same as lock() but with an additional timeout
+   if(abs_time == boost::posix_time::pos_infin){
+      this->lock();
+      return true;
+   }
+   //Obtain current count and target time
+   boost::posix_time::ptime now = microsec_clock::universal_time();
+
+   if(now >= abs_time)
+      return this->try_lock();
+
+   do{
+      if(this->try_lock()){
+         break;
+      }
+      now = microsec_clock::universal_time();
+
+      if(now >= abs_time){
+         return this->try_lock();
+      }
+      // relinquish current time slice
+      ipcdetail::thread_yield();
+   }while (true);
+
+   return true;
+}
+
+template<class Mutex>
+inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t owner, std::string &s)
+{
+   robust_emulation_helpers::create_and_get_robust_lock_file_path(s, owner);
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::robust_check()
+{
+   //If the old owner was dead, and we've acquired ownership, mark
+   //the mutex as 'fixing'. This means that a "consistent()" is needed
+   //to avoid marking the mutex as "broken" when the mutex is unlocked.
+   if(!this->check_if_owner_dead_and_take_ownership_atomically()){
+      return false;
+   }
+   atomic_write32(&this->state, fixing_state);
+   return true;
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::check_if_owner_dead_and_take_ownership_atomically()
+{
+   boost::uint32_t cur_owner = get_current_process_id();
+   boost::uint32_t old_owner = atomic_read32(&this->owner), old_owner2;
+   //The cas loop guarantees that only one thread from this or another process
+   //will succeed taking ownership
+   do{
+      //Check if owner is dead
+      if(!this->is_owner_dead(old_owner)){
+         return false;
+      }
+      //If it's dead, try to mark this process as the owner in the owner field
+      old_owner2 = old_owner;
+      old_owner = atomic_cas32(&this->owner, cur_owner, old_owner);
+   }while(old_owner2 != old_owner);
+   //If success, we fix mutex internals to assure our ownership
+   mutex_traits_t::take_ownership(mtx);
+   return true;
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t owner)
+{
+   //If owner is an invalid id, then it's clear it's dead
+   if(owner == (boost::uint32_t)get_invalid_process_id()){
+      return true;
+   }
+
+   //Obtain the lock filename of the owner field
+   std::string file;
+   this->owner_to_filename(owner, file);
+
+   //Now the logic is to open and lock it
+   file_handle_t fhnd = open_existing_file(file.c_str(), read_write);
+
+   if(fhnd != invalid_file()){
+      //If we can open the file, lock it.
+      bool acquired;
+      if(try_acquire_file_lock(fhnd, acquired) && acquired){
+         //If locked, just delete the file
+         delete_file(file.c_str());
+         close_file(fhnd);
+         return true;
+      }
+      //If not locked, the owner is suppossed to be still alive
+      close_file(fhnd);
+   }
+   else{
+      //If the lock file does not exist then the owner is dead (a previous cleanup)
+      //function has deleted the file. If there is another reason, then this is
+      //an unrecoverable error
+      if(error_info(system_error_code()).get_error_code() == not_found_error){
+         return true;
+      }
+   }
+   return false;
+}
+
+template<class Mutex>
+inline void robust_spin_mutex<Mutex>::consistent()
+{
+   //This function supposes the previous state was "fixing"
+   //and the current process holds the mutex
+   if(atomic_read32(&this->state) != fixing_state &&
+      atomic_read32(&this->owner) != (boost::uint32_t)get_current_process_id()){
+      throw interprocess_exception(lock_error, "Broken id");
+   }
+   //If that's the case, just update mutex state
+   atomic_write32(&this->state, correct_state);
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::previous_owner_dead()
+{
+   //Notifies if a owner recovery has been performed in the last lock()
+   return atomic_read32(&this->state) == fixing_state;
+};
+
+template<class Mutex>
+inline void robust_spin_mutex<Mutex>::unlock()
+{
+   //If in "fixing" state, unlock and mark the mutex as unrecoverable
+   //so next locks will fail and all threads will be notified that the
+   //data protected by the mutex was not recoverable.
+   if(atomic_read32(&this->state) == fixing_state){
+      atomic_write32(&this->state, broken_state);
+   }
+   //Write an invalid owner to minimize pid reuse possibility
+   atomic_write32(&this->owner, get_invalid_process_id());
+   mtx.unlock();
+}
+
+template<class Mutex>
+inline bool robust_spin_mutex<Mutex>::lock_own_unique_file()
+{
+   //This function forces instantiation of the singleton
+   robust_emulation_helpers::robust_mutex_lock_file* dummy =
+      &ipcdetail::intermodule_singleton
+         <robust_emulation_helpers::robust_mutex_lock_file>::get();
+   return dummy != 0;
+}
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif

+ 513 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/segment_manager_helper.hpp

@@ -0,0 +1,513 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
+#define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/in_place_interface.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <cstddef>   //std::size_t
+#include <string>    //char_traits
+#include <new>       //std::nothrow
+#include <utility>   //std::pair
+#include <boost/assert.hpp>   //BOOST_ASSERT
+#include <functional>   //unary_function
+#ifndef BOOST_NO_EXCEPTIONS
+#include <exception>
+#endif
+
+//!\file
+//!Describes the object placed in a memory segment that provides
+//!named object allocation capabilities.
+
+namespace boost{
+namespace interprocess{
+
+template<class MemoryManager>
+class segment_manager_base;
+
+//!An integer that describes the type of the
+//!instance constructed in memory
+enum instance_type {   anonymous_type, named_type, unique_type, max_allocation_type };
+
+namespace ipcdetail{
+
+template<class MemoryAlgorithm>
+class mem_algo_deallocator
+{
+   void *            m_ptr;
+   MemoryAlgorithm & m_algo;
+
+   public:
+   mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo)
+      :  m_ptr(ptr), m_algo(algo)
+   {}
+
+   void release()
+   {  m_ptr = 0;  }
+
+   ~mem_algo_deallocator()
+   {  if(m_ptr) m_algo.deallocate(m_ptr);  }
+};
+
+/// @cond
+template<class size_type>
+struct block_header
+{
+   size_type      m_value_bytes;
+   unsigned short m_num_char;
+   unsigned char  m_value_alignment;
+   unsigned char  m_alloc_type_sizeof_char;
+
+   block_header(size_type value_bytes
+               ,size_type value_alignment
+               ,unsigned char alloc_type
+               ,std::size_t sizeof_char
+               ,std::size_t num_char
+               )
+      :  m_value_bytes(value_bytes)
+      ,  m_num_char((unsigned short)num_char)
+      ,  m_value_alignment((unsigned char)value_alignment)
+      ,  m_alloc_type_sizeof_char
+         ( (alloc_type << 5u) |
+           ((unsigned char)sizeof_char & 0x1F)   )
+   {};
+
+
+   template<class T>
+   block_header &operator= (const T& )
+   {  return *this;  }
+
+   size_type total_size() const
+   {
+      if(alloc_type() != anonymous_type){
+         return name_offset() + (m_num_char+1)*sizeof_char();
+      }
+      else{
+         return this->value_offset() + m_value_bytes;
+      }
+   }
+
+   size_type value_bytes() const
+   {  return m_value_bytes;   }
+
+   template<class Header>
+   size_type total_size_with_header() const
+   {
+      return get_rounded_size
+               ( size_type(sizeof(Header))
+			   , size_type(::boost::alignment_of<block_header<size_type> >::value))
+           + total_size();
+   }
+
+   unsigned char alloc_type() const
+   {  return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7;  }
+
+   unsigned char sizeof_char() const
+   {  return m_alloc_type_sizeof_char & (unsigned char)0x1F;  }
+
+   template<class CharType>
+   CharType *name() const
+   {
+      return const_cast<CharType*>(reinterpret_cast<const CharType*>
+         (reinterpret_cast<const char*>(this) + name_offset()));
+   }
+
+   unsigned short name_length() const
+   {  return m_num_char;   }
+
+   size_type name_offset() const
+   {
+      return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char()));
+   }
+
+   void *value() const
+   {
+      return const_cast<char*>((reinterpret_cast<const char*>(this) + this->value_offset()));
+   }
+
+   size_type value_offset() const
+   {
+      return get_rounded_size(size_type(sizeof(block_header<size_type>)), size_type(m_value_alignment));
+   }
+
+   template<class CharType>
+   bool less_comp(const block_header<size_type> &b) const
+   {
+      return m_num_char < b.m_num_char ||
+             (m_num_char < b.m_num_char &&
+               std::char_traits<CharType>::compare
+                  (name<CharType>(), b.name<CharType>(), m_num_char) < 0);
+   }
+
+   template<class CharType>
+   bool equal_comp(const block_header<size_type> &b) const
+   {
+      return m_num_char == b.m_num_char &&
+             std::char_traits<CharType>::compare
+               (name<CharType>(), b.name<CharType>(), m_num_char) == 0;
+   }
+
+   template<class T>
+   static block_header<size_type> *block_header_from_value(T *value)
+   {  return block_header_from_value(value, sizeof(T), ::boost::alignment_of<T>::value);  }
+
+   static block_header<size_type> *block_header_from_value(const void *value, std::size_t sz, std::size_t algn)
+   {
+      block_header * hdr =
+         const_cast<block_header*>
+            (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) -
+               get_rounded_size(sizeof(block_header), algn)));
+      (void)sz;
+      //Some sanity checks
+      BOOST_ASSERT(hdr->m_value_alignment == algn);
+      BOOST_ASSERT(hdr->m_value_bytes % sz == 0);
+      return hdr;
+   }
+
+   template<class Header>
+   static block_header<size_type> *from_first_header(Header *header)
+   {
+      block_header<size_type> * hdr =
+         reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) +
+		 get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
+      //Some sanity checks
+      return hdr;
+   }
+
+   template<class Header>
+   static Header *to_first_header(block_header<size_type> *bheader)
+   {
+      Header * hdr =
+         reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
+		 get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
+      //Some sanity checks
+      return hdr;
+   }
+};
+
+inline void array_construct(void *mem, std::size_t num, in_place_interface &table)
+{
+   //Try constructors
+   std::size_t constructed = 0;
+   BOOST_TRY{
+      table.construct_n(mem, num, constructed);
+   }
+   //If there is an exception call destructors and erase index node
+   BOOST_CATCH(...){
+      std::size_t destroyed = 0;
+      table.destroy_n(mem, constructed, destroyed);
+      BOOST_RETHROW
+   }
+   BOOST_CATCH_END
+}
+
+template<class CharT>
+struct intrusive_compare_key
+{
+   typedef CharT char_type;
+
+   intrusive_compare_key(const CharT *str, std::size_t len)
+      :  mp_str(str), m_len(len)
+   {}
+
+   const CharT *  mp_str;
+   std::size_t    m_len;
+};
+
+//!This struct indicates an anonymous object creation
+//!allocation
+template<instance_type type>
+class instance_t
+{
+   instance_t(){}
+};
+
+template<class T>
+struct char_if_void
+{
+   typedef T type;
+};
+
+template<>
+struct char_if_void<void>
+{
+   typedef char type;
+};
+
+typedef instance_t<anonymous_type>  anonymous_instance_t;
+typedef instance_t<unique_type>     unique_instance_t;
+
+
+template<class Hook, class CharType, class SizeType>
+struct intrusive_value_type_impl
+   :  public Hook
+{
+   private:
+   //Non-copyable
+   intrusive_value_type_impl(const intrusive_value_type_impl &);
+   intrusive_value_type_impl& operator=(const intrusive_value_type_impl &);
+
+   public:
+   typedef CharType char_type;
+   typedef SizeType size_type;
+
+   intrusive_value_type_impl(){}
+
+   enum  {  BlockHdrAlignment = ::boost::alignment_of<block_header<size_type> >::value  };
+
+   block_header<size_type> *get_block_header() const
+   {
+      return const_cast<block_header<size_type>*>
+         (reinterpret_cast<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
+            get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
+   }
+
+   bool operator <(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
+   {  return (this->get_block_header())->template less_comp<CharType>(*other.get_block_header());  }
+
+   bool operator ==(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
+   {  return (this->get_block_header())->template equal_comp<CharType>(*other.get_block_header());  }
+
+   static intrusive_value_type_impl *get_intrusive_value_type(block_header<size_type> *hdr)
+   {
+      return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
+         get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
+   }
+
+   CharType *name() const
+   {  return get_block_header()->template name<CharType>(); }
+
+   unsigned short name_length() const
+   {  return get_block_header()->name_length(); }
+
+   void *value() const
+   {  return get_block_header()->value(); }
+};
+
+template<class CharType>
+class char_ptr_holder
+{
+   public:
+   char_ptr_holder(const CharType *name)
+      : m_name(name)
+   {}
+
+   char_ptr_holder(const anonymous_instance_t *)
+      : m_name(static_cast<CharType*>(0))
+   {}
+
+   char_ptr_holder(const unique_instance_t *)
+      : m_name(reinterpret_cast<CharType*>(-1))
+   {}
+
+   operator const CharType *()
+   {  return m_name;  }
+
+   private:
+   const CharType *m_name;
+};
+
+//!The key of the the named allocation information index. Stores an offset pointer
+//!to a null terminated string and the length of the string to speed up sorting
+template<class CharT, class VoidPointer>
+struct index_key
+{
+   typedef typename boost::intrusive::
+      pointer_traits<VoidPointer>::template
+         rebind_pointer<const CharT>::type               const_char_ptr_t;
+   typedef CharT                                         char_type;
+   typedef typename boost::intrusive::pointer_traits<const_char_ptr_t>::difference_type difference_type;
+   typedef typename boost::make_unsigned<difference_type>::type size_type;
+
+   private:
+   //Offset pointer to the object's name
+   const_char_ptr_t  mp_str;
+   //Length of the name buffer (null NOT included)
+   size_type         m_len;
+   public:
+
+   //!Constructor of the key
+   index_key (const char_type *name, size_type length)
+      : mp_str(name), m_len(length) {}
+
+   //!Less than function for index ordering
+   bool operator < (const index_key & right) const
+   {
+      return (m_len < right.m_len) ||
+               (m_len == right.m_len &&
+               std::char_traits<char_type>::compare
+                  (to_raw_pointer(mp_str)
+              ,to_raw_pointer(right.mp_str), m_len) < 0);
+   }
+
+   //!Equal to function for index ordering
+   bool operator == (const index_key & right) const
+   {
+      return   m_len == right.m_len &&
+               std::char_traits<char_type>::compare
+                  (to_raw_pointer(mp_str),
+                   to_raw_pointer(right.mp_str), m_len) == 0;
+   }
+
+   void name(const CharT *name)
+   {  mp_str = name; }
+
+   void name_length(size_type len)
+   {  m_len = len; }
+
+   const CharT *name() const
+   {  return to_raw_pointer(mp_str); }
+
+   size_type name_length() const
+   {  return m_len; }
+};
+
+//!The index_data stores a pointer to a buffer and the element count needed
+//!to know how many destructors must be called when calling destroy
+template<class VoidPointer>
+struct index_data
+{
+   typedef VoidPointer void_pointer;
+   void_pointer    m_ptr;
+   index_data(void *ptr) : m_ptr(ptr){}
+
+   void *value() const
+   {  return static_cast<void*>(to_raw_pointer(m_ptr));  }
+};
+
+template<class MemoryAlgorithm>
+struct segment_manager_base_type
+{  typedef segment_manager_base<MemoryAlgorithm> type;   };
+
+template<class CharT, class MemoryAlgorithm>
+struct index_config
+{
+   typedef typename MemoryAlgorithm::void_pointer        void_pointer;
+   typedef CharT                                         char_type;
+   typedef index_key<CharT, void_pointer>        key_type;
+   typedef index_data<void_pointer>              mapped_type;
+   typedef typename segment_manager_base_type
+      <MemoryAlgorithm>::type                            segment_manager_base;
+
+   template<class HeaderBase>
+   struct intrusive_value_type
+   {  typedef intrusive_value_type_impl<HeaderBase, CharT, typename segment_manager_base::size_type>  type; };
+
+   typedef intrusive_compare_key<CharT>            intrusive_compare_key_type;
+};
+
+template<class Iterator, bool intrusive>
+class segment_manager_iterator_value_adaptor
+{
+   typedef typename Iterator::value_type        iterator_val_t;
+   typedef typename iterator_val_t::char_type   char_type;
+
+   public:
+   segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
+      :  m_val(&val)
+   {}
+
+   const char_type *name() const
+   {  return m_val->name(); }
+
+   unsigned short name_length() const
+   {  return m_val->name_length(); }
+
+   const void *value() const
+   {  return m_val->value(); }
+
+   const typename Iterator::value_type *m_val;
+};
+
+
+template<class Iterator>
+class segment_manager_iterator_value_adaptor<Iterator, false>
+{
+   typedef typename Iterator::value_type        iterator_val_t;
+   typedef typename iterator_val_t::first_type  first_type;
+   typedef typename iterator_val_t::second_type second_type;
+   typedef typename first_type::char_type       char_type;
+   typedef typename first_type::size_type       size_type;
+
+   public:
+   segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
+      :  m_val(&val)
+   {}
+
+   const char_type *name() const
+   {  return m_val->first.name(); }
+
+   size_type name_length() const
+   {  return m_val->first.name_length(); }
+
+   const void *value() const
+   {
+      return reinterpret_cast<block_header<size_type>*>
+         (to_raw_pointer(m_val->second.m_ptr))->value();
+   }
+
+   const typename Iterator::value_type *m_val;
+};
+
+template<class Iterator, bool intrusive>
+struct segment_manager_iterator_transform
+   :  std::unary_function< typename Iterator::value_type
+                         , segment_manager_iterator_value_adaptor<Iterator, intrusive> >
+{
+   typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type;
+
+   result_type operator()(const typename Iterator::value_type &arg) const
+   {  return result_type(arg); }
+};
+
+}  //namespace ipcdetail {
+
+//These pointers are the ones the user will use to
+//indicate previous allocation types
+static const ipcdetail::anonymous_instance_t   * anonymous_instance = 0;
+static const ipcdetail::unique_instance_t      * unique_instance = 0;
+
+namespace ipcdetail_really_deep_namespace {
+
+//Otherwise, gcc issues a warning of previously defined
+//anonymous_instance and unique_instance
+struct dummy
+{
+   dummy()
+   {
+      (void)anonymous_instance;
+      (void)unique_instance;
+   }
+};
+
+}  //detail_really_deep_namespace
+
+}} //namespace boost { namespace interprocess
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
+

+ 181 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/tmp_dir_helpers.hpp

@@ -0,0 +1,181 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
+#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <string>
+
+#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS)
+   #include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
+#endif
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+   #if defined(BOOST_INTERPROCESS_WINDOWS)
+      //This type will initialize the stamp
+      struct windows_bootstamp
+      {
+         windows_bootstamp()
+         {
+            winapi::get_last_bootup_time(stamp);
+         }
+         //Use std::string. Even if this will be constructed in shared memory, all
+         //modules/dlls are from this process so internal raw pointers to heap are always valid
+         std::string stamp;
+      };
+
+      inline void get_bootstamp(std::string &s, bool add = false)
+      {
+         const windows_bootstamp &bootstamp = windows_intermodule_singleton<windows_bootstamp>::get();
+         if(add){
+            s += bootstamp.stamp;
+         }
+         else{
+            s = bootstamp.stamp;
+         }
+      }
+   #elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
+      inline void get_bootstamp(std::string &s, bool add = false)
+      {
+         // FreeBSD specific: sysctl "kern.boottime"
+         int request[2] = { CTL_KERN, KERN_BOOTTIME };
+         struct ::timeval result;
+         std::size_t result_len = sizeof result;
+
+         if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
+            return;
+
+         char bootstamp_str[256];
+
+         const char Characters [] =
+            { '0', '1', '2', '3', '4', '5', '6', '7'
+            , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+         std::size_t char_counter = 0;
+         //32 bit values to allow 32 and 64 bit process IPC
+         boost::uint32_t fields[2] = { boost::uint32_t(result.tv_sec), boost::uint32_t(result.tv_usec) };
+         for(std::size_t field = 0; field != 2; ++field){
+            for(std::size_t i = 0; i != sizeof(fields[0]); ++i){
+               const char *ptr = (const char *)&fields[field];
+               bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
+               bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
+            }
+         }
+         bootstamp_str[char_counter] = 0;
+         if(add){
+            s += bootstamp_str;
+         }
+         else{
+            s = bootstamp_str;
+         }
+      }
+   #else
+      #error "BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME defined with no known implementation"
+   #endif
+#endif   //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+
+inline void get_tmp_base_dir(std::string &tmp_name)
+{
+   #if defined (BOOST_INTERPROCESS_WINDOWS)
+      winapi::get_shared_documents_folder(tmp_name);
+      if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){
+         tmp_name = get_temporary_path();
+      }
+   #else
+      tmp_name = get_temporary_path();
+   #endif
+   if(tmp_name.empty()){
+      error_info err = system_error_code();
+      throw interprocess_exception(err);
+   }
+   //Remove final null.
+   tmp_name += "/boost_interprocess";
+}
+
+inline void tmp_folder(std::string &tmp_name)
+{
+   get_tmp_base_dir(tmp_name);
+   #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+      tmp_name += "/";
+      get_bootstamp(tmp_name, true);
+   #endif
+}
+
+inline void tmp_filename(const char *filename, std::string &tmp_name)
+{
+   tmp_folder(tmp_name);
+   tmp_name += "/";
+   tmp_name += filename;
+}
+
+inline void create_tmp_and_clean_old(std::string &tmp_name)
+{
+   //First get the temp directory
+   std::string root_tmp_name;
+   get_tmp_base_dir(root_tmp_name);
+
+   //If fails, check that it's because already exists
+   if(!create_directory(root_tmp_name.c_str())){
+      error_info info(system_error_code());
+      if(info.get_error_code() != already_exists_error){
+         throw interprocess_exception(info);
+      }
+   }
+
+   #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
+      tmp_folder(tmp_name);
+
+      //If fails, check that it's because already exists
+      if(!create_directory(tmp_name.c_str())){
+         error_info info(system_error_code());
+         if(info.get_error_code() != already_exists_error){
+            throw interprocess_exception(info);
+         }
+      }
+      //Now erase all old directories created in the previous boot sessions
+      std::string subdir = tmp_name;
+      subdir.erase(0, root_tmp_name.size()+1);
+      delete_subdirectories(root_tmp_name, subdir.c_str());
+   #else
+      tmp_name = root_tmp_name;
+   #endif
+}
+
+inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name)
+{
+   create_tmp_and_clean_old(tmp_name);
+   tmp_name += "/";
+   tmp_name += filename;
+}
+
+inline void add_leading_slash(const char *name, std::string &new_name)
+{
+   if(name[0] != '/'){
+      new_name = '/';
+   }
+   new_name += name;
+}
+
+}  //namespace boost{
+}  //namespace interprocess {
+}  //namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP

+ 195 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/transform_iterator.hpp

@@ -0,0 +1,195 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Gennaro Prota 2003 - 2004.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
+#define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+
+#include <iterator>
+#include <boost/interprocess/detail/type_traits.hpp>
+
+namespace boost {
+namespace interprocess {
+
+template <class PseudoReference>
+struct operator_arrow_proxy
+{
+   operator_arrow_proxy(const PseudoReference &px)
+      :  m_value(px)
+   {}
+
+   PseudoReference* operator->() const { return &m_value; }
+   // This function is needed for MWCW and BCC, which won't call operator->
+   // again automatically per 13.3.1.2 para 8
+//   operator T*() const { return &m_value; }
+   mutable PseudoReference m_value;
+};
+
+template <class T>
+struct operator_arrow_proxy<T&>
+{
+   operator_arrow_proxy(T &px)
+      :  m_value(px)
+   {}
+
+   T* operator->() const { return const_cast<T*>(&m_value); }
+   // This function is needed for MWCW and BCC, which won't call operator->
+   // again automatically per 13.3.1.2 para 8
+//   operator T*() const { return &m_value; }
+   T &m_value;
+};
+
+template <class Iterator, class UnaryFunction>
+class transform_iterator
+   : public UnaryFunction
+   , public std::iterator
+      < typename Iterator::iterator_category
+      , typename ipcdetail::remove_reference<typename UnaryFunction::result_type>::type
+      , typename Iterator::difference_type
+      , operator_arrow_proxy<typename UnaryFunction::result_type>
+      , typename UnaryFunction::result_type>
+{
+   public:
+   explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
+      :  UnaryFunction(f), m_it(it)
+   {}
+
+   explicit transform_iterator()
+      :  UnaryFunction(), m_it()
+   {}
+
+   //Constructors
+   transform_iterator& operator++()
+   { increment();   return *this;   }
+
+   transform_iterator operator++(int)
+   {
+      transform_iterator result (*this);
+      increment();
+      return result;
+   }
+
+   transform_iterator& operator--()
+   { decrement();   return *this;   }
+
+   transform_iterator operator--(int)
+   {
+      transform_iterator result (*this);
+      decrement();
+      return result;
+   }
+
+   friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
+   { return i.equal(i2); }
+
+   friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
+   { return !(i == i2); }
+
+   friend bool operator< (const transform_iterator& i, const transform_iterator& i2)
+   { return i < i2; }
+
+   friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
+   { return i2 < i; }
+
+   friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
+   { return !(i > i2); }
+
+   friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
+   { return !(i < i2); }
+
+   friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
+   { return i2.distance_to(i); }
+
+   //Arithmetic
+   transform_iterator& operator+=(typename Iterator::difference_type off)
+   {  this->advance(off); return *this;   }
+
+   transform_iterator operator+(typename Iterator::difference_type off) const
+   {
+      transform_iterator other(*this);
+      other.advance(off);
+      return other;
+   }
+
+   friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
+   {  return right + off; }
+
+   transform_iterator& operator-=(typename Iterator::difference_type off)
+   {  this->advance(-off); return *this;   }
+
+   transform_iterator operator-(typename Iterator::difference_type off) const
+   {  return *this + (-off);  }
+
+   typename UnaryFunction::result_type operator*() const
+   { return dereference(); }
+
+   typename UnaryFunction::result_type operator[](typename Iterator::difference_type off) const
+   { return UnaryFunction::operator()(m_it[off]); }
+
+   operator_arrow_proxy<typename UnaryFunction::result_type>
+      operator->() const
+   { return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference());  }
+
+   Iterator & base()
+   {  return m_it;   }
+
+   const Iterator & base() const
+   {  return m_it;   }
+
+   private:
+   Iterator m_it;
+
+   void increment()
+   { ++m_it; }
+
+   void decrement()
+   { --m_it; }
+
+   bool equal(const transform_iterator &other) const
+   {  return m_it == other.m_it;   }
+
+   bool less(const transform_iterator &other) const
+   {  return other.m_it < m_it;   }
+
+   typename UnaryFunction::result_type dereference() const
+   { return UnaryFunction::operator()(*m_it); }
+
+   void advance(typename Iterator::difference_type n)
+   {  std::advance(m_it, n); }
+
+   typename Iterator::difference_type distance_to(const transform_iterator &other)const
+   {  return std::distance(other.m_it, m_it); }
+};
+
+template <class Iterator, class UnaryFunc>
+transform_iterator<Iterator, UnaryFunc>
+make_transform_iterator(Iterator it, UnaryFunc fun)
+{
+   return transform_iterator<Iterator, UnaryFunc>(it, fun);
+}
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
+

+ 158 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/type_traits.hpp

@@ -0,0 +1,158 @@
+//////////////////////////////////////////////////////////////////////////////
+// (C) Copyright John Maddock 2000.
+// (C) Copyright Ion Gaztanaga 2005-2012.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
+#define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+struct nat{};
+
+template<class T>
+struct remove_reference
+{
+   typedef T type;
+};
+
+template<class T>
+struct remove_reference<T&>
+{
+   typedef T type;
+};
+
+template<class T>
+struct is_reference
+{
+   static const bool value = false;
+};
+
+template<class T>
+struct is_reference<T&>
+{
+   static const bool value = true;
+};
+
+template<class T>
+struct is_pointer
+{
+   static const bool value = false;
+};
+
+template<class T>
+struct is_pointer<T*>
+{
+   static const bool value = true;
+};
+
+template <typename T>
+struct add_reference
+{
+    typedef T& type;
+};
+
+template<class T>
+struct add_reference<T&>
+{
+    typedef T& type;
+};
+
+template<>
+struct add_reference<void>
+{
+    typedef nat &type;
+};
+
+template<>
+struct add_reference<const void>
+{
+    typedef const nat &type;
+};
+
+template <class T>
+struct add_const_reference
+{  typedef const T &type;   };
+
+template <class T>
+struct add_const_reference<T&>
+{  typedef T& type;   };
+
+template<class T>
+struct remove_const
+{
+   typedef T type;
+};
+
+template<class T>
+struct remove_const<const T>
+{
+   typedef T type;
+};
+
+template<class T>
+struct remove_volatile
+{
+   typedef T type;
+};
+
+template<class T>
+struct remove_volatile<volatile T>
+{
+   typedef T type;
+};
+
+template<class T>
+struct remove_const_volatile
+{
+   typedef typename remove_const<typename remove_volatile<T>::type>::type type;
+};
+
+template <typename T, typename U>
+struct is_same
+{
+   typedef char yes_type;
+   struct no_type
+   {
+      char padding[8];
+   };
+
+   template <typename V>
+   static yes_type is_same_tester(V*, V*);
+   static no_type is_same_tester(...);
+
+   static T *t;
+   static U *u;
+
+   static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
+};
+
+template<class T, class U>
+struct is_cv_same
+{
+   static const bool value = is_same< typename remove_const_volatile<T>::type
+                                    , typename remove_const_volatile<U>::type >::value;
+};
+
+} // namespace ipcdetail
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP

+ 218 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/utilities.hpp

@@ -0,0 +1,218 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Gennaro Prota 2003 - 2004.
+//
+// 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
+#define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/move/move.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/interprocess/detail/min_max.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/transform_iterator.hpp>
+#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/containers/version_type.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/move/move.hpp>
+#include <boost/static_assert.hpp>
+#include <utility>
+#include <algorithm>
+#include <climits>
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template <class T>
+inline T* to_raw_pointer(T* p)
+{  return p; }
+
+template <class Pointer>
+inline typename boost::intrusive::pointer_traits<Pointer>::element_type*
+to_raw_pointer(const Pointer &p)
+{  return boost::interprocess::ipcdetail::to_raw_pointer(p.operator->());  }
+
+//!To avoid ADL problems with swap
+template <class T>
+inline void do_swap(T& x, T& y)
+{
+   using std::swap;
+   swap(x, y);
+}
+
+//Rounds "orig_size" by excess to round_to bytes
+template<class SizeType>
+inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to)
+{
+   return ((orig_size-1)/round_to+1)*round_to;
+}
+
+//Truncates "orig_size" to a multiple of "multiple" bytes.
+template<class SizeType>
+inline SizeType get_truncated_size(SizeType orig_size, SizeType multiple)
+{
+   return orig_size/multiple*multiple;
+}
+
+//Rounds "orig_size" by excess to round_to bytes. round_to must be power of two
+template<class SizeType>
+inline SizeType get_rounded_size_po2(SizeType orig_size, SizeType round_to)
+{
+   return ((orig_size-1)&(~(round_to-1))) + round_to;
+}
+
+//Truncates "orig_size" to a multiple of "multiple" bytes. multiple must be power of two
+template<class SizeType>
+inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple)
+{
+   return (orig_size & (~(multiple-1)));
+}
+
+template <std::size_t OrigSize, std::size_t RoundTo>
+struct ct_rounded_size
+{
+   BOOST_STATIC_ASSERT((RoundTo != 0));
+   static const std::size_t intermediate_value = (OrigSize-1)/RoundTo+1;
+   BOOST_STATIC_ASSERT(intermediate_value <= std::size_t(-1)/RoundTo);
+   static const std::size_t value = intermediate_value*RoundTo;
+};
+
+// Gennaro Prota wrote this. Thanks!
+template <int p, int n = 4>
+struct ct_max_pow2_less
+{
+   static const std::size_t c = 2*n < p;
+
+   static const std::size_t value =
+         c ? (ct_max_pow2_less< c*p, 2*c*n>::value) : n;
+};
+
+template <>
+struct ct_max_pow2_less<0, 0>
+{
+   static const std::size_t value = 0;
+};
+
+}  //namespace ipcdetail {
+
+//!Trait class to detect if an index is a node
+//!index. This allows more efficient operations
+//!when deallocating named objects.
+template <class Index>
+struct is_node_index
+{
+   static const bool value = false;
+};
+
+//!Trait class to detect if an index is an intrusive
+//!index. This will embed the derivation hook in each
+//!allocation header, to provide memory for the intrusive
+//!container.
+template <class Index>
+struct is_intrusive_index
+{
+   static const bool value = false;
+};
+
+template <typename T> T*
+addressof(T& v)
+{
+  return reinterpret_cast<T*>(
+       &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+}
+
+template<class SizeType>
+struct sqrt_size_type_max
+{
+   static const SizeType value = (SizeType(1) << (sizeof(SizeType)*(CHAR_BIT/2)))-1;
+};
+
+template<class SizeType>
+inline bool multiplication_overflows(SizeType a, SizeType b)
+{
+   const SizeType sqrt_size_max = sqrt_size_type_max<SizeType>::value;
+   return   //Fast runtime check 
+         (  (a | b) > sqrt_size_max &&
+            //Slow division check 
+            b && a > SizeType(-1)/b
+         );
+}
+
+template<std::size_t SztSizeOfType, class SizeType>
+inline bool size_overflows(SizeType count)
+{
+   //Compile time-check
+   BOOST_STATIC_ASSERT(SztSizeOfType <= SizeType(-1));
+   //Runtime check
+   return multiplication_overflows(SizeType(SztSizeOfType), count);
+}
+
+template<class RawPointer>
+class pointer_size_t_caster
+{
+   public:
+   explicit pointer_size_t_caster(std::size_t sz)
+      : m_ptr(reinterpret_cast<RawPointer>(sz))
+   {}
+
+   explicit pointer_size_t_caster(RawPointer p)
+      : m_ptr(p)
+   {}
+
+   std::size_t size() const
+   {   return reinterpret_cast<std::size_t>(m_ptr);   }
+
+   RawPointer pointer() const
+   {   return m_ptr;   }
+
+   private:
+   RawPointer m_ptr;
+};
+
+
+template<class SizeType>
+inline bool sum_overflows(SizeType a, SizeType b)
+{  return SizeType(-1) - a < b;  }
+
+//Anti-exception node eraser
+template<class Cont>
+class value_eraser
+{
+   public:
+   value_eraser(Cont & cont, typename Cont::iterator it)
+      : m_cont(cont), m_index_it(it), m_erase(true){}
+   ~value_eraser()
+   {  if(m_erase) m_cont.erase(m_index_it);  }
+
+   void release() {  m_erase = false;  }
+
+   private:
+   Cont                   &m_cont;
+   typename Cont::iterator m_index_it;
+   bool                    m_erase;
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
+

+ 153 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/variadic_templates_tools.hpp

@@ -0,0 +1,153 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
+#define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <cstddef>   //std::size_t
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail {
+
+template<typename... Values>
+class tuple;
+
+template<> class tuple<>
+{};
+
+template<typename Head, typename... Tail>
+class tuple<Head, Tail...>
+   : private tuple<Tail...>
+{
+   typedef tuple<Tail...> inherited;
+
+   public:
+   tuple() { }
+
+   // implicit copy-constructor is okay
+   // Construct tuple from separate arguments.
+   tuple(typename add_const_reference<Head>::type v,
+         typename add_const_reference<Tail>::type... vtail)
+   : inherited(vtail...), m_head(v)
+   {}
+
+   // Construct tuple from another tuple.
+   template<typename... VValues>
+   tuple(const tuple<VValues...>& other)
+      : m_head(other.head()), inherited(other.tail())
+   {}
+
+   template<typename... VValues>
+   tuple& operator=(const tuple<VValues...>& other)
+   {
+      m_head = other.head();
+      tail() = other.tail();
+      return this;
+   }
+
+   typename add_reference<Head>::type head()             {  return m_head; }
+   typename add_reference<const Head>::type head() const {  return m_head; }
+
+   inherited& tail()             { return *this; }
+   const inherited& tail() const { return *this; }
+
+   protected:
+   Head m_head;
+};
+
+
+template<typename... Values>
+tuple<Values&&...> tie_forward(Values&&... values)
+{ return tuple<Values&&...>(values...); }
+
+template<int I, typename Tuple>
+struct tuple_element;
+
+template<int I, typename Head, typename... Tail>
+struct tuple_element<I, tuple<Head, Tail...> >
+{
+   typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_element<0, tuple<Head, Tail...> >
+{
+   typedef Head type;
+};
+
+template<int I, typename Tuple>
+class get_impl;
+
+template<int I, typename Head, typename... Values>
+class get_impl<I, tuple<Head, Values...> >
+{
+   typedef typename tuple_element<I-1, tuple<Values...> >::type   Element;
+   typedef get_impl<I-1, tuple<Values...> >                       Next;
+
+   public:
+   typedef typename add_reference<Element>::type                  type;
+   typedef typename add_const_reference<Element>::type            const_type;
+   static type get(tuple<Head, Values...>& t)              { return Next::get(t.tail()); }
+   static const_type get(const tuple<Head, Values...>& t)  { return Next::get(t.tail()); }
+};
+
+template<typename Head, typename... Values>
+class get_impl<0, tuple<Head, Values...> >
+{
+   public:
+   typedef typename add_reference<Head>::type         type;
+   typedef typename add_const_reference<Head>::type   const_type;
+   static type       get(tuple<Head, Values...>& t)      { return t.head(); }
+   static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
+};
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
+{  return get_impl<I, tuple<Values...> >::get(t);  }
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
+{  return get_impl<I, tuple<Values...> >::get(t);  }
+
+////////////////////////////////////////////////////
+// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
+// be used to "unpack" into comma-separated values
+// in a function call.
+////////////////////////////////////////////////////
+
+template<int... Indexes>
+struct index_tuple{};
+
+template<std::size_t Num, typename Tuple = index_tuple<> >
+struct build_number_seq;
+
+template<std::size_t Num, int... Indexes>
+struct build_number_seq<Num, index_tuple<Indexes...> >
+   : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
+{};
+
+template<int... Indexes>
+struct build_number_seq<0, index_tuple<Indexes...> >
+{  typedef index_tuple<Indexes...> type;  };
+
+
+}}}   //namespace boost { namespace interprocess { namespace ipcdetail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP

File diff suppressed because it is too large
+ 1852 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/win32_api.hpp


+ 306 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/windows_intermodule_singleton.hpp

@@ -0,0 +1,306 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
+#define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#if !defined(BOOST_INTERPROCESS_WINDOWS)
+   #error "This header can't be included from non-windows operating systems"
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/interprocess/detail/intermodule_singleton_common.hpp>
+#include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
+#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/cstdint.hpp>
+#include <string>
+#include <map>
+
+namespace boost{
+namespace interprocess{
+namespace ipcdetail{
+
+namespace intermodule_singleton_helpers {
+
+//This global map will be implemented using 3 sync primitives:
+//
+//1)  A named mutex that will implement global mutual exclusion between
+//    threads from different modules/dlls
+//
+//2)  A semaphore that will act as a global counter for modules attached to the global map
+//    so that the global map can be destroyed when the last module is detached.
+//
+//3)  A semaphore that will be hacked to hold the address of a heap-allocated map in the
+//    max and current semaphore count.
+class windows_semaphore_based_map
+{
+   typedef std::map<std::string, ref_count_ptr> map_type;
+
+   public:
+   windows_semaphore_based_map()
+   {
+      map_type *m = new map_type;
+      boost::uint32_t initial_count = 0;
+      boost::uint32_t max_count = 0;
+
+      //Windows user address space sizes:
+      //32 bit windows: [32 bit processes] 2GB or 3GB (31/32 bits)
+      //64 bit windows: [32 bit processes] 2GB or 4GB (31/32 bits)
+      //                [64 bit processes] 2GB or 8TB (31/43 bits)
+      //
+      //Windows semaphores use 'long' parameters (32 bits in LLP64 data model) and
+      //those values can't be negative, so we have 31 bits to store something
+      //in max_count and initial count parameters.
+      //Also, max count must be bigger than 0 and bigger or equal than initial count.
+      if(sizeof(void*) == sizeof(boost::uint32_t)){
+         //This means that for 32 bit processes, a semaphore count (31 usable bits) is
+         //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits).
+         //The max count will hold the pointer value and current semaphore count
+         //will be zero.
+         //
+         //Relying in UB with a cast through union, but all known windows compilers
+         //accept this (C11 also accepts this).
+         union caster_union
+         {
+            void *addr;
+            boost::uint32_t addr_uint32;
+         } caster;
+         caster.addr = m;
+         //memory is at least 4 byte aligned in windows
+         BOOST_ASSERT((caster.addr_uint32 & boost::uint32_t(3)) == 0);
+         max_count = caster.addr_uint32 >> 2;
+      }
+      else if(sizeof(void*) == sizeof(boost::uint64_t)){
+         //Relying in UB with a cast through union, but all known windows compilers
+         //accept this (C11 accepts this).
+         union caster_union
+         {
+            void *addr;
+            boost::uint64_t addr_uint64;
+         } caster;
+         caster.addr = m;
+         //We'll encode the address using 30 bits in each 32 bit high and low parts.
+         //High part will be the sem max count, low part will be the sem initial count.
+         //(restrictions: max count > 0, initial count >= 0 and max count >= initial count):
+         //
+         // - Low part will be shifted two times (4 byte alignment) so that top
+         //   two bits are cleared (the top one for sign, the next one to
+         //   assure low part value is always less than the high part value.
+         // - The top bit of the high part will be cleared and the next bit will be 1
+         //   (so high part is always bigger than low part due to the quasi-top bit).
+         //
+         //   This means that the addresses we can store must be 4 byte aligned
+         //   and less than 1 ExbiBytes ( 2^60 bytes, ~1 ExaByte). User-level address space in Windows 64
+         //   is much less than this (8TB, 2^43 bytes): "1 EByte (or it was 640K?) ought to be enough for anybody" ;-).
+         caster.addr = m;
+         BOOST_ASSERT((caster.addr_uint64 & boost::uint64_t(3)) == 0);
+         max_count = boost::uint32_t(caster.addr_uint64 >> 32);
+         initial_count = boost::uint32_t(caster.addr_uint64);
+         initial_count = initial_count/4;
+         //Make sure top two bits are zero
+         BOOST_ASSERT((max_count & boost::uint32_t(0xC0000000)) == 0);
+         //Set quasi-top bit
+         max_count |= boost::uint32_t(0x40000000);
+      }
+      bool created = false;
+      const permissions & perm = permissions();
+      std::string pid_creation_time, name;
+      get_pid_creation_time_str(pid_creation_time);
+      name = "bipc_gmap_sem_lock_";
+      name += pid_creation_time;
+      bool success = m_mtx_lock.open_or_create(name.c_str(), perm);
+      name = "bipc_gmap_sem_count_";
+      name += pid_creation_time;
+      scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+      {
+         success = success && m_sem_count.open_or_create
+            ( name.c_str(), static_cast<long>(0), winapi_semaphore_wrapper::MaxCount, perm, created);
+         name = "bipc_gmap_sem_map_";
+         name += pid_creation_time;
+         success = success && m_sem_map.open_or_create
+            (name.c_str(), initial_count, max_count, perm, created);
+         if(!success){
+            //winapi_xxx wrappers do the cleanup...
+            throw int(0);
+         }
+         if(!created){
+            delete m;
+         }
+         else{
+            BOOST_ASSERT(&get_map_unlocked() == m);
+         }
+         m_sem_count.post();
+      }
+   }
+
+   map_type &get_map_unlocked()
+   {
+      if(sizeof(void*) == sizeof(boost::uint32_t)){
+         union caster_union
+         {
+            void *addr;
+            boost::uint32_t addr_uint32;
+         } caster;
+         caster.addr = 0;
+         caster.addr_uint32 = m_sem_map.limit();
+         caster.addr_uint32 = caster.addr_uint32 << 2;
+         return *static_cast<map_type*>(caster.addr);
+      }
+      else{
+         union caster_union
+         {
+            void *addr;
+            boost::uint64_t addr_uint64;
+         } caster;
+         boost::uint32_t max_count(m_sem_map.limit()), initial_count(m_sem_map.value());
+         //Clear quasi-top bit
+         max_count &= boost::uint32_t(0xBFFFFFFF);
+         caster.addr_uint64 = max_count;
+         caster.addr_uint64 =  caster.addr_uint64 << 32;
+         caster.addr_uint64 |= boost::uint64_t(initial_count) << 2;
+         return *static_cast<map_type*>(caster.addr);
+      }
+   }
+
+   ref_count_ptr *find(const char *name)
+   {
+      scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+      map_type &map = this->get_map_unlocked();
+      map_type::iterator it = map.find(std::string(name));
+      if(it != map.end()){
+         return &it->second;
+      }
+      else{
+         return 0;
+      }
+   }
+
+   ref_count_ptr * insert(const char *name, const ref_count_ptr &ref)
+   {
+      scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+      map_type &map = this->get_map_unlocked();
+      map_type::iterator it = map.insert(map_type::value_type(std::string(name), ref)).first;
+      return &it->second;
+   }
+
+   bool erase(const char *name)
+   {
+      scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+      map_type &map = this->get_map_unlocked();
+      return map.erase(std::string(name)) != 0;
+   }
+
+   template<class F>
+   void atomic_func(F &f)
+   {
+      scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+      f();
+   }
+
+   ~windows_semaphore_based_map()
+   {
+      scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
+      m_sem_count.wait();
+      if(0 == m_sem_count.value()){
+         delete &this->get_map_unlocked();
+      }
+      //First close sems to protect this with the external mutex
+      m_sem_map.close();
+      m_sem_count.close();
+      //Once scoped_lock unlocks the mutex, the destructor will close the handle...
+   }
+
+   private:
+   winapi_mutex_wrapper     m_mtx_lock;
+   winapi_semaphore_wrapper m_sem_map;
+   winapi_semaphore_wrapper m_sem_count;
+};
+
+template<>
+struct thread_safe_global_map_dependant<windows_semaphore_based_map>
+{
+   static void apply_gmem_erase_logic(const char *, const char *){}
+
+   static bool remove_old_gmem()
+   { return true; }
+
+   struct lock_file_logic
+   {
+      lock_file_logic(windows_semaphore_based_map &)
+         : retry_with_new_map(false)
+      {}
+
+      void operator()(void){}
+      bool retry() const { return retry_with_new_map; }
+      private:
+      const bool retry_with_new_map;
+   };
+
+   static void construct_map(void *addr)
+   {
+      ::new (addr)windows_semaphore_based_map;
+   }
+
+   struct unlink_map_logic
+   {
+      unlink_map_logic(windows_semaphore_based_map &)
+      {}
+      void operator()(){}
+   };
+
+   static ref_count_ptr *find(windows_semaphore_based_map &map, const char *name)
+   {
+      return map.find(name);
+   }
+
+   static ref_count_ptr * insert(windows_semaphore_based_map &map, const char *name, const ref_count_ptr &ref)
+   {
+      return map.insert(name, ref);
+   }
+
+   static bool erase(windows_semaphore_based_map &map, const char *name)
+   {
+      return map.erase(name);
+   }
+
+   template<class F>
+   static void atomic_func(windows_semaphore_based_map &map, F &f)
+   {
+      map.atomic_func(f);
+   }
+};
+
+}  //namespace intermodule_singleton_helpers {
+
+template<typename C, bool LazyInit = true, bool Phoenix = true>
+class windows_intermodule_singleton
+   : public intermodule_singleton_impl
+      < C
+      , LazyInit
+      , Phoenix
+      , intermodule_singleton_helpers::windows_semaphore_based_map
+      >
+{};
+
+}  //namespace ipcdetail{
+}  //namespace interprocess{
+}  //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP

+ 160 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/workaround.hpp

@@ -0,0 +1,160 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
+#define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+   #define BOOST_INTERPROCESS_WINDOWS
+   #define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION
+   #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+#else
+   #include <unistd.h>
+
+   #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
+      //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
+      //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work.
+      #if !defined(__CYGWIN__) && !defined(__APPLE__)
+         #define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
+      #endif
+   #endif
+
+   #if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0)
+      #define BOOST_INTERPROCESS_POSIX_BARRIERS
+   #endif
+
+   #if defined(_POSIX_SEMAPHORES) && ((_POSIX_SEMAPHORES - 0) > 0)
+      #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+      #if defined(__CYGWIN__)
+         #define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
+      #endif
+   //Some platforms have a limited (name length) named semaphore support
+   #elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__)
+      #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+   #endif
+
+   #if ((defined _V6_ILP32_OFFBIG)  &&(_V6_ILP32_OFFBIG   - 0 > 0)) ||\
+       ((defined _V6_LP64_OFF64)    &&(_V6_LP64_OFF64     - 0 > 0)) ||\
+       ((defined _V6_LPBIG_OFFBIG)  &&(_V6_LPBIG_OFFBIG   - 0 > 0)) ||\
+       ((defined _XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\
+       ((defined _XBS5_LP64_OFF64)  &&(_XBS5_LP64_OFF64   - 0 > 0)) ||\
+       ((defined _XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\
+       ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS  - 0 >= 64))||\
+       ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS  - 0 >= 64))
+      #define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T
+   #endif
+
+   //Check for XSI shared memory objects. They are available in nearly all UNIX platforms
+   #if !defined(__QNXNTO__)
+      #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+   #endif
+
+   #if defined(_POSIX_SHARED_MEMORY_OBJECTS) && ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
+      #define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+   #else
+      //VMS and MACOS don't define it but they have shm_open/close interface
+      #if defined(__vms)
+         #if __CRTL_VER >= 70200000
+            #define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+         #endif
+         //Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
+      #elif defined (__APPLE__)
+         //#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+         //#define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW
+      #endif
+   #endif
+
+   //Now check if we have only XSI shared memory
+   #if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) &&\
+      !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
+      //#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY
+   #endif
+
+   #if defined(_POSIX_TIMEOUTS) && ((_POSIX_TIMEOUTS - 0) > 0)
+      #define BOOST_INTERPROCESS_POSIX_TIMEOUTS
+   #endif
+
+   #ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
+      //Some systems have filesystem-based resources, so the
+      //portable "/shmname" format does not work due to permission issues
+      //For those systems we need to form a path to a temporary directory:
+      //          hp-ux               tru64               vms               freebsd
+      #if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7))
+         #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
+      //Some systems have "jailed" environments where shm usage is restricted at runtime
+      //and temporary file file based shm is possible in those executions.
+      #elif defined(__FreeBSD__)
+         #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
+      #endif
+   #endif
+
+   #ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
+      #if defined(__osf__) || defined(__vms)
+         #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
+      #endif
+   #endif
+
+   #if defined(_POSIX_VERSION) && defined(_XOPEN_VERSION) && \
+       (((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500))
+      #define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
+   #endif
+
+   #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+      #define BOOST_INTERPROCESS_BSD_DERIVATIVE
+      #include <sys/sysctl.h>
+      #if defined(CTL_KERN) && defined (KERN_BOOTTIME)
+         //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+      #endif
+   #endif
+#endif   //!defined(BOOST_INTERPROCESS_WINDOWS)
+
+#if    !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
+   #define BOOST_INTERPROCESS_PERFECT_FORWARDING
+#endif
+
+//Now declare some Boost.Interprocess features depending on the implementation
+#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
+   #define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
+   #define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
+#endif
+
+// Timeout duration use if BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING is set
+#ifndef BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS
+   #define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
+#endif
+
+//Other switches
+//BOOST_INTERPROCESS_MSG_QUEUE_USES_CIRC_INDEX
+//message queue uses a circular queue as index instead of an array (better performance)
+//Boost version < 1.52 uses an array, so undef this if you want to communicate
+//with processes compiled with those versions.
+#define BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX
+
+//Inline attributes
+#if defined(_MSC_VER)
+   #define BOOST_INTERPROCESS_ALWAYS_INLINE __forceinline
+#elif defined (__GNUC__)
+   #define BOOST_INTERPROCESS_ALWAYS_INLINE __attribute__((__always_inline__))
+#else
+   #define BOOST_INTERPROCESS_ALWAYS_INLINE inline
+#endif
+
+#if defined(_MSC_VER)
+   #define BOOST_INTERPROCESS_NEVER_INLINE __declspec(noinline)
+#elif defined (__GNUC__)
+   #define BOOST_INTERPROCESS_NEVER_INLINE __attribute__((__noinline__))
+#endif
+
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP

+ 392 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/xsi_shared_memory_device.hpp

@@ -0,0 +1,392 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
+#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if defined(BOOST_INTERPROCESS_WINDOWS)
+#error "This header can't be used in Windows operating systems"
+#endif
+
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+#include <boost/interprocess/xsi_shared_memory.hpp>
+#include <boost/interprocess/sync/xsi/xsi_named_mutex.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <cstddef>
+#include <boost/cstdint.hpp>
+#include <string>
+#include <cstring>
+
+//!\file
+//!Describes a class representing a native xsi shared memory.
+
+namespace boost {
+namespace interprocess {
+
+class xsi_shared_memory_device
+{
+   /// @cond
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
+   /// @endcond
+
+   public:
+
+   xsi_shared_memory_device();
+
+   xsi_shared_memory_device(create_only_t, const char *name, mode_t mode, std::size_t size)
+   {  this->priv_open_or_create_name_only(ipcdetail::DoCreate, name, mode, size);  }
+
+   xsi_shared_memory_device(open_or_create_t, const char *name, mode_t mode, std::size_t size)
+   {  this->priv_open_or_create_name_only(ipcdetail::DoOpenOrCreate, name, mode, size);  }
+
+   xsi_shared_memory_device(open_only_t, const char *name, mode_t mode)
+   {  this->priv_open_or_create_name_only(ipcdetail::DoOpen, name, mode, 0);  }
+
+   xsi_shared_memory_device(create_only_t, const char *filepath, boost::uint8_t id, mode_t mode, std::size_t size)
+   {  this->priv_open_or_create_name_id(ipcdetail::DoCreate, name, id, mode, size);  }
+
+   xsi_shared_memory_device(open_or_create_t, const char *filepath, boost::uint8_t id, mode_t mode, std::size_t size)
+   {  this->priv_open_or_create_name_id(ipcdetail::DoOpenOrCreate, id, name, mode, size);  }
+
+   xsi_shared_memory_device(open_only_t, const char *filepath, boost::uint8_t id, mode_t mode)
+   {  this->priv_open_or_create_name_id(ipcdetail::DoOpen, name, id, mode, 0);  }
+
+   xsi_shared_memory_device(BOOST_RV_REF(xsi_shared_memory_device) moved)
+   {  this->swap(moved);   }
+
+   xsi_shared_memory_device &operator=(BOOST_RV_REF(xsi_shared_memory_device) moved)
+   {
+      xsi_shared_memory_device tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Swaps two xsi_shared_memory_device. Does not throw
+   void swap(xsi_shared_memory_device &other);
+
+   //!Destroys *this. The shared memory won't be destroyed, just
+   //!this connection to it. Use remove() to destroy the shared memory.
+   ~xsi_shared_memory_device();
+
+   //!Returns the name of the
+   //!shared memory.
+   const char *get_name() const;
+
+   //!Returns the shared memory ID that
+   //!identifies the shared memory
+   int get_shmid() const;
+
+   //!Returns access
+   //!permissions
+   mode_t get_mode() const;
+
+   //!Returns the mapping handle.
+   //!Never throws
+   mapping_handle_t get_mapping_handle() const;
+
+   //!Erases a XSI shared memory object identified by shmname
+   //!from the system.
+   //!Returns false on error. Never throws
+   static bool remove(const char *shmname);
+
+   //!Erases the XSI shared memory object identified by shmid
+   //!from the system.
+   //!Returns false on error. Never throws
+   static bool remove(int shmid);
+
+   /// @cond
+   private:
+   template<int Dummy>
+   struct info_constants_t
+   {
+      static const std::size_t MaxName = 32;
+      static const std::size_t FirstID = 2;
+      static const std::size_t LastID  = 256;
+      static const std::size_t NumID   = LastID - FirstID;
+   };
+
+   struct info_t
+   {
+      struct names_t
+      {
+         char buf[info_constants_t<0>::MaxName];
+      } names[info_constants_t<0>::NumID];
+   };
+
+   static void priv_obtain_index(mapped_region &m, xsi_named_mutex &m, std::string &path);
+   static bool priv_remove_dead_memory(info_t *info, const char *path);
+
+   bool priv_open_or_create_name_only( ipcdetail::create_enum_t type
+                           , const char *shmname
+                           , mode_t mode
+                           , std::size_t size);
+   bool priv_open_or_create_name_id( ipcdetail::create_enum_t type
+                           , const char *shmname
+                           , boost::uint8_t id
+                           , mode_t mode
+                           , std::size_t size);
+   xsi_shared_memory m_shm;
+   mode_t            m_mode;
+   std::string       m_name;
+   /// @endcond
+};
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::MaxName;
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::FirstID;
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::LastID;
+
+template<int Dummy>
+const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::NumID;
+
+/// @cond
+
+inline xsi_shared_memory_device::xsi_shared_memory_device()
+   : m_shm(), m_mode(invalid_mode), m_name()
+{}
+
+inline xsi_shared_memory_device::~xsi_shared_memory_device()
+{}
+
+inline const char *xsi_shared_memory_device::get_name() const
+{  return m_name.c_str(); }
+
+inline void xsi_shared_memory_device::swap(xsi_shared_memory_device &other)
+{
+   m_shm.swap(other.m_shm);
+   std::swap(m_mode,  other.m_mode);
+   m_name.swap(other.m_name);
+}
+
+inline mapping_handle_t xsi_shared_memory_device::get_mapping_handle() const
+{  return m_shm.get_mapping_handle();   }
+
+inline mode_t xsi_shared_memory_device::get_mode() const
+{  return m_mode; }
+
+inline int xsi_shared_memory::get_shmid() const
+{  return m_shm.get_shmid(); }
+
+inline void xsi_shared_memory_device::priv_obtain_index
+   (mapped_region &reg, xsi_named_mutex &mut, std::string &path)
+{
+   const char *const filename = "xsi_shm_emulation_file";
+   permissions p;
+   p.set_unrestricted();
+   std::string xsi_shm_emulation_file_path;
+   ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, xsi_shm_emulation_file_path);
+   ipcdetail::create_or_open_file(xsi_shm_emulation_file_path.c_str(), read_write, p);
+   const std::size_t MemSize = sizeof(info_t);
+
+   xsi_shared_memory index_shm(open_or_create, xsi_shm_emulation_file_path.c_str(), 1, MemSize, 0666);
+   mapped_region r(index_shm, read_write, 0, MemSize, 0);
+   xsi_named_mutex m(open_or_create, xsi_shm_emulation_file_path.c_str(), 2, 0666);
+   reg = boost::move(r);
+   mut = boost::move(m);
+   path.swap(xsi_shm_emulation_file_path);
+}
+
+inline bool xsi_shared_memory_device::priv_remove_dead_memory
+   (xsi_shared_memory_device::info_t *info, const char *path)
+{
+   bool removed = false;
+   for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
+      if(info->names[i].buf[0]){
+         try{
+            xsi_shared_memory temp( open_only, path, i+info_constants_t<0>::FirstID, 0600);
+         }
+         catch(interprocess_exception &e){
+               if(e.get_error_code() == not_found_error){
+                  std::memset(info->names[i].buf, 0, info_constants_t<0>::MaxName);
+                  removed = true;
+               }
+         }
+      }
+   }
+   return removed;
+}
+
+inline bool xsi_shared_memory_device::priv_open_or_create_name_id
+   (ipcdetail::create_enum_t type, const char *filepath, mode_t mode, std::size_t size)
+{
+   //Set accesses
+   if (mode != read_write && mode != read_only){
+      error_info err = other_error;
+      throw interprocess_exception(err);
+   }
+
+   int perm = (mode == read_only) ? (0444) : (0666);
+
+   if(type == ipcdetail::DoOpen){
+      if(!found){
+         error_info err = not_found_error;
+         throw interprocess_exception(err);
+      }
+      xsi_shared_memory temp(open_only, filepath, id, perm);
+      m_shm = boost::move(temp);
+   }
+   else if(type == ipcdetail::DoCreate){
+      //Try to reuse slot
+      xsi_shared_memory temp(create_only, filepath, id, size, perm);
+      std::strcpy(info->names[target_entry].buf, shmname);
+      m_shm = boost::move(temp);
+   }
+   else{ // if(type == ipcdetail::DoOpenOrCreate){
+      xsi_shared_memory temp(open_or_create, filepath, id, size, perm);
+      m_shm = boost::move(temp);
+   }
+
+   m_mode = mode;
+   m_name.clear();
+   return true;
+}
+
+inline bool xsi_shared_memory_device::priv_open_or_create_name_only
+   (ipcdetail::create_enum_t type, const char *shmname, mode_t mode, std::size_t size)
+{
+   //Set accesses
+   if (mode != read_write && mode != read_only){
+      error_info err = other_error;
+      throw interprocess_exception(err);
+   }
+
+   if (std::strlen(shmname) >= (info_constants_t<0>::MaxName)){
+      error_info err = other_error;
+      throw interprocess_exception(err);
+   }
+
+   {
+      //Obtain index and index lock
+      mapped_region region;
+      xsi_named_mutex mut;
+      std::string xsi_shm_emulation_file_path;
+      priv_obtain_index(region, mut, xsi_shm_emulation_file_path);
+      info_t *info = static_cast<info_t *>(region.get_address());
+      scoped_lock<xsi_named_mutex> lock(mut);
+
+      //Find the correct entry or the first empty index
+      bool found = false;
+      int target_entry = -1;
+      int tries = 2;
+      while(tries--){
+         for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
+            if(target_entry < 0 && !info->names[i].buf[0]){
+               target_entry = static_cast<int>(i);
+            }
+            else if(0 == std::strcmp(info->names[i].buf, shmname)){
+               found = true;
+               target_entry = static_cast<int>(i);
+               break;
+            }
+         }
+         if(target_entry < 0){
+            if(!tries || !priv_remove_dead_memory(info, xsi_shm_emulation_file_path.c_str())){
+               error_info err = out_of_resource_error;
+               throw interprocess_exception(err);
+            }
+         }
+      }
+      //Now handle the result
+      int perm = (mode == read_only) ? (0444) : (0666);
+      if(type == ipcdetail::DoOpen){
+         if(!found){
+            error_info err = not_found_error;
+            throw interprocess_exception(err);
+         }
+         xsi_shared_memory temp( open_only, xsi_shm_emulation_file_path.c_str()
+                               , target_entry+info_constants_t<0>::FirstID, perm);
+         m_shm = boost::move(temp);
+      }
+      else{
+
+         if(type == ipcdetail::DoCreate){
+            //Try to reuse slot
+            xsi_shared_memory temp( create_only, xsi_shm_emulation_file_path.c_str()
+                                  , target_entry+info_constants_t<0>::FirstID, size, perm);
+            std::strcpy(info->names[target_entry].buf, shmname);
+            m_shm = boost::move(temp);
+         }
+         else{ // if(type == ipcdetail::DoOpenOrCreate){
+            xsi_shared_memory temp( open_or_create, xsi_shm_emulation_file_path.c_str()
+                                  , target_entry+info_constants_t<0>::FirstID, size, perm);
+            if(!found){
+               std::memset(info->names[target_entry].buf, 0, info_constants_t<0>::MaxName);
+               std::strcpy(info->names[target_entry].buf, shmname);
+            }
+            m_shm = boost::move(temp);
+         }
+      }
+   }
+
+   m_mode = mode;
+   m_name = shmname;
+   return true;
+}
+
+inline bool xsi_shared_memory_device::remove(const char *shmname)
+{
+   try{
+      //Obtain index and index lockss
+      mapped_region region;
+      xsi_named_mutex mut;
+      std::string xsi_shm_emulation_file_path;
+      priv_obtain_index(region, mut, xsi_shm_emulation_file_path);
+      scoped_lock<xsi_named_mutex> lock(mut);
+      info_t *info = static_cast<info_t *>(region.get_address());
+
+      //Now check and remove
+      bool removed = false;
+
+      for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
+         if(0 == std::strcmp(info->names[i].buf, name)){
+            xsi_shared_memory temp( open_only, xsi_shm_emulation_file_path.c_str()
+                                  , i+info_constants_t<0>::FirstID);
+            if(!xsi_shared_memory::remove(temp.get_shmid()) && (system_error_code() != invalid_argument)){
+               return false;
+            }
+            std::memset(info->names[i].buf, 0, info_constants_t<0>::MaxName);
+            removed = true;
+            break;
+         }
+      }
+      return removed;
+   }
+   catch(...){
+      return false;
+   }
+}
+
+inline bool xsi_shared_memory_device::remove(int shmid)
+{  return xsi_shared_memory::remove(shmid);  }
+
+///@endcond
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP

+ 80 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/detail/xsi_shared_memory_file_wrapper.hpp

@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
+#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
+#error "This header can't be used in operating systems without XSI (System V) shared memory support"
+#endif
+
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+
+#include <boost/interprocess/xsi_shared_memory.hpp>
+
+//!\file
+//!Describes a class representing a pseudo-file implemented on top of xsi shared memory.
+
+namespace boost {
+namespace interprocess {
+
+class xsi_shared_memory_file_wrapper
+   : public xsi_shared_memory
+{
+   /// @cond
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
+   /// @endcond
+   public:
+
+   xsi_shared_memory_file_wrapper() : xsi_shared_memory() {}
+
+   xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions())
+      : xsi_shared_memory(create_only_t(), key, size, perm.get_permissions())
+   {}
+
+   xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions())
+      : xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions())
+   {}
+
+   xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t mode, const permissions& perm = permissions())
+      : xsi_shared_memory(open_only_t(), key)
+   {}
+
+   xsi_shared_memory_file_wrapper(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved)
+   {  this->swap(moved);   }
+
+   xsi_shared_memory_file_wrapper &operator=(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved)
+   {
+      xsi_shared_memory_file_wrapper tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Swaps two xsi_shared_memory_file_wrapper. Does not throw
+   void swap(xsi_shared_memory_file_wrapper &other)
+   {  this->xsi_shared_memory::swap(other);  }
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP

+ 236 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/errors.hpp

@@ -0,0 +1,236 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+// Parts of this code are taken from boost::filesystem library
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+//  Copyright (C) 2002 Beman Dawes
+//  Copyright (C) 2001 Dietmar Kuehl
+//  Use, modification, and distribution is subject to 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)
+//
+//  See library home page at http://www.boost.org/libs/filesystem
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef BOOST_INTERPROCESS_ERRORS_HPP
+#define BOOST_INTERPROCESS_ERRORS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <stdarg.h>
+#include <string>
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+#  include <boost/interprocess/detail/win32_api.hpp>
+#else
+#  ifdef BOOST_HAS_UNISTD_H
+#    include <errno.h>        //Errors
+#    include <cstring>        //strerror
+#  else  //ifdef BOOST_HAS_UNISTD_H
+#    error Unknown platform
+#  endif //ifdef BOOST_HAS_UNISTD_H
+#endif   //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+//!\file
+//!Describes the error numbering of interprocess classes
+
+namespace boost {
+namespace interprocess {
+/// @cond
+inline int system_error_code() // artifact of POSIX and WINDOWS error reporting
+{
+   #if (defined BOOST_INTERPROCESS_WINDOWS)
+   return winapi::get_last_error();
+   #else
+   return errno; // GCC 3.1 won't accept ::errno
+   #endif
+}
+
+
+#if (defined BOOST_INTERPROCESS_WINDOWS)
+inline void fill_system_message(int sys_err_code, std::string &str)
+{
+   void *lpMsgBuf;
+   winapi::format_message(
+      winapi::format_message_allocate_buffer |
+      winapi::format_message_from_system |
+      winapi::format_message_ignore_inserts,
+      0,
+      sys_err_code,
+      winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language
+      reinterpret_cast<char *>(&lpMsgBuf),
+      0,
+      0
+   );
+   str += static_cast<const char*>(lpMsgBuf);
+   winapi::local_free( lpMsgBuf ); // free the buffer
+   while ( str.size()
+      && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
+      str.erase( str.size()-1 );
+}
+# else
+inline void fill_system_message( int system_error, std::string &str)
+{  str = std::strerror(system_error);  }
+# endif
+/// @endcond
+
+enum error_code_t
+{
+   no_error = 0,
+   system_error,     // system generated error; if possible, is translated
+                     // to one of the more specific errors below.
+   other_error,      // library generated error
+   security_error,   // includes access rights, permissions failures
+   read_only_error,
+   io_error,
+   path_error,
+   not_found_error,
+//   not_directory_error,
+   busy_error,       // implies trying again might succeed
+   already_exists_error,
+   not_empty_error,
+   is_directory_error,
+   out_of_space_error,
+   out_of_memory_error,
+   out_of_resource_error,
+   lock_error,
+   sem_error,
+   mode_error,
+   size_error,
+   corrupted_error,
+   not_such_file_or_directory,
+   invalid_argument,
+   timeout_when_locking_error,
+   timeout_when_waiting_error,
+};
+
+typedef int    native_error_t;
+
+/// @cond
+struct ec_xlate
+{
+   native_error_t sys_ec;
+   error_code_t   ec;
+};
+
+static const ec_xlate ec_table[] =
+{
+   #if (defined BOOST_INTERPROCESS_WINDOWS)
+   { /*ERROR_ACCESS_DENIED*/5L, security_error },
+   { /*ERROR_INVALID_ACCESS*/12L, security_error },
+   { /*ERROR_SHARING_VIOLATION*/32L, security_error },
+   { /*ERROR_LOCK_VIOLATION*/33L, security_error },
+   { /*ERROR_LOCKED*/212L, security_error },
+   { /*ERROR_NOACCESS*/998L, security_error },
+   { /*ERROR_WRITE_PROTECT*/19L, read_only_error },
+   { /*ERROR_NOT_READY*/21L, io_error },
+   { /*ERROR_SEEK*/25L, io_error },
+   { /*ERROR_READ_FAULT*/30L, io_error },
+   { /*ERROR_WRITE_FAULT*/29L, io_error },
+   { /*ERROR_CANTOPEN*/1011L, io_error },
+   { /*ERROR_CANTREAD*/1012L, io_error },
+   { /*ERROR_CANTWRITE*/1013L, io_error },
+   { /*ERROR_DIRECTORY*/267L, path_error },
+   { /*ERROR_INVALID_NAME*/123L, path_error },
+   { /*ERROR_FILE_NOT_FOUND*/2L, not_found_error },
+   { /*ERROR_PATH_NOT_FOUND*/3L, not_found_error },
+   { /*ERROR_DEV_NOT_EXIST*/55L, not_found_error },
+   { /*ERROR_DEVICE_IN_USE*/2404L, busy_error },
+   { /*ERROR_OPEN_FILES*/2401L, busy_error },
+   { /*ERROR_BUSY_DRIVE*/142L, busy_error },
+   { /*ERROR_BUSY*/170L, busy_error },
+   { /*ERROR_FILE_EXISTS*/80L, already_exists_error },
+   { /*ERROR_ALREADY_EXISTS*/183L, already_exists_error },
+   { /*ERROR_DIR_NOT_EMPTY*/145L, not_empty_error },
+   { /*ERROR_HANDLE_DISK_FULL*/39L, out_of_space_error },
+   { /*ERROR_DISK_FULL*/112L, out_of_space_error },
+   { /*ERROR_OUTOFMEMORY*/14L, out_of_memory_error },
+   { /*ERROR_NOT_ENOUGH_MEMORY*/8L, out_of_memory_error },
+   { /*ERROR_TOO_MANY_OPEN_FILES*/4L, out_of_resource_error },
+   { /*ERROR_INVALID_ADDRESS*/487L, busy_error }
+   #else    //#if (defined BOOST_INTERPROCESS_WINDOWS)
+   { EACCES, security_error },
+   { EROFS, read_only_error },
+   { EIO, io_error },
+   { ENAMETOOLONG, path_error },
+   { ENOENT, not_found_error },
+   //    { ENOTDIR, not_directory_error },
+   { EAGAIN, busy_error },
+   { EBUSY, busy_error },
+   { ETXTBSY, busy_error },
+   { EEXIST, already_exists_error },
+   { ENOTEMPTY, not_empty_error },
+   { EISDIR, is_directory_error },
+   { ENOSPC, out_of_space_error },
+   { ENOMEM, out_of_memory_error },
+   { EMFILE, out_of_resource_error },
+   { ENOENT, not_such_file_or_directory },
+   { EINVAL, invalid_argument }
+   #endif   //#if (defined BOOST_INTERPROCESS_WINDOWS)
+};
+
+inline error_code_t lookup_error(native_error_t err)
+{
+   const ec_xlate *cur  = &ec_table[0],
+                  *end  = cur + sizeof(ec_table)/sizeof(ec_xlate);
+   for  (;cur != end; ++cur ){
+      if ( err == cur->sys_ec ) return cur->ec;
+   }
+   return system_error; // general system error code
+}
+
+struct error_info
+{
+   error_info(error_code_t ec = other_error )
+      :  m_nat(0), m_ec(ec)
+   {}
+
+   error_info(native_error_t sys_err_code)
+      :  m_nat(sys_err_code), m_ec(lookup_error(sys_err_code))
+   {}
+
+   error_info & operator =(error_code_t ec)
+   {
+      m_nat = 0;
+      m_ec = ec;
+      return *this;
+   }
+
+   error_info & operator =(native_error_t sys_err_code)
+   {
+      m_nat = sys_err_code;
+      m_ec = lookup_error(sys_err_code);
+      return *this;
+   }
+
+   native_error_t get_native_error()const
+   {  return m_nat;  }
+
+   error_code_t   get_error_code()const
+   {  return m_ec;  }
+
+   private:
+   native_error_t m_nat;
+   error_code_t   m_ec;
+};
+/// @endcond
+
+}  // namespace interprocess {
+}  // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_ERRORS_HPP

+ 150 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/exceptions.hpp

@@ -0,0 +1,150 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_EXCEPTIONS_HPP
+#define BOOST_INTERPROCESS_EXCEPTIONS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/errors.hpp>
+#include <stdexcept>
+#include <new>
+
+//!\file
+//!Describes exceptions thrown by interprocess classes
+
+namespace boost {
+
+namespace interprocess {
+
+//!This class is the base class of all exceptions
+//!thrown by boost::interprocess
+class interprocess_exception : public std::exception
+{
+   public:
+   interprocess_exception(const char *err/*error_code_t ec = other_error*/)
+      :  m_err(other_error)
+   {
+//      try   {  m_str = "boost::interprocess_exception::library_error"; }
+      try   {  m_str = err; }
+      catch (...) {}
+   }
+/*
+   interprocess_exception(native_error_t sys_err_code)
+      :  m_err(sys_err_code)
+   {
+      try   {  fill_system_message(m_err.get_native_error(), m_str); }
+      catch (...) {}
+   }*/
+
+   interprocess_exception(const error_info &err_info, const char *str = 0)
+      :  m_err(err_info)
+   {
+      try{
+         if(m_err.get_native_error() != 0){
+            fill_system_message(m_err.get_native_error(), m_str);
+         }
+         else if(str){
+            m_str = str;
+         }
+         else{
+            m_str = "boost::interprocess_exception::library_error";
+         }
+      }
+      catch(...){}
+   }
+
+   virtual ~interprocess_exception() throw(){}
+
+   virtual const char * what() const throw()
+   {  return m_str.c_str();  }
+
+   native_error_t get_native_error()const { return m_err.get_native_error(); }
+
+   // Note: a value of other_error implies a library (rather than system) error
+   error_code_t   get_error_code()  const { return m_err.get_error_code(); }
+
+   /// @cond
+   private:
+   error_info        m_err;
+   std::string       m_str;
+   /// @endcond
+};
+
+//!This is the exception thrown by shared interprocess_mutex family when a deadlock situation
+//!is detected or when using a interprocess_condition the interprocess_mutex is not locked
+class lock_exception : public interprocess_exception
+{
+   public:
+   lock_exception()
+      :  interprocess_exception(lock_error)
+   {}
+
+   virtual const char* what() const throw()
+   {  return "boost::interprocess::lock_exception";  }
+};
+
+//!This is the exception thrown by named interprocess_semaphore when a deadlock situation
+//!is detected or when an error is detected in the post/wait operation
+/*
+class sem_exception : public interprocess_exception
+{
+   public:
+   sem_exception()
+      :  interprocess_exception(lock_error)
+   {}
+
+   virtual const char* what() const throw()
+   {  return "boost::interprocess::sem_exception";  }
+};
+*/
+//!This is the exception thrown by synchronization objects when there is
+//!an error in a wait() function
+/*
+class wait_exception : public interprocess_exception
+{
+   public:
+   virtual const char* what() const throw()
+   {  return "boost::interprocess::wait_exception";  }
+};
+*/
+
+//!This exception is thrown when a named object is created
+//!in "open_only" mode and the resource was not already created
+/*
+class not_previously_created : public interprocess_exception
+{
+ public:
+    virtual const char* what() const throw()
+      {  return "boost::interprocess::not_previously_created";  }
+};
+*/
+
+//!This exception is thrown when a memory request can't be
+//!fulfilled.
+class bad_alloc : public interprocess_exception
+{
+ public:
+   bad_alloc() : interprocess_exception("::boost::interprocess::bad_alloc"){}
+   virtual const char* what() const throw()
+      {  return "boost::interprocess::bad_alloc";  }
+};
+
+}  // namespace interprocess {
+
+}  // namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // BOOST_INTERPROCESS_EXCEPTIONS_HPP

+ 184 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/file_mapping.hpp

@@ -0,0 +1,184 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_FILE_MAPPING_HPP
+#define BOOST_INTERPROCESS_FILE_MAPPING_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/move/move.hpp>
+#include <string>    //std::string
+
+//!\file
+//!Describes file_mapping and mapped region classes
+
+namespace boost {
+namespace interprocess {
+
+//!A class that wraps a file-mapping that can be used to
+//!create mapped regions from the mapped files
+class file_mapping
+{
+   /// @cond
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(file_mapping)
+   /// @endcond
+
+   public:
+   //!Constructs an empty file mapping.
+   //!Does not throw
+   file_mapping();
+
+   //!Opens a file mapping of file "filename", starting in offset
+   //!"file_offset", and the mapping's size will be "size". The mapping
+   //!can be opened for read-only "read_only" or read-write "read_write"
+   //!modes. Throws interprocess_exception on error.
+   file_mapping(const char *filename, mode_t mode);
+
+   //!Moves the ownership of "moved"'s file mapping object to *this.
+   //!After the call, "moved" does not represent any file mapping object.
+   //!Does not throw
+   file_mapping(BOOST_RV_REF(file_mapping) moved)
+      :  m_handle(file_handle_t(ipcdetail::invalid_file()))
+   {  this->swap(moved);   }
+
+   //!Moves the ownership of "moved"'s file mapping to *this.
+   //!After the call, "moved" does not represent any file mapping.
+   //!Does not throw
+   file_mapping &operator=(BOOST_RV_REF(file_mapping) moved)
+   {
+      file_mapping tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Swaps to file_mappings.
+   //!Does not throw.
+   void swap(file_mapping &other);
+
+   //!Returns access mode
+   //!used in the constructor
+   mode_t get_mode() const;
+
+   //!Obtains the mapping handle
+   //!to be used with mapped_region
+   mapping_handle_t get_mapping_handle() const;
+
+   //!Destroys the file mapping. All mapped regions created from this are still
+   //!valid. Does not throw
+   ~file_mapping();
+
+   //!Returns the name of the file
+   //!used in the constructor.
+   const char *get_name() const;
+
+   //!Removes the file named "filename" even if it's been memory mapped.
+   //!Returns true on success.
+   //!The function might fail in some operating systems if the file is
+   //!being used other processes and no deletion permission was shared.
+   static bool remove(const char *filename);
+
+   /// @cond
+   private:
+   //!Closes a previously opened file mapping. Never throws.
+   void priv_close();
+   file_handle_t  m_handle;
+   mode_t    m_mode;
+   std::string       m_filename;
+   /// @endcond
+};
+
+inline file_mapping::file_mapping()
+   :  m_handle(file_handle_t(ipcdetail::invalid_file()))
+{}
+
+inline file_mapping::~file_mapping()
+{  this->priv_close(); }
+
+inline const char *file_mapping::get_name() const
+{  return m_filename.c_str(); }
+
+inline void file_mapping::swap(file_mapping &other)
+{
+   std::swap(m_handle, other.m_handle);
+   std::swap(m_mode, other.m_mode);
+   m_filename.swap(other.m_filename);
+}
+
+inline mapping_handle_t file_mapping::get_mapping_handle() const
+{  return ipcdetail::mapping_handle_from_file_handle(m_handle);  }
+
+inline mode_t file_mapping::get_mode() const
+{  return m_mode; }
+
+inline file_mapping::file_mapping
+   (const char *filename, mode_t mode)
+   :  m_filename(filename)
+{
+   //Check accesses
+   if (mode != read_write && mode != read_only){
+      error_info err = other_error;
+      throw interprocess_exception(err);
+   }
+
+   //Open file
+   m_handle = ipcdetail::open_existing_file(filename, mode);
+
+   //Check for error
+   if(m_handle == ipcdetail::invalid_file()){
+      error_info err = system_error_code();
+      this->priv_close();
+      throw interprocess_exception(err);
+   }
+   m_mode = mode;
+}
+
+inline bool file_mapping::remove(const char *filename)
+{  return ipcdetail::delete_file(filename);  }
+
+///@cond
+
+inline void file_mapping::priv_close()
+{
+   if(m_handle != ipcdetail::invalid_file()){
+      ipcdetail::close_file(m_handle);
+      m_handle = ipcdetail::invalid_file();
+   }
+}
+
+///@endcond
+
+//!A class that stores the name of a file
+//!and tries to remove it in its destructor
+//!Useful to remove temporary files in the presence
+//!of exceptions
+class remove_file_on_destroy
+{
+   const char * m_name;
+   public:
+   remove_file_on_destroy(const char *name)
+      :  m_name(name)
+   {}
+
+   ~remove_file_on_destroy()
+   {  ipcdetail::delete_file(m_name);  }
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_FILE_MAPPING_HPP

+ 78 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/indexes/flat_map_index.hpp

@@ -0,0 +1,78 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP
+#define BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <functional>
+#include <utility>
+#include <boost/interprocess/containers/flat_map.hpp>
+#include <boost/interprocess/allocators/allocator.hpp>
+
+//!\file
+//!Describes index adaptor of boost::map container, to use it
+//!as name/shared memory index
+
+//[flat_map_index
+namespace boost { namespace interprocess {
+
+//!Helper class to define typedefs from IndexTraits
+template <class MapConfig>
+struct flat_map_index_aux
+{
+   typedef typename MapConfig::key_type            key_type;
+   typedef typename MapConfig::mapped_type         mapped_type;
+   typedef typename MapConfig::
+      segment_manager_base                   segment_manager_base;
+   typedef std::less<key_type>                     key_less;
+   typedef std::pair<key_type, mapped_type>        value_type;
+   typedef allocator<value_type
+                    ,segment_manager_base>   allocator_type;
+   typedef flat_map<key_type,  mapped_type,
+                    key_less, allocator_type>      index_t;
+};
+
+//!Index type based in flat_map. Just derives from flat_map and
+//!defines the interface needed by managed memory segments.
+template <class MapConfig>
+class flat_map_index
+   //Derive class from flat_map specialization
+   : public flat_map_index_aux<MapConfig>::index_t
+{
+   /// @cond
+   typedef flat_map_index_aux<MapConfig>  index_aux;
+   typedef typename index_aux::index_t    base_type;
+   typedef typename index_aux::
+      segment_manager_base          segment_manager_base;
+   /// @endcond
+
+   public:
+   //!Constructor. Takes a pointer to the segment manager. Can throw
+   flat_map_index(segment_manager_base *segment_mngr)
+      : base_type(typename index_aux::key_less(),
+                  typename index_aux::allocator_type(segment_mngr))
+   {}
+
+   //!This reserves memory to optimize the insertion of n elements in the index
+   void reserve(typename segment_manager_base::size_type n)
+   {  base_type::reserve(n);  }
+
+   //!This frees all unnecessary memory
+   void shrink_to_fit()
+   {  base_type::shrink_to_fit();   }
+};
+
+}}   //namespace boost { namespace interprocess
+//]
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP

+ 150 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/indexes/iset_index.hpp

@@ -0,0 +1,150 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP
+#define BOOST_INTERPROCESS_ISET_INDEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <string>
+#include <functional>
+#include <utility>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/intrusive/set.hpp>
+
+
+//!\file
+//!Describes index adaptor of boost::intrusive::set container, to use it
+//!as name/shared memory index
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+//!Helper class to define typedefs from IndexTraits
+template <class MapConfig>
+struct iset_index_aux
+{
+   typedef typename
+      MapConfig::segment_manager_base                          segment_manager_base;
+
+   typedef typename
+      segment_manager_base::void_pointer                       void_pointer;
+   typedef typename bi::make_set_base_hook
+      < bi::void_pointer<void_pointer>
+      , bi::optimize_size<true>
+      >::type                                                  derivation_hook;
+
+   typedef typename MapConfig::template
+      intrusive_value_type<derivation_hook>::type              value_type;
+   typedef std::less<value_type>                               value_compare;
+   typedef typename bi::make_set
+      < value_type
+      , bi::base_hook<derivation_hook>
+      >::type                                                  index_t;
+};
+/// @endcond
+
+//!Index type based in boost::intrusive::set.
+//!Just derives from boost::intrusive::set
+//!and defines the interface needed by managed memory segments*/
+template <class MapConfig>
+class iset_index
+   //Derive class from map specialization
+   :  public iset_index_aux<MapConfig>::index_t
+{
+   /// @cond
+   typedef iset_index_aux<MapConfig>                     index_aux;
+   typedef typename index_aux::index_t                   index_type;
+   typedef typename MapConfig::
+      intrusive_compare_key_type                         intrusive_compare_key_type;
+   typedef typename MapConfig::char_type                 char_type;
+   /// @endcond
+
+   public:
+   typedef typename index_type::iterator                 iterator;
+   typedef typename index_type::const_iterator           const_iterator;
+   typedef typename index_type::insert_commit_data       insert_commit_data;
+   typedef typename index_type::value_type               value_type;
+
+   /// @cond
+   private:
+
+   struct intrusive_key_value_less
+   {
+      bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
+      {
+         std::size_t blen = b.name_length();
+         return (i.m_len < blen) ||
+                  (i.m_len == blen &&
+                  std::char_traits<char_type>::compare
+                     (i.mp_str, b.name(), i.m_len) < 0);
+      }
+
+      bool operator()(const value_type &b, const intrusive_compare_key_type &i) const
+      {
+         std::size_t blen = b.name_length();
+         return (blen < i.m_len) ||
+                  (blen == i.m_len &&
+                  std::char_traits<char_type>::compare
+                     (b.name(), i.mp_str, i.m_len) < 0);
+      }
+   };
+
+   /// @endcond
+
+   public:
+
+   //!Constructor. Takes a pointer to the
+   //!segment manager. Can throw
+   iset_index(typename MapConfig::segment_manager_base *)
+      : index_type(/*typename index_aux::value_compare()*/)
+   {}
+
+   //!This reserves memory to optimize the insertion of n
+   //!elements in the index
+   void reserve(typename MapConfig::segment_manager_base::size_type)
+   {  /*Does nothing, map has not reserve or rehash*/  }
+
+   //!This frees all unnecessary memory
+   void shrink_to_fit()
+   {  /*Does nothing, this intrusive index does not allocate memory;*/   }
+
+   iterator find(const intrusive_compare_key_type &key)
+   {  return index_type::find(key, intrusive_key_value_less());  }
+
+   const_iterator find(const intrusive_compare_key_type &key) const
+   {  return index_type::find(key, intrusive_key_value_less());  }
+
+   std::pair<iterator, bool>insert_check
+      (const intrusive_compare_key_type &key, insert_commit_data &commit_data)
+   {  return index_type::insert_check(key, intrusive_key_value_less(), commit_data); }
+};
+
+/// @cond
+
+//!Trait class to detect if an index is an intrusive
+//!index.
+template<class MapConfig>
+struct is_intrusive_index
+   <boost::interprocess::iset_index<MapConfig> >
+{
+   static const bool value = true;
+};
+/// @endcond
+
+}  //namespace interprocess {
+}  //namespace boost
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP

+ 368 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/indexes/iunordered_set_index.hpp

@@ -0,0 +1,368 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP
+#define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <functional>
+#include <utility>
+
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/containers/vector.hpp>
+#include <boost/intrusive/unordered_set.hpp>
+#include <boost/interprocess/allocators/allocator.hpp>
+
+//!\file
+//!Describes index adaptor of boost::intrusive::unordered_set container, to use it
+//!as name/shared memory index
+
+namespace boost { namespace interprocess {
+
+/// @cond
+
+//!Helper class to define typedefs
+//!from IndexTraits
+template <class MapConfig>
+struct iunordered_set_index_aux
+{
+   typedef typename
+      MapConfig::segment_manager_base                 segment_manager_base;
+
+   typedef typename
+      segment_manager_base::void_pointer              void_pointer;
+
+   typedef typename bi::make_unordered_set_base_hook
+      < bi::void_pointer<void_pointer>
+      >::type        derivation_hook;
+
+   typedef typename MapConfig::template
+      intrusive_value_type<derivation_hook>::type     value_type;
+
+   typedef typename MapConfig::
+      intrusive_compare_key_type                      intrusive_compare_key_type;
+
+   typedef std::equal_to<value_type>                  value_equal;
+
+   typedef typename MapConfig::char_type              char_type;
+
+   struct equal_function
+   {
+      bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
+      {
+         return (i.m_len == b.name_length()) &&
+                  (std::char_traits<char_type>::compare
+                     (i.mp_str, b.name(), i.m_len) == 0);
+      }
+
+      bool operator()(const value_type &b, const intrusive_compare_key_type &i) const
+      {
+         return (i.m_len == b.name_length()) &&
+                  (std::char_traits<char_type>::compare
+                     (i.mp_str, b.name(), i.m_len) == 0);
+      }
+
+      bool operator()(const value_type &b1, const value_type &b2) const
+      {
+         return (b1.name_length() == b2.name_length()) &&
+                  (std::char_traits<char_type>::compare
+                     (b1.name(), b2.name(), b1.name_length()) == 0);
+      }
+   };
+
+    struct hash_function
+      : std::unary_function<value_type, std::size_t>
+    {
+        std::size_t operator()(const value_type &val) const
+        {
+            const char_type *beg = ipcdetail::to_raw_pointer(val.name()),
+                            *end = beg + val.name_length();
+            return boost::hash_range(beg, end);
+        }
+
+        std::size_t operator()(const intrusive_compare_key_type &i) const
+        {
+            const char_type *beg = i.mp_str,
+                            *end = beg + i.m_len;
+            return boost::hash_range(beg, end);
+        }
+    };
+
+   typedef typename bi::make_unordered_set
+      < value_type
+      , bi::hash<hash_function>
+      , bi::equal<equal_function>
+     , bi::size_type<typename segment_manager_base::size_type>
+      >::type                                         index_t;
+   typedef typename index_t::bucket_type              bucket_type;
+   typedef allocator
+      <bucket_type, segment_manager_base>             allocator_type;
+
+   struct allocator_holder
+   {
+      allocator_holder(segment_manager_base *mngr)
+         :  alloc(mngr)
+      {}
+      allocator_type alloc;
+      bucket_type init_bucket;
+   };
+};
+/// @endcond
+
+//!Index type based in boost::intrusive::set.
+//!Just derives from boost::intrusive::set
+//!and defines the interface needed by managed memory segments
+template <class MapConfig>
+class iunordered_set_index
+      //Derive class from map specialization
+   :  private iunordered_set_index_aux<MapConfig>::allocator_holder
+   ,  public iunordered_set_index_aux<MapConfig>::index_t
+{
+   /// @cond
+   typedef iunordered_set_index_aux<MapConfig>           index_aux;
+   typedef typename index_aux::index_t                   index_type;
+   typedef typename MapConfig::
+      intrusive_compare_key_type                         intrusive_compare_key_type;
+   typedef typename index_aux::equal_function            equal_function;
+   typedef typename index_aux::hash_function             hash_function;
+   typedef typename MapConfig::char_type                 char_type;
+   typedef typename
+      iunordered_set_index_aux<MapConfig>::allocator_type      allocator_type;
+   typedef typename
+      iunordered_set_index_aux<MapConfig>::allocator_holder    allocator_holder;
+   /// @endcond
+
+   public:
+   typedef typename index_type::iterator                 iterator;
+   typedef typename index_type::const_iterator           const_iterator;
+   typedef typename index_type::insert_commit_data       insert_commit_data;
+   typedef typename index_type::value_type               value_type;
+   typedef typename index_type::bucket_ptr               bucket_ptr;
+   typedef typename index_type::bucket_type              bucket_type;
+   typedef typename index_type::bucket_traits            bucket_traits;
+   typedef typename index_type::size_type                size_type;
+
+   /// @cond
+   private:
+   typedef typename index_aux::
+      segment_manager_base             segment_manager_base;
+
+   static const std::size_t InitBufferSize = 64;
+
+   static bucket_ptr create_buckets(allocator_type &alloc, size_type num)
+   {
+      num = index_type::suggested_upper_bucket_count(num);
+      bucket_ptr buckets = alloc.allocate(num);
+      bucket_ptr buckets_init = buckets;
+      for(size_type i = 0; i < num; ++i){
+         new(to_raw_pointer(buckets_init++))bucket_type();
+      }
+      return buckets;
+   }
+
+   static size_type shrink_buckets
+      ( bucket_ptr buckets, size_type old_size
+      , allocator_type &alloc, size_type new_size)
+   {
+      if(old_size <= new_size )
+         return old_size;
+      size_type received_size;
+      if(!alloc.allocation_command
+         (boost::interprocess::try_shrink_in_place | boost::interprocess::nothrow_allocation, old_size, new_size, received_size, buckets).first){
+         return old_size;
+      }
+
+      for( bucket_type *p = ipcdetail::to_raw_pointer(buckets) + received_size
+         , *pend = ipcdetail::to_raw_pointer(buckets) + old_size
+         ; p != pend
+         ; ++p){
+         p->~bucket_type();
+      }
+
+      bucket_ptr shunk_p = alloc.allocation_command
+         (boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, received_size, buckets).first;
+      BOOST_ASSERT(buckets == shunk_p); (void)shunk_p;
+
+      bucket_ptr buckets_init = buckets + received_size;
+      for(size_type i = 0; i < (old_size - received_size); ++i){
+         to_raw_pointer(buckets_init++)->~bucket_type();
+      }
+      return received_size;
+   }
+
+   static bucket_ptr expand_or_create_buckets
+      ( bucket_ptr old_buckets, const size_type old_num
+      , allocator_type &alloc,  const size_type new_num)
+   {
+      size_type received_size;
+      std::pair<bucket_ptr, bool> ret =
+         alloc.allocation_command
+            (boost::interprocess::expand_fwd | boost::interprocess::allocate_new, new_num, new_num, received_size, old_buckets);
+      if(ret.first == old_buckets){
+         bucket_ptr buckets_init = old_buckets + old_num;
+         for(size_type i = 0; i < (new_num - old_num); ++i){
+            new(to_raw_pointer(buckets_init++))bucket_type();
+         }
+      }
+      else{
+         bucket_ptr buckets_init = ret.first;
+         for(size_type i = 0; i < new_num; ++i){
+            new(to_raw_pointer(buckets_init++))bucket_type();
+         }
+      }
+
+      return ret.first;
+   }
+
+   static void destroy_buckets
+      (allocator_type &alloc, bucket_ptr buckets, size_type num)
+   {
+      bucket_ptr buckets_destroy = buckets;
+      for(size_type i = 0; i < num; ++i){
+         to_raw_pointer(buckets_destroy++)->~bucket_type();
+      }
+      alloc.deallocate(buckets, num);
+   }
+
+   iunordered_set_index<MapConfig>* get_this_pointer()
+   {  return this;   }
+
+   /// @endcond
+
+   public:
+   //!Constructor. Takes a pointer to the
+   //!segment manager. Can throw
+   iunordered_set_index(segment_manager_base *mngr)
+      :  allocator_holder(mngr)
+      ,  index_type(bucket_traits(&get_this_pointer()->init_bucket, 1))
+   {}
+
+   ~iunordered_set_index()
+   {
+      index_type::clear();
+      if(index_type::bucket_pointer() != bucket_ptr(&this->init_bucket)){
+         destroy_buckets(this->alloc, index_type::bucket_pointer(), index_type::bucket_count());
+      }
+   }
+
+   //!This reserves memory to optimize the insertion of n
+   //!elements in the index
+   void reserve(size_type new_n)
+   {
+      //Let's maintain a 1.0f load factor
+      size_type old_n  = this->bucket_count();
+      if(new_n <= old_n)
+         return;
+      bucket_ptr old_p = this->bucket_pointer();
+      new_n = index_type::suggested_upper_bucket_count(new_n);
+      bucket_ptr new_p;
+      //This can throw
+      try{
+         if(old_p != bucket_ptr(&this->init_bucket))
+            new_p = expand_or_create_buckets(old_p, old_n, this->alloc, new_n);
+         else
+            new_p = create_buckets(this->alloc, new_n);
+      }
+      catch(...){
+         return;
+      }
+      //Rehashing does not throw, since neither the hash nor the
+      //comparison function can throw
+      this->rehash(bucket_traits(new_p, new_n));
+      if(new_p != old_p && old_p != bucket_ptr(&this->init_bucket)){
+         destroy_buckets(this->alloc, old_p, old_n);
+      }
+   }
+
+   //!This tries to free unused memory
+   //!previously allocated.
+   void shrink_to_fit()
+   {
+      size_type cur_size   = this->size();
+      size_type cur_count  = this->bucket_count();
+      bucket_ptr old_p = this->bucket_pointer();
+
+      if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){
+         this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1));
+         destroy_buckets(this->alloc, old_p, cur_count);
+      }
+      else{
+         size_type sug_count = 0; //gcc warning
+         sug_count = index_type::suggested_upper_bucket_count(cur_size);
+
+         if(sug_count >= cur_count)
+            return;
+
+         try{
+            shrink_buckets(old_p, cur_count, this->alloc, sug_count);
+         }
+         catch(...){
+            return;
+         }
+
+         //Rehashing does not throw, since neither the hash nor the
+         //comparison function can throw
+         this->rehash(bucket_traits(old_p, sug_count));
+      }
+   }
+
+   iterator find(const intrusive_compare_key_type &key)
+   {  return index_type::find(key, hash_function(), equal_function());  }
+
+   const_iterator find(const intrusive_compare_key_type &key) const
+   {  return index_type::find(key, hash_function(), equal_function());  }
+
+   std::pair<iterator, bool>insert_check
+      (const intrusive_compare_key_type &key, insert_commit_data &commit_data)
+   {  return index_type::insert_check(key, hash_function(), equal_function(), commit_data); }
+
+   iterator insert_commit(value_type &val, insert_commit_data &commit_data)
+   {
+      iterator it = index_type::insert_commit(val, commit_data);
+      size_type cur_size      = this->size();
+      if(cur_size > this->bucket_count()){
+         try{
+            this->reserve(cur_size);
+         }
+         catch(...){
+            //Strong guarantee: if something goes wrong
+            //we should remove the insertion.
+            //
+            //We can use the iterator because the hash function
+            //can't throw and this means that "reserve" will
+            //throw only because of the memory allocation:
+            //the iterator has not been invalidated.
+            index_type::erase(it);
+            throw;
+         }
+      }
+      return it;
+   }
+};
+
+/// @cond
+
+//!Trait class to detect if an index is an intrusive
+//!index
+template<class MapConfig>
+struct is_intrusive_index
+   <boost::interprocess::iunordered_set_index<MapConfig> >
+{
+   static const bool value = true;
+};
+/// @endcond
+
+}}   //namespace boost { namespace interprocess {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP

+ 100 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/indexes/map_index.hpp

@@ -0,0 +1,100 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP
+#define BOOST_INTERPROCESS_MAP_INDEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <functional>
+#include <utility>
+#include <boost/interprocess/containers/map.hpp>
+#include <boost/interprocess/allocators/private_adaptive_pool.hpp>
+
+//!\file
+//!Describes index adaptor of boost::map container, to use it
+//!as name/shared memory index
+
+namespace boost {
+namespace interprocess {
+namespace ipcdetail{
+
+//!Helper class to define typedefs from IndexTraits
+template <class MapConfig>
+struct map_index_aux
+{
+   typedef typename MapConfig::key_type            key_type;
+   typedef typename MapConfig::mapped_type         mapped_type;
+   typedef std::less<key_type>                     key_less;
+   typedef std::pair<const key_type, mapped_type>  value_type;
+
+   typedef private_adaptive_pool
+            <value_type,
+               typename MapConfig::
+         segment_manager_base>                     allocator_type;
+
+   typedef boost::interprocess::map
+      <key_type,  mapped_type,
+       key_less, allocator_type>                   index_t;
+};
+
+}  //namespace ipcdetail {
+
+//!Index type based in boost::interprocess::map. Just derives from boost::interprocess::map
+//!and defines the interface needed by managed memory segments
+template <class MapConfig>
+class map_index
+   //Derive class from map specialization
+   : public ipcdetail::map_index_aux<MapConfig>::index_t
+{
+   /// @cond
+   typedef ipcdetail::map_index_aux<MapConfig>  index_aux;
+   typedef typename index_aux::index_t       base_type;
+   typedef typename MapConfig::
+      segment_manager_base          segment_manager_base;
+   /// @endcond
+
+   public:
+   //!Constructor. Takes a pointer to the
+   //!segment manager. Can throw
+   map_index(segment_manager_base *segment_mngr)
+      : base_type(typename index_aux::key_less(),
+                  segment_mngr){}
+
+   //!This reserves memory to optimize the insertion of n
+   //!elements in the index
+   void reserve(typename segment_manager_base::size_type)
+      {  /*Does nothing, map has not reserve or rehash*/  }
+
+   //!This tries to free previously allocate
+   //!unused memory.
+   void shrink_to_fit()
+   {  base_type::get_stored_allocator().deallocate_free_blocks(); }
+};
+
+/// @cond
+
+//!Trait class to detect if an index is a node
+//!index. This allows more efficient operations
+//!when deallocating named objects.
+template<class MapConfig>
+struct is_node_index
+   <boost::interprocess::map_index<MapConfig> >
+{
+   static const bool value = true;
+};
+/// @endcond
+
+}}   //namespace boost { namespace interprocess {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP

+ 68 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/indexes/null_index.hpp

@@ -0,0 +1,68 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP
+#define BOOST_INTERPROCESS_NULL_INDEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/offset_ptr.hpp>
+
+//!\file
+//!Describes a null index adaptor, so that if we don't want to construct
+//!named objects, we can use this null index type to save resources.
+
+namespace boost {
+namespace interprocess {
+
+//!Null index type
+//!used to save compilation time when
+//!named indexes are not needed.
+template <class MapConfig>
+class null_index
+{
+   /// @cond
+   typedef typename MapConfig::
+      segment_manager_base    segment_manager_base;
+   /// @endcond
+
+   public:
+   typedef void * iterator;
+   typedef const void * const_iterator;
+
+   //!begin() is equal
+   //!to end()
+   const_iterator begin() const
+   {  return const_iterator(0);  }
+
+   //!begin() is equal
+   //!to end()
+   iterator begin()
+   {  return iterator(0);  }
+
+   //!begin() is equal
+   //!to end()
+   const_iterator end() const
+   {  return const_iterator(0);  }
+
+   //!begin() is equal
+   //!to end()
+   iterator end()
+   {  return iterator(0);  }
+
+   //!Empty constructor
+   null_index(segment_manager_base *){}
+};
+
+}}   //namespace boost { namespace interprocess {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP

+ 113 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/indexes/unordered_map_index.hpp

@@ -0,0 +1,113 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP
+#define BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <functional>
+#include <utility>
+#include <boost/unordered_map.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/allocators/private_adaptive_pool.hpp>
+
+//!\file
+//!Describes index adaptor of boost::unordered_map container, to use it
+//!as name/shared memory index
+
+namespace boost {
+namespace interprocess {
+
+///@cond
+
+//!Helper class to define typedefs from
+//!IndexTraits
+template <class MapConfig>
+struct unordered_map_index_aux
+{
+   typedef typename MapConfig::key_type            key_type;
+   typedef typename MapConfig::mapped_type         mapped_type;
+   typedef std::equal_to<key_type>                 key_equal;
+   typedef std::pair<const key_type, mapped_type>  value_type;
+   typedef private_adaptive_pool
+            <value_type,
+               typename MapConfig::
+                  segment_manager_base>      allocator_type;
+    struct hasher
+      : std::unary_function<key_type, std::size_t>
+    {
+        std::size_t operator()(const key_type &val) const
+        {
+            typedef typename key_type::char_type    char_type;
+            const char_type *beg = ipcdetail::to_raw_pointer(val.mp_str),
+                            *end = beg + val.m_len;
+            return boost::hash_range(beg, end);
+        }
+    };
+   typedef unordered_map<key_type,  mapped_type, hasher,
+                         key_equal, allocator_type>      index_t;
+};
+
+///@endcond
+
+//!Index type based in unordered_map. Just derives from unordered_map and
+//!defines the interface needed by managed memory segments
+template <class MapConfig>
+class unordered_map_index
+   //Derive class from unordered_map specialization
+   : public unordered_map_index_aux<MapConfig>::index_t
+{
+   /// @cond
+   typedef unordered_map_index_aux<MapConfig>   index_aux;
+   typedef typename index_aux::index_t          base_type;
+   typedef typename
+      MapConfig::segment_manager_base     segment_manager_base;
+   /// @endcond
+
+   public:
+   //!Constructor. Takes a pointer to the
+   //!segment manager. Can throw
+   unordered_map_index(segment_manager_base *segment_mngr)
+      : base_type(0,
+                  typename index_aux::hasher(),
+                  typename index_aux::key_equal(),
+                  segment_mngr){}
+
+   //!This reserves memory to optimize the insertion of n
+   //!elements in the index
+   void reserve(typename segment_manager_base::size_type n)
+   {  base_type::rehash(n);  }
+
+   //!This tries to free previously allocate
+   //!unused memory.
+   void shrink_to_fit()
+   {  base_type::rehash(base_type::size()); }
+};
+
+/// @cond
+
+//!Trait class to detect if an index is a node
+//!index. This allows more efficient operations
+//!when deallocating named objects.
+template<class MapConfig>
+struct is_node_index
+   <boost::interprocess::unordered_map_index<MapConfig> >
+{
+   static const bool value = true;
+};
+/// @endcond
+
+}}   //namespace boost { namespace interprocess {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP

+ 418 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/interprocess_fwd.hpp

@@ -0,0 +1,418 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_FWD_HPP
+#define BOOST_INTERPROCESS_FWD_HPP
+
+#if defined (_MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <cstddef>
+
+//////////////////////////////////////////////////////////////////////////////
+//                        Standard predeclarations
+//////////////////////////////////////////////////////////////////////////////
+
+/// @cond
+
+namespace boost{
+namespace intrusive{
+}}
+
+namespace boost{
+namespace interprocess{
+namespace bi = boost::intrusive;
+}}
+
+#include <utility>
+#include <memory>
+#include <functional>
+#include <iosfwd>
+#include <string>
+
+/// @endcond
+
+namespace boost { namespace interprocess {
+
+//////////////////////////////////////////////////////////////////////////////
+//                            permissions
+//////////////////////////////////////////////////////////////////////////////
+
+class permissions;
+
+//////////////////////////////////////////////////////////////////////////////
+//                            shared_memory
+//////////////////////////////////////////////////////////////////////////////
+
+class shared_memory_object;
+
+#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+class windows_shared_memory;
+#endif   //#if defined (BOOST_INTERPROCESS_WINDOWS)
+
+//////////////////////////////////////////////////////////////////////////////
+//              mapped file/mapped region/mapped_file
+//////////////////////////////////////////////////////////////////////////////
+
+class file_mapping;
+class mapped_region;
+class mapped_file;
+
+//////////////////////////////////////////////////////////////////////////////
+//                               Mutexes
+//////////////////////////////////////////////////////////////////////////////
+
+class null_mutex;
+
+class interprocess_mutex;
+class interprocess_recursive_mutex;
+
+class named_mutex;
+class named_recursive_mutex;
+
+class interprocess_semaphore;
+class named_semaphore;
+
+//////////////////////////////////////////////////////////////////////////////
+//                         Mutex families
+//////////////////////////////////////////////////////////////////////////////
+
+struct mutex_family;
+struct null_mutex_family;
+
+//////////////////////////////////////////////////////////////////////////////
+//                   Other synchronization classes
+//////////////////////////////////////////////////////////////////////////////
+
+class barrier;
+class interprocess_sharable_mutex;
+class interprocess_condition;
+
+//////////////////////////////////////////////////////////////////////////////
+//                              Locks
+//////////////////////////////////////////////////////////////////////////////
+
+template <class Mutex>
+class scoped_lock;
+
+template <class SharableMutex>
+class sharable_lock;
+
+template <class UpgradableMutex>
+class upgradable_lock;
+
+//////////////////////////////////////////////////////////////////////////////
+//                      STL compatible allocators
+//////////////////////////////////////////////////////////////////////////////
+
+template<class T, class SegmentManager>
+class allocator;
+
+template<class T, class SegmentManager, std::size_t NodesPerBlock = 64>
+class node_allocator;
+
+template<class T, class SegmentManager, std::size_t NodesPerBlock = 64>
+class private_node_allocator;
+
+template<class T, class SegmentManager, std::size_t NodesPerBlock = 64>
+class cached_node_allocator;
+
+template<class T, class SegmentManager, std::size_t NodesPerBlock = 64, std::size_t MaxFreeBlocks = 2
+         , unsigned char OverheadPercent = 5
+>
+class adaptive_pool;
+
+template<class T, class SegmentManager, std::size_t NodesPerBlock = 64, std::size_t MaxFreeBlocks = 2
+         , unsigned char OverheadPercent = 5
+>
+class private_adaptive_pool;
+
+template<class T, class SegmentManager, std::size_t NodesPerBlock = 64, std::size_t MaxFreeBlocks = 2
+         , unsigned char OverheadPercent = 5
+>
+class cached_adaptive_pool;
+
+
+//////////////////////////////////////////////////////////////////////////////
+//                            offset_ptr
+//////////////////////////////////////////////////////////////////////////////
+
+static const std::size_t offset_type_alignment = 0;
+
+template <class T, class DifferenceType = std::ptrdiff_t, class OffsetType = std::size_t, std::size_t Alignment = offset_type_alignment>
+class offset_ptr;
+
+//////////////////////////////////////////////////////////////////////////////
+//                    Memory allocation algorithms
+//////////////////////////////////////////////////////////////////////////////
+
+//Single segment memory allocation algorithms
+template<class MutexFamily, class VoidMutex = offset_ptr<void> >
+class simple_seq_fit;
+
+template<class MutexFamily, class VoidMutex = offset_ptr<void>, std::size_t MemAlignment = 0>
+class rbtree_best_fit;
+
+//////////////////////////////////////////////////////////////////////////////
+//                         Index Types
+//////////////////////////////////////////////////////////////////////////////
+
+template<class IndexConfig> class flat_map_index;
+template<class IndexConfig> class iset_index;
+template<class IndexConfig> class iunordered_set_index;
+template<class IndexConfig> class map_index;
+template<class IndexConfig> class null_index;
+template<class IndexConfig> class unordered_map_index;
+
+//////////////////////////////////////////////////////////////////////////////
+//                         Segment manager
+//////////////////////////////////////////////////////////////////////////////
+
+template <class CharType
+         ,class MemoryAlgorithm
+         ,template<class IndexConfig> class IndexType>
+class segment_manager;
+
+//////////////////////////////////////////////////////////////////////////////
+//                  External buffer managed memory classes
+//////////////////////////////////////////////////////////////////////////////
+
+template <class CharType
+         ,class MemoryAlgorithm
+         ,template<class IndexConfig> class IndexType>
+class basic_managed_external_buffer;
+
+typedef basic_managed_external_buffer
+   <char
+   ,rbtree_best_fit<null_mutex_family>
+   ,iset_index>
+managed_external_buffer;
+
+typedef basic_managed_external_buffer
+   <wchar_t
+   ,rbtree_best_fit<null_mutex_family>
+   ,iset_index>
+wmanaged_external_buffer;
+
+//////////////////////////////////////////////////////////////////////////////
+//                      managed memory classes
+//////////////////////////////////////////////////////////////////////////////
+
+template <class CharType
+         ,class MemoryAlgorithm
+         ,template<class IndexConfig> class IndexType>
+class basic_managed_shared_memory;
+
+typedef basic_managed_shared_memory
+   <char
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+managed_shared_memory;
+
+typedef basic_managed_shared_memory
+   <wchar_t
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+wmanaged_shared_memory;
+
+
+//////////////////////////////////////////////////////////////////////////////
+//                      Windows shared memory managed memory classes
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined (BOOST_INTERPROCESS_WINDOWS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+template <class CharType
+         ,class MemoryAlgorithm
+         ,template<class IndexConfig> class IndexType>
+class basic_managed_windows_shared_memory;
+
+typedef basic_managed_windows_shared_memory
+   <char
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+managed_windows_shared_memory;
+
+typedef basic_managed_windows_shared_memory
+   <wchar_t
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+wmanaged_windows_shared_memory;
+
+#endif   //#if defined (BOOST_INTERPROCESS_WINDOWS)
+
+#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+template <class CharType
+         ,class MemoryAlgorithm
+         ,template<class IndexConfig> class IndexType>
+class basic_managed_xsi_shared_memory;
+
+typedef basic_managed_xsi_shared_memory
+   <char
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+managed_xsi_shared_memory;
+
+typedef basic_managed_xsi_shared_memory
+   <wchar_t
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+wmanaged_xsi_shared_memory;
+
+#endif //#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
+
+//////////////////////////////////////////////////////////////////////////////
+//                      Fixed address shared memory
+//////////////////////////////////////////////////////////////////////////////
+
+typedef basic_managed_shared_memory
+   <char
+   ,rbtree_best_fit<mutex_family, void*>
+   ,iset_index>
+fixed_managed_shared_memory;
+
+typedef basic_managed_shared_memory
+   <wchar_t
+   ,rbtree_best_fit<mutex_family, void*>
+   ,iset_index>
+wfixed_managed_shared_memory;
+
+//////////////////////////////////////////////////////////////////////////////
+//                      Heap memory managed memory classes
+//////////////////////////////////////////////////////////////////////////////
+
+template
+   <class CharType
+   ,class MemoryAlgorithm
+   ,template<class IndexConfig> class IndexType>
+class basic_managed_heap_memory;
+
+typedef basic_managed_heap_memory
+   <char
+   ,rbtree_best_fit<null_mutex_family>
+   ,iset_index>
+managed_heap_memory;
+
+typedef basic_managed_heap_memory
+   <wchar_t
+   ,rbtree_best_fit<null_mutex_family>
+   ,iset_index>
+wmanaged_heap_memory;
+
+//////////////////////////////////////////////////////////////////////////////
+//                         Mapped file managed memory classes
+//////////////////////////////////////////////////////////////////////////////
+
+template
+   <class CharType
+   ,class MemoryAlgorithm
+   ,template<class IndexConfig> class IndexType>
+class basic_managed_mapped_file;
+
+typedef basic_managed_mapped_file
+   <char
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+managed_mapped_file;
+
+typedef basic_managed_mapped_file
+   <wchar_t
+   ,rbtree_best_fit<mutex_family>
+   ,iset_index>
+wmanaged_mapped_file;
+
+//////////////////////////////////////////////////////////////////////////////
+//                            Exceptions
+//////////////////////////////////////////////////////////////////////////////
+
+class interprocess_exception;
+class lock_exception;
+class bad_alloc;
+
+//////////////////////////////////////////////////////////////////////////////
+//                            Bufferstream
+//////////////////////////////////////////////////////////////////////////////
+
+//bufferstream
+template <class CharT
+         ,class CharTraits = std::char_traits<CharT> >
+class basic_bufferbuf;
+
+template <class CharT
+         ,class CharTraits = std::char_traits<CharT> >
+class basic_ibufferstream;
+
+template <class CharT
+         ,class CharTraits = std::char_traits<CharT> >
+class basic_obufferstream;
+
+template <class CharT
+         ,class CharTraits = std::char_traits<CharT> >
+class basic_bufferstream;
+
+//////////////////////////////////////////////////////////////////////////////
+//                            Vectorstream
+//////////////////////////////////////////////////////////////////////////////
+
+template <class CharVector
+         ,class CharTraits = std::char_traits<typename CharVector::value_type> >
+class basic_vectorbuf;
+
+template <class CharVector
+         ,class CharTraits = std::char_traits<typename CharVector::value_type> >
+class basic_ivectorstream;
+
+template <class CharVector
+         ,class CharTraits = std::char_traits<typename CharVector::value_type> >
+class basic_ovectorstream;
+
+template <class CharVector
+         ,class CharTraits = std::char_traits<typename CharVector::value_type> >
+class basic_vectorstream;
+
+//////////////////////////////////////////////////////////////////////////////
+//                             Smart pointers
+//////////////////////////////////////////////////////////////////////////////
+
+template<class T, class Deleter>
+class scoped_ptr;
+
+template<class T, class VoidPointer>
+class intrusive_ptr;
+
+template<class T, class VoidAllocator, class Deleter>
+class shared_ptr;
+
+template<class T, class VoidAllocator, class Deleter>
+class weak_ptr;
+
+//////////////////////////////////////////////////////////////////////////////
+//                                  IPC
+//////////////////////////////////////////////////////////////////////////////
+
+template<class VoidPointer>
+class message_queue_t;
+
+typedef message_queue_t<offset_ptr<void> > message_queue;
+
+}}  //namespace boost { namespace interprocess {
+
+//////////////////////////////////////////////////////////////////////////////
+//                                  CONTAINERS
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_FWD_HPP

+ 900 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/ipc/message_queue.hpp

@@ -0,0 +1,900 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
+#define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/sync/interprocess_condition.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/offset_ptr.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <algorithm> //std::lower_bound
+#include <cstddef>   //std::size_t
+#include <cstring>   //memcpy
+
+
+//!\file
+//!Describes an inter-process message queue. This class allows sending
+//!messages between processes and allows blocking, non-blocking and timed
+//!sending and receiving.
+
+namespace boost{  namespace interprocess{
+
+//!A class that allows sending messages
+//!between processes.
+template<class VoidPointer>
+class message_queue_t
+{
+   /// @cond
+   //Blocking modes
+   enum block_t   {  blocking,   timed,   non_blocking   };
+
+   message_queue_t();
+   /// @endcond
+
+   public:
+   typedef VoidPointer                                                 void_pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<char>::type                                    char_ptr;
+   typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type;
+   typedef typename boost::make_unsigned<difference_type>::type        size_type;
+
+   //!Creates a process shared message queue with name "name". For this message queue,
+   //!the maximum number of messages will be "max_num_msg" and the maximum message size
+   //!will be "max_msg_size". Throws on error and if the queue was previously created.
+   message_queue_t(create_only_t create_only,
+                 const char *name,
+                 size_type max_num_msg,
+                 size_type max_msg_size,
+                 const permissions &perm = permissions());
+
+   //!Opens or creates a process shared message queue with name "name".
+   //!If the queue is created, the maximum number of messages will be "max_num_msg"
+   //!and the maximum message size will be "max_msg_size". If queue was previously
+   //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters
+   //!are ignored. Throws on error.
+   message_queue_t(open_or_create_t open_or_create,
+                 const char *name,
+                 size_type max_num_msg,
+                 size_type max_msg_size,
+                 const permissions &perm = permissions());
+
+   //!Opens a previously created process shared message queue with name "name".
+   //!If the queue was not previously created or there are no free resources,
+   //!throws an error.
+   message_queue_t(open_only_t open_only,
+                 const char *name);
+
+   //!Destroys *this and indicates that the calling process is finished using
+   //!the resource. All opened message queues are still
+   //!valid after destruction. The destructor function will deallocate
+   //!any system resources allocated by the system for use by this process for
+   //!this resource. The resource can still be opened again calling
+   //!the open constructor overload. To erase the message queue from the system
+   //!use remove().
+   ~message_queue_t();
+
+   //!Sends a message stored in buffer "buffer" with size "buffer_size" in the
+   //!message queue with priority "priority". If the message queue is full
+   //!the sender is blocked. Throws interprocess_error on error.
+   void send (const void *buffer,     size_type buffer_size,
+              unsigned int priority);
+
+   //!Sends a message stored in buffer "buffer" with size "buffer_size" through the
+   //!message queue with priority "priority". If the message queue is full
+   //!the sender is not blocked and returns false, otherwise returns true.
+   //!Throws interprocess_error on error.
+   bool try_send    (const void *buffer,     size_type buffer_size,
+                         unsigned int priority);
+
+   //!Sends a message stored in buffer "buffer" with size "buffer_size" in the
+   //!message queue with priority "priority". If the message queue is full
+   //!the sender retries until time "abs_time" is reached. Returns true if
+   //!the message has been successfully sent. Returns false if timeout is reached.
+   //!Throws interprocess_error on error.
+   bool timed_send    (const void *buffer,     size_type buffer_size,
+                           unsigned int priority,  const boost::posix_time::ptime& abs_time);
+
+   //!Receives a message from the message queue. The message is stored in buffer
+   //!"buffer", which has size "buffer_size". The received message has size
+   //!"recvd_size" and priority "priority". If the message queue is empty
+   //!the receiver is blocked. Throws interprocess_error on error.
+   void receive (void *buffer,           size_type buffer_size,
+                 size_type &recvd_size,unsigned int &priority);
+
+   //!Receives a message from the message queue. The message is stored in buffer
+   //!"buffer", which has size "buffer_size". The received message has size
+   //!"recvd_size" and priority "priority". If the message queue is empty
+   //!the receiver is not blocked and returns false, otherwise returns true.
+   //!Throws interprocess_error on error.
+   bool try_receive (void *buffer,           size_type buffer_size,
+                     size_type &recvd_size,unsigned int &priority);
+
+   //!Receives a message from the message queue. The message is stored in buffer
+   //!"buffer", which has size "buffer_size". The received message has size
+   //!"recvd_size" and priority "priority". If the message queue is empty
+   //!the receiver retries until time "abs_time" is reached. Returns true if
+   //!the message has been successfully sent. Returns false if timeout is reached.
+   //!Throws interprocess_error on error.
+   bool timed_receive (void *buffer,           size_type buffer_size,
+                       size_type &recvd_size,unsigned int &priority,
+                       const boost::posix_time::ptime &abs_time);
+
+   //!Returns the maximum number of messages allowed by the queue. The message
+   //!queue must be opened or created previously. Otherwise, returns 0.
+   //!Never throws
+   size_type get_max_msg() const;
+
+   //!Returns the maximum size of message allowed by the queue. The message
+   //!queue must be opened or created previously. Otherwise, returns 0.
+   //!Never throws
+   size_type get_max_msg_size() const;
+
+   //!Returns the number of messages currently stored.
+   //!Never throws
+   size_type get_num_msg();
+
+   //!Removes the message queue from the system.
+   //!Returns false on error. Never throws
+   static bool remove(const char *name);
+
+   /// @cond
+   private:
+   typedef boost::posix_time::ptime ptime;
+   bool do_receive(block_t block,
+                   void *buffer,         size_type buffer_size,
+                   size_type &recvd_size, unsigned int &priority,
+                   const ptime &abs_time);
+
+   bool do_send(block_t block,
+                const void *buffer,      size_type buffer_size,
+                unsigned int priority,   const ptime &abs_time);
+
+   //!Returns the needed memory size for the shared message queue.
+   //!Never throws
+   static size_type get_mem_size(size_type max_msg_size, size_type max_num_msg);
+
+   ipcdetail::managed_open_or_create_impl<shared_memory_object> m_shmem;
+   /// @endcond
+};
+
+/// @cond
+
+namespace ipcdetail {
+
+//!This header is the prefix of each message in the queue
+template<class VoidPointer>
+class msg_hdr_t
+{
+   typedef VoidPointer                                                           void_pointer;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<char>::type                                              char_ptr;
+   typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type  difference_type;
+   typedef typename boost::make_unsigned<difference_type>::type                  size_type;
+
+   public:
+   size_type               len;     // Message length
+   unsigned int            priority;// Message priority
+   //!Returns the data buffer associated with this this message
+   void * data(){ return this+1; }  //
+};
+
+//!This functor is the predicate to order stored messages by priority
+template<class VoidPointer>
+class priority_functor
+{
+   typedef typename boost::intrusive::
+      pointer_traits<VoidPointer>::template
+         rebind_pointer<msg_hdr_t<VoidPointer> >::type                  msg_hdr_ptr_t;
+
+   public:
+   bool operator()(const msg_hdr_ptr_t &msg1,
+                   const msg_hdr_ptr_t &msg2) const
+      {  return msg1->priority < msg2->priority;  }
+};
+
+//!This header is placed in the beginning of the shared memory and contains
+//!the data to control the queue. This class initializes the shared memory
+//!in the following way: in ascending memory address with proper alignment
+//!fillings:
+//!
+//!-> mq_hdr_t:
+//!   Main control block that controls the rest of the elements
+//!
+//!-> offset_ptr<msg_hdr_t> index [max_num_msg]
+//!   An array of pointers with size "max_num_msg" called index. Each pointer
+//!   points to a preallocated message. Elements of this array are
+//!   reordered in runtime in the following way:
+//!
+//!   IF BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is defined:
+//!
+//!   When the current number of messages is "cur_num_msg", the array
+//!   is treated like a circular buffer. Starting from position "cur_first_msg"
+//!   "cur_num_msg" in a circular way, pointers point to inserted messages and the rest
+//!   point to free messages. Those "cur_num_msg" pointers are
+//!   ordered by the priority of the pointed message and by insertion order
+//!   if two messages have the same priority. So the next message to be
+//!   used in a "receive" is pointed by index [(cur_first_msg + cur_num_msg-1)%max_num_msg]
+//!   and the first free message ready to be used in a "send" operation is
+//!   [cur_first_msg] if circular buffer is extended from front, 
+//!   [(cur_first_msg + cur_num_msg)%max_num_msg] otherwise.
+//!
+//!   This transforms the index in a circular buffer with an embedded free
+//!   message queue.
+//!
+//!   ELSE (BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is NOT defined):
+//!
+//!   When the current number of messages is "cur_num_msg", the first
+//!   "cur_num_msg" pointers point to inserted messages and the rest
+//!   point to free messages. The first "cur_num_msg" pointers are
+//!   ordered by the priority of the pointed message and by insertion order
+//!   if two messages have the same priority. So the next message to be
+//!   used in a "receive" is pointed by index [cur_num_msg-1] and the first free
+//!   message ready to be used in a "send" operation is index [cur_num_msg].
+//!
+//!   This transforms the index in a fixed size priority queue with an embedded free
+//!   message queue.
+//!
+//!-> struct message_t
+//!   {
+//!      msg_hdr_t            header;
+//!      char[max_msg_size]   data;
+//!   } messages [max_num_msg];
+//!
+//!   An array of buffers of preallocated messages, each one prefixed with the
+//!   msg_hdr_t structure. Each of this message is pointed by one pointer of
+//!   the index structure.
+template<class VoidPointer>
+class mq_hdr_t
+   : public ipcdetail::priority_functor<VoidPointer>
+{
+   typedef VoidPointer                                                     void_pointer;
+   typedef msg_hdr_t<void_pointer>                                         msg_header;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<msg_header>::type                                  msg_hdr_ptr_t;
+   typedef typename boost::intrusive::pointer_traits
+      <msg_hdr_ptr_t>::difference_type                                     difference_type;
+   typedef typename boost::make_unsigned<difference_type>::type            size_type;
+   typedef typename boost::intrusive::
+      pointer_traits<void_pointer>::template
+         rebind_pointer<msg_hdr_ptr_t>::type                              msg_hdr_ptr_ptr_t;
+
+   public:
+   //!Constructor. This object must be constructed in the beginning of the
+   //!shared memory of the size returned by the function "get_mem_size".
+   //!This constructor initializes the needed resources and creates
+   //!the internal structures like the priority index. This can throw.
+   mq_hdr_t(size_type max_num_msg, size_type max_msg_size)
+      : m_max_num_msg(max_num_msg),
+         m_max_msg_size(max_msg_size),
+         m_cur_num_msg(0)
+         #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+         ,m_cur_first_msg(0u)
+         #endif
+      {  this->initialize_memory();  }
+
+   //!Returns true if the message queue is full
+   bool is_full() const
+      {  return m_cur_num_msg == m_max_num_msg;  }
+
+   //!Returns true if the message queue is empty
+   bool is_empty() const
+      {  return !m_cur_num_msg;  }
+
+   //!Frees the top priority message and saves it in the free message list
+   void free_top_msg()
+      {  --m_cur_num_msg;  }
+
+   #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+
+   typedef msg_hdr_ptr_t *iterator;
+
+   size_type end_pos() const
+   {
+      const size_type space_until_bufend = m_max_num_msg - m_cur_first_msg;
+      return space_until_bufend > m_cur_num_msg
+         ? m_cur_first_msg + m_cur_num_msg : m_cur_num_msg - space_until_bufend;
+   }
+
+   //!Returns the inserted message with top priority
+   msg_header &top_msg()
+   {
+      size_type pos = this->end_pos();
+      return *mp_index[pos ? --pos : m_max_num_msg - 1];
+   }
+
+   //!Returns the inserted message with bottom priority
+   msg_header &bottom_msg()
+      {  return *mp_index[m_cur_first_msg];   }
+
+   iterator inserted_ptr_begin() const
+   {  return &mp_index[m_cur_first_msg]; }
+
+   iterator inserted_ptr_end() const
+      {  return &mp_index[this->end_pos()];  }
+
+   iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func)
+   {
+      iterator begin(this->inserted_ptr_begin()), end(this->inserted_ptr_end());
+      if(end < begin){
+         iterator idx_end = &mp_index[m_max_num_msg];
+         iterator ret = std::lower_bound(begin, idx_end, value, func); 
+         if(idx_end == ret){
+            iterator idx_beg = &mp_index[0];
+            ret = std::lower_bound(idx_beg, end, value, func);
+            //sanity check, these cases should not call lower_bound (optimized out)
+            assert(ret != end);
+            assert(ret != begin);
+            return ret;
+         }
+         else{
+            return ret;
+         }
+      }
+      else{
+         return std::lower_bound(begin, end, value, func);
+      }
+   }
+
+   msg_header & insert_at(iterator where)
+   {
+      iterator inserted_ptr_end = this->inserted_ptr_end();
+      iterator inserted_ptr_beg = this->inserted_ptr_begin();
+      if(where == inserted_ptr_end){
+         ++m_cur_num_msg;
+         return **inserted_ptr_end;
+      }
+      else if(where == inserted_ptr_beg){
+         //unsigned integer guarantees underflow
+         m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg;
+         --m_cur_first_msg;
+         ++m_cur_num_msg;
+         return *mp_index[m_cur_first_msg];
+      }
+      else{
+         size_type pos  = where - &mp_index[0];
+         size_type circ_pos = pos >= m_cur_first_msg ? pos - m_cur_first_msg : pos + (m_max_num_msg - m_cur_first_msg);
+         //Check if it's more efficient to move back or move front
+         if(circ_pos < m_cur_num_msg/2){
+            //The queue can't be full so m_cur_num_msg == 0 or m_cur_num_msg <= pos
+            //indicates two step insertion
+            if(!pos){
+               pos   = m_max_num_msg;
+               where = &mp_index[m_max_num_msg-1];
+            }
+            else{
+               --where;
+            }
+            const bool unique_segment = m_cur_first_msg && m_cur_first_msg <= pos;
+            size_type first_segment_beg  = unique_segment ? m_cur_first_msg : 1u;
+            size_type first_segment_end  = pos;
+            size_type second_segment_beg = unique_segment || !m_cur_first_msg ? m_max_num_msg : m_cur_first_msg;
+            size_type second_segment_end = m_max_num_msg;
+            const msg_hdr_ptr_t backup   = *(&mp_index[0] + (unique_segment ?  first_segment_beg : second_segment_beg) - 1);
+
+            //First segment
+            if(!unique_segment){
+               std::copy( &mp_index[0] + second_segment_beg
+                        , &mp_index[0] + second_segment_end
+                        , &mp_index[0] + second_segment_beg - 1);
+               mp_index[m_max_num_msg-1] = mp_index[0];
+            }
+            std::copy( &mp_index[0] + first_segment_beg
+                     , &mp_index[0] + first_segment_end
+                     , &mp_index[0] + first_segment_beg - 1);
+            *where = backup;
+            m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg;
+            --m_cur_first_msg;
+            ++m_cur_num_msg;
+            return **where;
+         }
+         else{
+            //The queue can't be full so end_pos < m_cur_first_msg
+            //indicates two step insertion
+            const size_type end_pos = this->end_pos();
+            const bool unique_segment = pos < end_pos;
+            size_type first_segment_beg  = pos;
+            size_type first_segment_end  = unique_segment  ? end_pos : m_max_num_msg-1;
+            size_type second_segment_beg = 0u;
+            size_type second_segment_end = unique_segment ? 0u : end_pos;
+            const msg_hdr_ptr_t backup   = *inserted_ptr_end;
+
+            //First segment
+            if(!unique_segment){
+               std::copy_backward( &mp_index[0] + second_segment_beg
+                                 , &mp_index[0] + second_segment_end
+                                 , &mp_index[0] + second_segment_end + 1);
+               mp_index[0] = mp_index[m_max_num_msg-1];
+            }
+            std::copy_backward( &mp_index[0] + first_segment_beg
+                              , &mp_index[0] + first_segment_end
+                              , &mp_index[0] + first_segment_end + 1);
+            *where = backup;
+            ++m_cur_num_msg;
+            return **where;
+         }
+      }
+   }
+
+   #else
+
+   typedef msg_hdr_ptr_t *iterator;
+
+   //!Returns the inserted message with top priority
+   msg_header &top_msg()
+      {  return *mp_index[m_cur_num_msg-1];   }
+
+   //!Returns the inserted message with bottom priority
+   msg_header &bottom_msg()
+      {  return *mp_index[0];   }
+
+   iterator inserted_ptr_begin() const
+   {  return &mp_index[0]; }
+
+   iterator inserted_ptr_end() const
+   {  return &mp_index[m_cur_num_msg]; }
+
+   iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor<VoidPointer> func)
+   {  return std::lower_bound(this->inserted_ptr_begin(), this->inserted_ptr_end(), value, func);  }
+
+   msg_header & insert_at(iterator pos)
+   {
+      const msg_hdr_ptr_t backup = *inserted_ptr_end();
+      std::copy_backward(pos, inserted_ptr_end(), inserted_ptr_end()+1);
+      *pos = backup;
+      ++m_cur_num_msg;
+      return **pos;
+   }
+
+   #endif
+
+   //!Inserts the first free message in the priority queue
+   msg_header & queue_free_msg(unsigned int priority)
+   {
+      //Get priority queue's range
+      iterator it  (inserted_ptr_begin()), it_end(inserted_ptr_end());
+      //Optimize for non-priority usage
+      if(m_cur_num_msg && priority > this->bottom_msg().priority){
+         //Check for higher priority than all stored messages
+         if(priority > this->top_msg().priority){
+            it = it_end;
+         }
+         else{
+            //Since we don't now which free message we will pick
+            //build a dummy header for searches
+            msg_header dummy_hdr;
+            dummy_hdr.priority = priority;
+
+            //Get free msg
+            msg_hdr_ptr_t dummy_ptr(&dummy_hdr);
+
+            //Check where the free message should be placed
+            it = this->lower_bound(dummy_ptr, static_cast<priority_functor<VoidPointer>&>(*this));
+         }
+         
+      }
+      //Insert the free message in the correct position
+      return this->insert_at(it);
+   }
+
+   //!Returns the number of bytes needed to construct a message queue with
+   //!"max_num_size" maximum number of messages and "max_msg_size" maximum
+   //!message size. Never throws.
+   static size_type get_mem_size
+      (size_type max_msg_size, size_type max_num_msg)
+   {
+      const size_type
+		 msg_hdr_align  = ::boost::alignment_of<msg_header>::value,
+		 index_align    = ::boost::alignment_of<msg_hdr_ptr_t>::value,
+         r_hdr_size     = ipcdetail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
+         r_index_size   = ipcdetail::get_rounded_size(max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align),
+         r_max_msg_size = ipcdetail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(msg_header);
+      return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) +
+         ipcdetail::managed_open_or_create_impl<shared_memory_object>::ManagedOpenOrCreateUserOffset;
+   }
+
+   //!Initializes the memory structures to preallocate messages and constructs the
+   //!message index. Never throws.
+   void initialize_memory()
+   {
+      const size_type
+		  msg_hdr_align  = ::boost::alignment_of<msg_header>::value,
+		  index_align    = ::boost::alignment_of<msg_hdr_ptr_t>::value,
+         r_hdr_size     = ipcdetail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
+         r_index_size   = ipcdetail::get_rounded_size(m_max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align),
+         r_max_msg_size = ipcdetail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(msg_header);
+
+      //Pointer to the index
+      msg_hdr_ptr_t *index =  reinterpret_cast<msg_hdr_ptr_t*>
+                                 (reinterpret_cast<char*>(this)+r_hdr_size);
+
+      //Pointer to the first message header
+      msg_header *msg_hdr   =  reinterpret_cast<msg_header*>
+                                 (reinterpret_cast<char*>(this)+r_hdr_size+r_index_size);
+
+      //Initialize the pointer to the index
+      mp_index             = index;
+
+      //Initialize the index so each slot points to a preallocated message
+      for(size_type i = 0; i < m_max_num_msg; ++i){
+         index[i] = msg_hdr;
+         msg_hdr  = reinterpret_cast<msg_header*>
+                        (reinterpret_cast<char*>(msg_hdr)+r_max_msg_size);
+      }
+   }
+
+   public:
+   //Pointer to the index
+   msg_hdr_ptr_ptr_t          mp_index;
+   //Maximum number of messages of the queue
+   const size_type            m_max_num_msg;
+   //Maximum size of messages of the queue
+   const size_type            m_max_msg_size;
+   //Current number of messages
+   size_type                  m_cur_num_msg;
+   //Mutex to protect data structures
+   interprocess_mutex         m_mutex;
+   //Condition block receivers when there are no messages
+   interprocess_condition     m_cond_recv;
+   //Condition block senders when the queue is full
+   interprocess_condition     m_cond_send;
+   #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
+   //Current start offset in the circular index
+   size_type                  m_cur_first_msg;
+   #endif
+};
+
+
+//!This is the atomic functor to be executed when creating or opening
+//!shared memory. Never throws
+template<class VoidPointer>
+class initialization_func_t
+{
+   public:
+   typedef typename boost::intrusive::
+      pointer_traits<VoidPointer>::template
+         rebind_pointer<char>::type                                    char_ptr;
+   typedef typename boost::intrusive::pointer_traits<char_ptr>::difference_type difference_type;
+   typedef typename boost::make_unsigned<difference_type>::type        size_type;
+
+   initialization_func_t(size_type maxmsg = 0,
+                         size_type maxmsgsize = 0)
+      : m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {}
+
+   bool operator()(void *address, size_type, bool created)
+   {
+      char      *mptr;
+
+      if(created){
+         mptr     = reinterpret_cast<char*>(address);
+         //Construct the message queue header at the beginning
+         BOOST_TRY{
+            new (mptr) mq_hdr_t<VoidPointer>(m_maxmsg, m_maxmsgsize);
+         }
+         BOOST_CATCH(...){
+            return false;
+         }
+         BOOST_CATCH_END
+      }
+      return true;
+   }
+   const size_type m_maxmsg;
+   const size_type m_maxmsgsize;
+};
+
+}  //namespace ipcdetail {
+
+template<class VoidPointer>
+inline message_queue_t<VoidPointer>::~message_queue_t()
+{}
+
+template<class VoidPointer>
+inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_mem_size
+   (size_type max_msg_size, size_type max_num_msg)
+{  return ipcdetail::mq_hdr_t<VoidPointer>::get_mem_size(max_msg_size, max_num_msg);   }
+
+template<class VoidPointer>
+inline message_queue_t<VoidPointer>::message_queue_t(create_only_t create_only,
+                                    const char *name,
+                                    size_type max_num_msg,
+                                    size_type max_msg_size,
+                                    const permissions &perm)
+      //Create shared memory and execute functor atomically
+   :  m_shmem(create_only,
+              name,
+              get_mem_size(max_msg_size, max_num_msg),
+              read_write,
+              static_cast<void*>(0),
+              //Prepare initialization functor
+              ipcdetail::initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
+              perm)
+{}
+
+template<class VoidPointer>
+inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t open_or_create,
+                                    const char *name,
+                                    size_type max_num_msg,
+                                    size_type max_msg_size,
+                                    const permissions &perm)
+      //Create shared memory and execute functor atomically
+   :  m_shmem(open_or_create,
+              name,
+              get_mem_size(max_msg_size, max_num_msg),
+              read_write,
+              static_cast<void*>(0),
+              //Prepare initialization functor
+              ipcdetail::initialization_func_t<VoidPointer> (max_num_msg, max_msg_size),
+              perm)
+{}
+
+template<class VoidPointer>
+inline message_queue_t<VoidPointer>::message_queue_t(open_only_t open_only,
+                                    const char *name)
+   //Create shared memory and execute functor atomically
+   :  m_shmem(open_only,
+              name,
+              read_write,
+              static_cast<void*>(0),
+              //Prepare initialization functor
+              ipcdetail::initialization_func_t<VoidPointer> ())
+{}
+
+template<class VoidPointer>
+inline void message_queue_t<VoidPointer>::send
+   (const void *buffer, size_type buffer_size, unsigned int priority)
+{  this->do_send(blocking, buffer, buffer_size, priority, ptime()); }
+
+template<class VoidPointer>
+inline bool message_queue_t<VoidPointer>::try_send
+   (const void *buffer, size_type buffer_size, unsigned int priority)
+{  return this->do_send(non_blocking, buffer, buffer_size, priority, ptime()); }
+
+template<class VoidPointer>
+inline bool message_queue_t<VoidPointer>::timed_send
+   (const void *buffer, size_type buffer_size
+   ,unsigned int priority, const boost::posix_time::ptime &abs_time)
+{
+   if(abs_time == boost::posix_time::pos_infin){
+      this->send(buffer, buffer_size, priority);
+      return true;
+   }
+   return this->do_send(timed, buffer, buffer_size, priority, abs_time);
+}
+
+template<class VoidPointer>
+inline bool message_queue_t<VoidPointer>::do_send(block_t block,
+                                const void *buffer,      size_type buffer_size,
+                                unsigned int priority,   const boost::posix_time::ptime &abs_time)
+{
+   ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
+   //Check if buffer is smaller than maximum allowed
+   if (buffer_size > p_hdr->m_max_msg_size) {
+      throw interprocess_exception(size_error);
+   }
+
+   bool was_empty = false;
+   //---------------------------------------------
+   scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
+   //---------------------------------------------
+   {
+      //If the queue is full execute blocking logic
+      if (p_hdr->is_full()) {
+         switch(block){
+            case non_blocking :
+               return false;
+            break;
+
+            case blocking :
+               do{
+                  p_hdr->m_cond_send.wait(lock);
+               }
+               while (p_hdr->is_full());
+            break;
+
+            case timed :
+               do{
+                  if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){
+                     if(p_hdr->is_full())
+                        return false;
+                     break;
+                  }
+               }
+               while (p_hdr->is_full());
+            break;
+            default:
+            break;
+         }
+      }
+
+      was_empty = p_hdr->is_empty();
+      //Insert the first free message in the priority queue
+      ipcdetail::msg_hdr_t<VoidPointer> &free_msg_hdr = p_hdr->queue_free_msg(priority);
+
+      //Sanity check, free msgs are always cleaned when received
+      assert(free_msg_hdr.priority == 0);
+      assert(free_msg_hdr.len == 0);
+
+      //Copy control data to the free message
+      free_msg_hdr.priority = priority;
+      free_msg_hdr.len      = buffer_size;
+
+      //Copy user buffer to the message
+      std::memcpy(free_msg_hdr.data(), buffer, buffer_size);
+   }  // Lock end
+
+   //Notify outside lock to avoid contention. This might produce some
+   //spurious wakeups, but it's usually far better than notifying inside.
+   //If this message changes the queue empty state, notify it to receivers
+   if (was_empty){
+      p_hdr->m_cond_recv.notify_one();
+   }
+
+   return true;
+}
+
+template<class VoidPointer>
+inline void message_queue_t<VoidPointer>::receive(void *buffer,        size_type buffer_size,
+                        size_type &recvd_size,   unsigned int &priority)
+{  this->do_receive(blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
+
+template<class VoidPointer>
+inline bool
+   message_queue_t<VoidPointer>::try_receive(void *buffer,              size_type buffer_size,
+                              size_type &recvd_size,   unsigned int &priority)
+{  return this->do_receive(non_blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
+
+template<class VoidPointer>
+inline bool
+   message_queue_t<VoidPointer>::timed_receive(void *buffer,            size_type buffer_size,
+                                size_type &recvd_size,   unsigned int &priority,
+                                const boost::posix_time::ptime &abs_time)
+{
+   if(abs_time == boost::posix_time::pos_infin){
+      this->receive(buffer, buffer_size, recvd_size, priority);
+      return true;
+   }
+   return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time);
+}
+
+template<class VoidPointer>
+inline bool
+   message_queue_t<VoidPointer>::do_receive(block_t block,
+                          void *buffer,            size_type buffer_size,
+                          size_type &recvd_size,   unsigned int &priority,
+                          const boost::posix_time::ptime &abs_time)
+{
+   ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
+   //Check if buffer is big enough for any message
+   if (buffer_size < p_hdr->m_max_msg_size) {
+      throw interprocess_exception(size_error);
+   }
+
+   bool was_full = false;
+   //---------------------------------------------
+   scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
+   //---------------------------------------------
+   {
+      //If there are no messages execute blocking logic
+      if (p_hdr->is_empty()) {
+         switch(block){
+            case non_blocking :
+               return false;
+            break;
+
+            case blocking :
+               do{
+                  p_hdr->m_cond_recv.wait(lock);
+               }
+               while (p_hdr->is_empty());
+            break;
+
+            case timed :
+               do{
+                  if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){
+                     if(p_hdr->is_empty())
+                        return false;
+                     break;
+                  }
+               }
+               while (p_hdr->is_empty());
+            break;
+
+            //Paranoia check
+            default:
+            break;
+         }
+      }
+
+      //There is at least one message ready to pick, get the top one
+      ipcdetail::msg_hdr_t<VoidPointer> &top_msg = p_hdr->top_msg();
+
+      //Get data from the message
+      recvd_size     = top_msg.len;
+      priority       = top_msg.priority;
+
+      //Some cleanup to ease debugging
+      top_msg.len       = 0;
+      top_msg.priority  = 0;
+
+      //Copy data to receiver's bufers
+      std::memcpy(buffer, top_msg.data(), recvd_size);
+
+      was_full = p_hdr->is_full();
+
+      //Free top message and put it in the free message list
+      p_hdr->free_top_msg();
+   }  //Lock end
+
+   //Notify outside lock to avoid contention. This might produce some
+   //spurious wakeups, but it's usually far better than notifying inside.
+   //If this reception changes the queue full state, notify senders
+   if (was_full){
+      p_hdr->m_cond_send.notify_one();
+   }
+
+   return true;
+}
+
+template<class VoidPointer>
+inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_max_msg() const
+{
+   ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
+   return p_hdr ? p_hdr->m_max_num_msg : 0;  }
+
+template<class VoidPointer>
+inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_max_msg_size() const
+{
+   ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
+   return p_hdr ? p_hdr->m_max_msg_size : 0;
+}
+
+template<class VoidPointer>
+inline typename message_queue_t<VoidPointer>::size_type message_queue_t<VoidPointer>::get_num_msg()
+{
+   ipcdetail::mq_hdr_t<VoidPointer> *p_hdr = static_cast<ipcdetail::mq_hdr_t<VoidPointer>*>(m_shmem.get_user_address());
+   if(p_hdr){
+      //---------------------------------------------
+      scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
+      //---------------------------------------------
+      return p_hdr->m_cur_num_msg;
+   }
+
+   return 0;
+}
+
+template<class VoidPointer>
+inline bool message_queue_t<VoidPointer>::remove(const char *name)
+{  return shared_memory_object::remove(name);  }
+
+/// @endcond
+
+}} //namespace boost{  namespace interprocess{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP

+ 113 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/managed_external_buffer.hpp

@@ -0,0 +1,113 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP
+#define BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/move/move.hpp>
+#include <boost/assert.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+#include <boost/interprocess/indexes/iset_index.hpp>
+
+//!\file
+//!Describes a named user memory allocation user class.
+
+namespace boost {
+namespace interprocess {
+
+//!A basic user memory named object creation class. Inherits all
+//!basic functionality from
+//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
+template
+      <
+         class CharType,
+         class AllocationAlgorithm,
+         template<class IndexConfig> class IndexType
+      >
+class basic_managed_external_buffer
+   : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType>
+{
+   /// @cond
+   typedef ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType>    base_t;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_external_buffer)
+   /// @endcond
+
+   public:
+   typedef typename base_t::size_type              size_type;
+
+   //!Default constructor. Does nothing.
+   //!Useful in combination with move semantics
+   basic_managed_external_buffer()
+   {}
+
+   //!Creates and places the segment manager. This can throw
+   basic_managed_external_buffer
+      (create_only_t, void *addr, size_type size)
+   {
+      //Check if alignment is correct
+      BOOST_ASSERT((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - size_type(1u)))));
+      if(!base_t::create_impl(addr, size)){
+         throw interprocess_exception("Could not initialize buffer in basic_managed_external_buffer constructor");
+      }
+   }
+
+   //!Creates and places the segment manager. This can throw
+   basic_managed_external_buffer
+      (open_only_t, void *addr, size_type size)
+   {
+      //Check if alignment is correct
+      BOOST_ASSERT((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - size_type(1u)))));
+      if(!base_t::open_impl(addr, size)){
+         throw interprocess_exception("Could not initialize buffer in basic_managed_external_buffer constructor");
+      }
+   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this. Does not throw
+   basic_managed_external_buffer(BOOST_RV_REF(basic_managed_external_buffer) moved)
+   {
+      this->swap(moved);
+   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this. Does not throw
+   basic_managed_external_buffer &operator=(BOOST_RV_REF(basic_managed_external_buffer) moved)
+   {
+      basic_managed_external_buffer tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   void grow(size_type extra_bytes)
+   {  base_t::grow(extra_bytes);   }
+
+   //!Swaps the ownership of the managed heap memories managed by *this and other.
+   //!Never throws.
+   void swap(basic_managed_external_buffer &other)
+   {  base_t::swap(other); }
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP
+

+ 148 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/managed_heap_memory.hpp

@@ -0,0 +1,148 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP
+#define BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/move/move.hpp>
+#include <vector>
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+#include <boost/interprocess/indexes/iset_index.hpp>
+
+//!\file
+//!Describes a named heap memory allocation user class.
+
+namespace boost {
+namespace interprocess {
+
+//!A basic heap memory named object creation class. Initializes the
+//!heap memory segment. Inherits all basic functionality from
+//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
+template
+      <
+         class CharType,
+         class AllocationAlgorithm,
+         template<class IndexConfig> class IndexType
+      >
+class basic_managed_heap_memory
+   : public ipcdetail::basic_managed_memory_impl <CharType, AllocationAlgorithm, IndexType>
+{
+   /// @cond
+   private:
+
+   typedef ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType>             base_t;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_heap_memory)
+   /// @endcond
+
+   public: //functions
+   typedef typename base_t::size_type              size_type;
+
+   //!Default constructor. Does nothing.
+   //!Useful in combination with move semantics
+   basic_managed_heap_memory(){}
+
+   //!Destructor. Liberates the heap memory holding the managed data.
+   //!Never throws.
+   ~basic_managed_heap_memory()
+   {  this->priv_close();  }
+
+   //!Creates heap memory and initializes the segment manager.
+   //!This can throw.
+   basic_managed_heap_memory(size_type size)
+      :  m_heapmem(size, char(0))
+   {
+      if(!base_t::create_impl(&m_heapmem[0], size)){
+         this->priv_close();
+         throw interprocess_exception("Could not initialize heap in basic_managed_heap_memory constructor");
+      }
+   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this. Does not throw
+   basic_managed_heap_memory(BOOST_RV_REF(basic_managed_heap_memory) moved)
+   {  this->swap(moved);   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this. Does not throw
+   basic_managed_heap_memory &operator=(BOOST_RV_REF(basic_managed_heap_memory) moved)
+   {
+      basic_managed_heap_memory tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Tries to resize internal heap memory so that
+   //!we have room for more objects.
+   //!WARNING: If memory is reallocated, all the objects will
+   //!be binary-copied to the new buffer. To be able to use
+   //!this function, all pointers constructed in this buffer
+   //!must be offset pointers. Otherwise, the result is undefined.
+   //!Returns true if the growth has been successful, so you will
+   //!have some extra bytes to allocate new objects. If returns
+   //!false, the heap allocation has failed.
+   bool grow(size_type extra_bytes)
+   {
+      //If memory is reallocated, data will
+      //be automatically copied
+      BOOST_TRY{
+        m_heapmem.resize(m_heapmem.size()+extra_bytes);
+      }
+      BOOST_CATCH(...){
+         return false;
+      }
+      BOOST_CATCH_END
+
+      //Grow always works
+      base_t::close_impl();
+      base_t::open_impl(&m_heapmem[0], m_heapmem.size());
+      base_t::grow(extra_bytes);
+      return true;
+   }
+
+   //!Swaps the ownership of the managed heap memories managed by *this and other.
+   //!Never throws.
+   void swap(basic_managed_heap_memory &other)
+   {
+      base_t::swap(other);
+      m_heapmem.swap(other.m_heapmem);
+   }
+
+   /// @cond
+   private:
+   //!Frees resources. Never throws.
+   void priv_close()
+   {
+      base_t::destroy_impl();
+      std::vector<char>().swap(m_heapmem);
+   }
+
+   std::vector<char>  m_heapmem;
+   /// @endcond
+};
+
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP
+

+ 217 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/managed_mapped_file.hpp

@@ -0,0 +1,217 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP
+#define BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/detail/file_wrapper.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/file_mapping.hpp>
+#include <boost/interprocess/permissions.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+#include <boost/interprocess/indexes/iset_index.hpp>
+
+namespace boost {
+namespace interprocess {
+
+//!A basic mapped file named object creation class. Initializes the
+//!mapped file. Inherits all basic functionality from
+//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>
+template
+      <
+         class CharType,
+         class AllocationAlgorithm,
+         template<class IndexConfig> class IndexType
+      >
+class basic_managed_mapped_file
+   : public ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType
+      ,ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper
+                                             , AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset
+      >
+{
+   /// @cond
+   public:
+   typedef ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType,
+      ipcdetail::managed_open_or_create_impl
+         <ipcdetail::file_wrapper, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset
+      >   base_t;
+   typedef ipcdetail::file_wrapper device_type;
+   typedef typename base_t::size_type              size_type;
+
+   private:
+
+   typedef ipcdetail::create_open_func<base_t>        create_open_func_t;
+   typedef ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper
+                                                 , AllocationAlgorithm::Alignment> managed_open_or_create_type;
+
+   basic_managed_mapped_file *get_this_pointer()
+   {  return this;   }
+
+   private:
+   typedef typename base_t::char_ptr_holder_t   char_ptr_holder_t;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_mapped_file)
+   /// @endcond
+
+   public: //functions
+
+   //!Creates mapped file and creates and places the segment manager.
+   //!This can throw.
+   basic_managed_mapped_file()
+   {}
+
+   //!Creates mapped file and creates and places the segment manager.
+   //!This can throw.
+   basic_managed_mapped_file(create_only_t create_only, const char *name,
+                             size_type size, const void *addr = 0, const permissions &perm = permissions())
+      : m_mfile(create_only, name, size, read_write, addr,
+                create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm)
+   {}
+
+   //!Creates mapped file and creates and places the segment manager if
+   //!segment was not created. If segment was created it connects to the
+   //!segment.
+   //!This can throw.
+   basic_managed_mapped_file (open_or_create_t open_or_create,
+                              const char *name, size_type size,
+                              const void *addr = 0, const permissions &perm = permissions())
+      : m_mfile(open_or_create, name, size, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpenOrCreate), perm)
+   {}
+
+   //!Connects to a created mapped file and its segment manager.
+   //!This can throw.
+   basic_managed_mapped_file (open_only_t open_only, const char* name,
+                              const void *addr = 0)
+      : m_mfile(open_only, name, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Connects to a created mapped file and its segment manager
+   //!in copy_on_write mode.
+   //!This can throw.
+   basic_managed_mapped_file (open_copy_on_write_t, const char* name,
+                              const void *addr = 0)
+      : m_mfile(open_only, name, copy_on_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Connects to a created mapped file and its segment manager
+   //!in read-only mode.
+   //!This can throw.
+   basic_managed_mapped_file (open_read_only_t, const char* name,
+                              const void *addr = 0)
+      : m_mfile(open_only, name, read_only, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_mapped_file(BOOST_RV_REF(basic_managed_mapped_file) moved)
+   {
+      this->swap(moved);
+   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_mapped_file &operator=(BOOST_RV_REF(basic_managed_mapped_file) moved)
+   {
+      basic_managed_mapped_file tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Destroys *this and indicates that the calling process is finished using
+   //!the resource. The destructor function will deallocate
+   //!any system resources allocated by the system for use by this process for
+   //!this resource. The resource can still be opened again calling
+   //!the open constructor overload. To erase the resource from the system
+   //!use remove().
+   ~basic_managed_mapped_file()
+   {}
+
+   //!Swaps the ownership of the managed mapped memories managed by *this and other.
+   //!Never throws.
+   void swap(basic_managed_mapped_file &other)
+   {
+      base_t::swap(other);
+      m_mfile.swap(other.m_mfile);
+   }
+
+   //!Flushes cached data to file.
+   //!Never throws
+   bool flush()
+   {  return m_mfile.flush();  }
+
+   //!Tries to resize mapped file so that we have room for
+   //!more objects.
+   //!
+   //!This function is not synchronized so no other thread or process should
+   //!be reading or writing the file
+   static bool grow(const char *filename, size_type extra_bytes)
+   {
+      return base_t::template grow
+         <basic_managed_mapped_file>(filename, extra_bytes);
+   }
+
+   //!Tries to resize mapped file to minimized the size of the file.
+   //!
+   //!This function is not synchronized so no other thread or process should
+   //!be reading or writing the file
+   static bool shrink_to_fit(const char *filename)
+   {
+      return base_t::template shrink_to_fit
+         <basic_managed_mapped_file>(filename);
+   }
+
+   /// @cond
+
+   //!Tries to find a previous named allocation address. Returns a memory
+   //!buffer and the object count. If not found returned pointer is 0.
+   //!Never throws.
+   template <class T>
+   std::pair<T*, size_type> find  (char_ptr_holder_t name)
+   {
+      if(m_mfile.get_mapped_region().get_mode() == read_only){
+         return base_t::template find_no_lock<T>(name);
+      }
+      else{
+         return base_t::template find<T>(name);
+      }
+   }
+
+   private:
+   managed_open_or_create_type m_mfile;
+   /// @endcond
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP

+ 215 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/managed_shared_memory.hpp

@@ -0,0 +1,215 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP
+#define BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/permissions.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+
+namespace boost {
+
+namespace interprocess {
+
+//!A basic shared memory named object creation class. Initializes the
+//!shared memory segment. Inherits all basic functionality from
+//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
+template
+      <
+         class CharType,
+         class AllocationAlgorithm,
+         template<class IndexConfig> class IndexType
+      >
+class basic_managed_shared_memory
+   : public ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType
+      ,ipcdetail::managed_open_or_create_impl<shared_memory_object
+                                             , AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset>
+   , private ipcdetail::managed_open_or_create_impl<shared_memory_object
+                                                   , AllocationAlgorithm::Alignment>
+{
+   /// @cond
+   typedef ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType,
+      ipcdetail::managed_open_or_create_impl
+         < shared_memory_object, AllocationAlgorithm::Alignment>::ManagedOpenOrCreateUserOffset>   base_t;
+   typedef ipcdetail::managed_open_or_create_impl
+      <shared_memory_object, AllocationAlgorithm::Alignment>                       base2_t;
+
+   typedef ipcdetail::create_open_func<base_t>        create_open_func_t;
+
+   basic_managed_shared_memory *get_this_pointer()
+   {  return this;   }
+
+   public:
+   typedef shared_memory_object                    device_type;
+   typedef typename base_t::size_type              size_type;
+
+   private:
+   typedef typename base_t::char_ptr_holder_t   char_ptr_holder_t;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_shared_memory)
+   /// @endcond
+
+   public: //functions
+
+   //!Destroys *this and indicates that the calling process is finished using
+   //!the resource. The destructor function will deallocate
+   //!any system resources allocated by the system for use by this process for
+   //!this resource. The resource can still be opened again calling
+   //!the open constructor overload. To erase the resource from the system
+   //!use remove().
+   ~basic_managed_shared_memory()
+   {}
+
+   //!Default constructor. Does nothing.
+   //!Useful in combination with move semantics
+   basic_managed_shared_memory()
+   {}
+
+   //!Creates shared memory and creates and places the segment manager.
+   //!This can throw.
+   basic_managed_shared_memory(create_only_t create_only, const char *name,
+                             size_type size, const void *addr = 0, const permissions& perm = permissions())
+      : base_t()
+      , base2_t(create_only, name, size, read_write, addr,
+                create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm)
+   {}
+
+   //!Creates shared memory and creates and places the segment manager if
+   //!segment was not created. If segment was created it connects to the
+   //!segment.
+   //!This can throw.
+   basic_managed_shared_memory (open_or_create_t open_or_create,
+                              const char *name, size_type size,
+                              const void *addr = 0, const permissions& perm = permissions())
+      : base_t()
+      , base2_t(open_or_create, name, size, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpenOrCreate), perm)
+   {}
+
+   //!Connects to a created shared memory and its segment manager.
+   //!in copy_on_write mode.
+   //!This can throw.
+   basic_managed_shared_memory (open_copy_on_write_t, const char* name,
+                                const void *addr = 0)
+      : base_t()
+      , base2_t(open_only, name, copy_on_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Connects to a created shared memory and its segment manager.
+   //!in read-only mode.
+   //!This can throw.
+   basic_managed_shared_memory (open_read_only_t, const char* name,
+                                const void *addr = 0)
+      : base_t()
+      , base2_t(open_only, name, read_only, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Connects to a created shared memory and its segment manager.
+   //!This can throw.
+   basic_managed_shared_memory (open_only_t open_only, const char* name,
+                                const void *addr = 0)
+      : base_t()
+      , base2_t(open_only, name, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_shared_memory(BOOST_RV_REF(basic_managed_shared_memory) moved)
+   {
+      basic_managed_shared_memory tmp;
+      this->swap(moved);
+      tmp.swap(moved);
+   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_shared_memory &operator=(BOOST_RV_REF(basic_managed_shared_memory) moved)
+   {
+      basic_managed_shared_memory tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Swaps the ownership of the managed shared memories managed by *this and other.
+   //!Never throws.
+   void swap(basic_managed_shared_memory &other)
+   {
+      base_t::swap(other);
+      base2_t::swap(other);
+   }
+
+   //!Tries to resize the managed shared memory object so that we have
+   //!room for more objects.
+   //!
+   //!This function is not synchronized so no other thread or process should
+   //!be reading or writing the file
+   static bool grow(const char *shmname, size_type extra_bytes)
+   {
+      return base_t::template grow
+         <basic_managed_shared_memory>(shmname, extra_bytes);
+   }
+
+   //!Tries to resize the managed shared memory to minimized the size of the file.
+   //!
+   //!This function is not synchronized so no other thread or process should
+   //!be reading or writing the file
+   static bool shrink_to_fit(const char *shmname)
+   {
+      return base_t::template shrink_to_fit
+         <basic_managed_shared_memory>(shmname);
+   }
+   /// @cond
+
+   //!Tries to find a previous named allocation address. Returns a memory
+   //!buffer and the object count. If not found returned pointer is 0.
+   //!Never throws.
+   template <class T>
+   std::pair<T*, size_type> find  (char_ptr_holder_t name)
+   {
+      if(base2_t::get_mapped_region().get_mode() == read_only){
+         return base_t::template find_no_lock<T>(name);
+      }
+      else{
+         return base_t::template find<T>(name);
+      }
+   }
+
+   /// @endcond
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP
+

+ 194 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/managed_windows_shared_memory.hpp

@@ -0,0 +1,194 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP
+#define BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+#include <boost/interprocess/windows_shared_memory.hpp>
+#include <boost/interprocess/permissions.hpp>
+#include <boost/move/move.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+#include <boost/interprocess/indexes/iset_index.hpp>
+
+namespace boost {
+namespace interprocess {
+
+//!A basic managed windows shared memory creation class. Initializes the
+//!shared memory segment. Inherits all basic functionality from
+//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>
+//!Unlike basic_managed_shared_memory, it has
+//!no kernel persistence and the shared memory is destroyed
+//!when all processes destroy all their windows_shared_memory
+//!objects and mapped regions for the same shared memory
+//!or the processes end/crash.
+//!
+//!Warning: basic_managed_windows_shared_memory and
+//!basic_managed_shared_memory can't communicate between them.
+template
+      <
+         class CharType,
+         class AllocationAlgorithm,
+         template<class IndexConfig> class IndexType
+      >
+class basic_managed_windows_shared_memory
+   : public ipcdetail::basic_managed_memory_impl
+      < CharType, AllocationAlgorithm, IndexType
+      , ipcdetail::managed_open_or_create_impl
+         < windows_shared_memory
+         , AllocationAlgorithm::Alignment
+         , false>::ManagedOpenOrCreateUserOffset
+      >
+{
+   /// @cond
+   private:
+   typedef ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType,
+      ipcdetail::managed_open_or_create_impl
+         <windows_shared_memory, AllocationAlgorithm::Alignment, false>::ManagedOpenOrCreateUserOffset>   base_t;
+   typedef ipcdetail::create_open_func<base_t>        create_open_func_t;
+
+   basic_managed_windows_shared_memory *get_this_pointer()
+   {  return this;   }
+
+   private:
+   typedef typename base_t::char_ptr_holder_t   char_ptr_holder_t;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_windows_shared_memory)
+   /// @endcond
+
+   public: //functions
+   typedef typename base_t::size_type              size_type;
+
+   //!Default constructor. Does nothing.
+   //!Useful in combination with move semantics
+   basic_managed_windows_shared_memory()
+   {}
+
+   //!Creates shared memory and creates and places the segment manager.
+   //!This can throw.
+   basic_managed_windows_shared_memory
+      (create_only_t create_only, const char *name,
+     size_type size, const void *addr = 0, const permissions &perm = permissions())
+      : m_wshm(create_only, name, size, read_write, addr,
+                create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm)
+   {}
+
+   //!Creates shared memory and creates and places the segment manager if
+   //!segment was not created. If segment was created it connects to the
+   //!segment.
+   //!This can throw.
+   basic_managed_windows_shared_memory
+      (open_or_create_t open_or_create,
+      const char *name, size_type size,
+      const void *addr = 0,
+      const permissions &perm = permissions())
+      : m_wshm(open_or_create, name, size, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpenOrCreate), perm)
+   {}
+
+   //!Connects to a created shared memory and its segment manager.
+   //!This can throw.
+   basic_managed_windows_shared_memory
+      (open_only_t open_only, const char* name, const void *addr = 0)
+      : m_wshm(open_only, name, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Connects to a created shared memory and its segment manager
+   //!in copy_on_write mode.
+   //!This can throw.
+   basic_managed_windows_shared_memory
+      (open_copy_on_write_t, const char* name, const void *addr = 0)
+      : m_wshm(open_only, name, copy_on_write, addr,
+                create_open_func_t(get_this_pointer(), ipcdetail::DoOpen))
+   {}
+
+   //!Connects to a created shared memory and its segment manager
+   //!in read-only mode.
+   //!This can throw.
+   basic_managed_windows_shared_memory
+      (open_read_only_t, const char* name, const void *addr = 0)
+      : base_t()
+      , m_wshm(open_only, name, read_only, addr,
+                create_open_func_t(get_this_pointer(), ipcdetail::DoOpen))
+   {}
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_windows_shared_memory
+      (BOOST_RV_REF(basic_managed_windows_shared_memory) moved)
+   {  this->swap(moved);   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_windows_shared_memory &operator=(BOOST_RV_REF(basic_managed_windows_shared_memory) moved)
+   {
+      basic_managed_windows_shared_memory tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Destroys *this and indicates that the calling process is finished using
+   //!the resource. All mapped regions are still valid after
+   //!destruction. When all mapped regions and basic_managed_windows_shared_memory
+   //!objects referring the shared memory are destroyed, the
+   //!operating system will destroy the shared memory.
+   ~basic_managed_windows_shared_memory()
+   {}
+
+   //!Swaps the ownership of the managed mapped memories managed by *this and other.
+   //!Never throws.
+   void swap(basic_managed_windows_shared_memory &other)
+   {
+      base_t::swap(other);
+      m_wshm.swap(other.m_wshm);
+   }
+
+   /// @cond
+
+   //!Tries to find a previous named allocation address. Returns a memory
+   //!buffer and the object count. If not found returned pointer is 0.
+   //!Never throws.
+   template <class T>
+   std::pair<T*, size_type> find  (char_ptr_holder_t name)
+   {
+      if(m_wshm.get_mapped_region().get_mode() == read_only){
+         return base_t::template find_no_lock<T>(name);
+      }
+      else{
+         return base_t::template find<T>(name);
+      }
+   }
+
+   private:
+   ipcdetail::managed_open_or_create_impl< windows_shared_memory
+                                         , AllocationAlgorithm::Alignment, false> m_wshm;
+   /// @endcond
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP

+ 198 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/managed_xsi_shared_memory.hpp

@@ -0,0 +1,198 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP
+#define BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#  pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
+#error "This header can't be used in operating systems without XSI (System V) shared memory support"
+#endif
+
+#include <boost/interprocess/detail/managed_memory_impl.hpp>
+#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
+#include <boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp>
+#include <boost/interprocess/creation_tags.hpp>
+//These includes needed to fulfill default template parameters of
+//predeclarations in interprocess_fwd.hpp
+#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
+#include <boost/interprocess/sync/mutex_family.hpp>
+#include <boost/interprocess/indexes/iset_index.hpp>
+
+namespace boost {
+
+namespace interprocess {
+
+//!A basic X/Open System Interface (XSI) shared memory named object creation class. Initializes the
+//!shared memory segment. Inherits all basic functionality from
+//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
+template
+      <
+         class CharType,
+         class AllocationAlgorithm,
+         template<class IndexConfig> class IndexType
+      >
+class basic_managed_xsi_shared_memory
+   : public ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType
+      ,ipcdetail::managed_open_or_create_impl
+         < xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment
+         , false, true>::ManagedOpenOrCreateUserOffset>
+   , private ipcdetail::managed_open_or_create_impl
+      <xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true>
+{
+   /// @cond
+   public:
+   typedef xsi_shared_memory_file_wrapper device_type;
+
+   public:
+   typedef ipcdetail::managed_open_or_create_impl
+      <xsi_shared_memory_file_wrapper, AllocationAlgorithm::Alignment, false, true>            base2_t;
+   typedef ipcdetail::basic_managed_memory_impl
+      <CharType, AllocationAlgorithm, IndexType,
+      base2_t::ManagedOpenOrCreateUserOffset>   base_t;
+
+   typedef ipcdetail::create_open_func<base_t>        create_open_func_t;
+
+   basic_managed_xsi_shared_memory *get_this_pointer()
+   {  return this;   }
+
+   private:
+   typedef typename base_t::char_ptr_holder_t   char_ptr_holder_t;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_xsi_shared_memory)
+   /// @endcond
+
+   public: //functions
+   typedef typename base_t::size_type              size_type;
+
+   //!Destroys *this and indicates that the calling process is finished using
+   //!the resource. The destructor function will deallocate
+   //!any system resources allocated by the system for use by this process for
+   //!this resource. The resource can still be opened again calling
+   //!the open constructor overload. To erase the resource from the system
+   //!use remove().
+   ~basic_managed_xsi_shared_memory()
+   {}
+
+   //!Default constructor. Does nothing.
+   //!Useful in combination with move semantics
+   basic_managed_xsi_shared_memory()
+   {}
+
+   //!Creates shared memory and creates and places the segment manager.
+   //!This can throw.
+   basic_managed_xsi_shared_memory(create_only_t create_only, const xsi_key &key,
+                             std::size_t size, const void *addr = 0, const permissions& perm = permissions())
+      : base_t()
+      , base2_t(create_only, key, size, read_write, addr,
+                create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm)
+   {}
+
+   //!Creates shared memory and creates and places the segment manager if
+   //!segment was not created. If segment was created it connects to the
+   //!segment.
+   //!This can throw.
+   basic_managed_xsi_shared_memory (open_or_create_t open_or_create,
+                              const xsi_key &key, std::size_t size,
+                              const void *addr = 0, const permissions& perm = permissions())
+      : base_t()
+      , base2_t(open_or_create, key, size, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpenOrCreate), perm)
+   {}
+
+   //!Connects to a created shared memory and its segment manager.
+   //!in read-only mode.
+   //!This can throw.
+   basic_managed_xsi_shared_memory (open_read_only_t, const xsi_key &key,
+                                const void *addr = 0)
+      : base_t()
+      , base2_t(open_only, key, read_only, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Connects to a created shared memory and its segment manager.
+   //!This can throw.
+   basic_managed_xsi_shared_memory (open_only_t open_only, const xsi_key &key,
+                                const void *addr = 0)
+      : base_t()
+      , base2_t(open_only, key, read_write, addr,
+                create_open_func_t(get_this_pointer(),
+                ipcdetail::DoOpen))
+   {}
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_xsi_shared_memory(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved)
+   {
+      basic_managed_xsi_shared_memory tmp;
+      this->swap(moved);
+      tmp.swap(moved);
+   }
+
+   //!Moves the ownership of "moved"'s managed memory to *this.
+   //!Does not throw
+   basic_managed_xsi_shared_memory &operator=(BOOST_RV_REF(basic_managed_xsi_shared_memory) moved)
+   {
+      basic_managed_xsi_shared_memory tmp(boost::move(moved));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Swaps the ownership of the managed shared memories managed by *this and other.
+   //!Never throws.
+   void swap(basic_managed_xsi_shared_memory &other)
+   {
+      base_t::swap(other);
+      base2_t::swap(other);
+   }
+
+   //!Erases a XSI shared memory object identified by shmid
+   //!from the system.
+   //!Returns false on error. Never throws
+   static bool remove(int shmid)
+   {  return device_type::remove(shmid); }
+
+   int get_shmid() const
+   {  return base2_t::get_device().get_shmid(); }
+
+   /// @cond
+
+   //!Tries to find a previous named allocation address. Returns a memory
+   //!buffer and the object count. If not found returned pointer is 0.
+   //!Never throws.
+   template <class T>
+   std::pair<T*, std::size_t> find  (char_ptr_holder_t name)
+   {
+      if(base2_t::get_mapped_region().get_mode() == read_only){
+         return base_t::template find_no_lock<T>(name);
+      }
+      else{
+         return base_t::template find<T>(name);
+      }
+   }
+
+   /// @endcond
+};
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MANAGED_XSI_SHARED_MEMORY_HPP
+

+ 883 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/mapped_region.hpp

@@ -0,0 +1,883 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2012. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_MAPPED_REGION_HPP
+#define BOOST_INTERPROCESS_MAPPED_REGION_HPP
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#include <boost/interprocess/interprocess_fwd.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <boost/move/move.hpp>
+#include <boost/interprocess/detail/utilities.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <string>
+#include <boost/cstdint.hpp>
+//Some Unixes use caddr_t instead of void * in madvise
+//              SunOS                                 Tru64                               HP-UX                    AIX
+#if defined(sun) || defined(__sun) || defined(__osf__) || defined(__osf) || defined(_hpux) || defined(hpux) || defined(_AIX)
+#define BOOST_INTERPROCESS_MADVISE_USES_CADDR_T
+#include <sys/types.h>
+#endif
+
+//A lot of UNIXes have destructive semantics for MADV_DONTNEED, so
+//we need to be careful to allow it.
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+#define BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS
+#endif
+
+#if defined (BOOST_INTERPROCESS_WINDOWS)
+#  include <boost/interprocess/detail/win32_api.hpp>
+#  include <boost/interprocess/sync/windows/sync_utils.hpp>
+#else
+#  ifdef BOOST_HAS_UNISTD_H
+#    include <fcntl.h>
+#    include <sys/mman.h>     //mmap
+#    include <unistd.h>
+#    include <sys/stat.h>
+#    include <sys/types.h>
+#    if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
+#      include <sys/shm.h>      //System V shared memory...
+#    endif
+#    include <boost/assert.hpp>
+#  else
+#    error Unknown platform
+#  endif
+
+#endif   //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+//!\file
+//!Describes mapped region class
+
+namespace boost {
+namespace interprocess {
+
+/// @cond
+
+//Solaris declares madvise only in some configurations but defines MADV_XXX, a bit confusing.
+//Predeclare it here to avoid any compilation error
+#if (defined(sun) || defined(__sun)) && defined(MADV_NORMAL)
+extern "C" int madvise(caddr_t, size_t, int);
+#endif
+
+namespace ipcdetail{ class interprocess_tester; }
+namespace ipcdetail{ class raw_mapped_region_creator; }
+
+/// @endcond
+
+//!The mapped_region class represents a portion or region created from a
+//!memory_mappable object.
+//!
+//!The OS can map a region bigger than the requested one, as region must
+//!be multiple of the page size, but mapped_region will always refer to
+//!the region specified by the user.
+class mapped_region
+{
+   /// @cond
+   //Non-copyable
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(mapped_region)
+   /// @endcond
+
+   public:
+
+   //!Creates a mapping region of the mapped memory "mapping", starting in
+   //!offset "offset", and the mapping's size will be "size". The mapping
+   //!can be opened for read only, read-write or copy-on-write.
+   //!
+   //!If an address is specified, both the offset and the address must be
+   //!multiples of the page size.
+   //!
+   //!The OS could allocate more pages than size/page_size(), but get_address()
+   //!will always return the address passed in this function (if not null) and
+   //!get_size() will return the specified size.
+   template<class MemoryMappable>
+   mapped_region(const MemoryMappable& mapping
+                ,mode_t mode
+                ,offset_t offset = 0
+                ,std::size_t size = 0
+                ,const void *address = 0);
+
+   //!Default constructor. Address will be 0 (nullptr).
+   //!Size will be 0.
+   //!Does not throw
+   mapped_region();
+
+   //!Move constructor. *this will be constructed taking ownership of "other"'s
+   //!region and "other" will be left in default constructor state.
+   mapped_region(BOOST_RV_REF(mapped_region) other)
+   #if defined (BOOST_INTERPROCESS_WINDOWS)
+   :  m_base(0), m_size(0)
+   ,  m_page_offset(0)
+   ,  m_mode(read_only)
+   ,  m_file_or_mapping_hnd(ipcdetail::invalid_file())
+   #else
+   :  m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
+   #endif
+   {  this->swap(other);   }
+
+   //!Destroys the mapped region.
+   //!Does not throw
+   ~mapped_region();
+
+   //!Move assignment. If *this owns a memory mapped region, it will be
+   //!destroyed and it will take ownership of "other"'s memory mapped region.
+   mapped_region &operator=(BOOST_RV_REF(mapped_region) other)
+   {
+      mapped_region tmp(boost::move(other));
+      this->swap(tmp);
+      return *this;
+   }
+
+   //!Swaps the mapped_region with another
+   //!mapped region
+   void swap(mapped_region &other);
+
+   //!Returns the size of the mapping. Never throws.
+   std::size_t get_size() const;
+
+   //!Returns the base address of the mapping.
+   //!Never throws.
+   void*       get_address() const;
+
+   //!Returns the mode of the mapping used to construct the mapped region.
+   //!Never throws.
+   mode_t get_mode() const;
+
+   //!Flushes to the disk a byte range within the mapped memory.
+   //!If 'async' is true, the function will return before flushing operation is completed
+   //!If 'async' is false, function will return once data has been written into the underlying
+   //!device (i.e., in mapped files OS cached information is written to disk).
+   //!Never throws. Returns false if operation could not be performed.
+   bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0, bool async = true);
+
+   //!Shrinks current mapped region. If after shrinking there is no longer need for a previously
+   //!mapped memory page, accessing that page can trigger a segmentation fault.
+   //!Depending on the OS, this operation might fail (XSI shared memory), it can decommit storage
+   //!and free a portion of the virtual address space (e.g.POSIX) or this
+   //!function can release some physical memory wihout freeing any virtual address space(Windows).
+   //!Returns true on success. Never throws.
+   bool shrink_by(std::size_t bytes, bool from_back = true);
+
+   //!This enum specifies region usage behaviors that an application can specify
+   //!to the mapped region implementation.
+   enum advice_types{ 
+      //!Specifies that the application has no advice to give on its behavior with respect to
+      //!the region. It is the default characteristic if no advice is given for a range of memory.
+      advice_normal,
+      //!Specifies that the application expects to access the region sequentially from
+      //!lower addresses to higher addresses. The implementation can lower the priority of
+      //!preceding pages within the region once a page have been accessed.
+      advice_sequential,
+      //!Specifies that the application expects to access the region in a random order,
+      //!and prefetching is likely not advantageous.
+      advice_random,
+      //!Specifies that the application expects to access the region in the near future.
+      //!The implementation can prefetch pages of the region.
+      advice_willneed,
+      //!Specifies that the application expects that it will not access the region in the near future.
+      //!The implementation can unload pages within the range to save system resources.
+      advice_dontneed
+   };
+
+   //!Advises the implementation on the expected behavior of the application with respect to the data
+   //!in the region. The implementation may use this information to optimize handling of the region data.
+   //!This function has no effect on the semantics of access to memory in the region, although it may affect
+   //!the performance of access.
+   //!If the advise type is not known to the implementation, the function returns false. True otherwise.
+   bool advise(advice_types advise);
+
+   //!Returns the size of the page. This size is the minimum memory that
+   //!will be used by the system when mapping a memory mappable source and
+   //!will restrict the address and the offset to map.
+   static std::size_t get_page_size();
+
+   /// @cond
+   private:
+   //!Closes a previously opened memory mapping. Never throws
+   void priv_close();
+
+   void* priv_map_address()  const;
+   std::size_t priv_map_size()  const;
+   bool priv_flush_param_check(std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const;
+   bool priv_shrink_param_check(std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes);
+   static void priv_size_from_mapping_size
+      (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size);
+   static offset_t priv_page_offset_addr_fixup(offset_t page_offset, const void *&addr);
+
+   template<int dummy>
+   struct page_size_holder
+   {
+      static const std::size_t PageSize;
+      static std::size_t get_page_size();
+   };
+
+   void*             m_base;
+   std::size_t       m_size;
+   std::size_t       m_page_offset;
+   mode_t            m_mode;
+   #if defined(BOOST_INTERPROCESS_WINDOWS)
+   file_handle_t     m_file_or_mapping_hnd;
+   #else
+   bool              m_is_xsi;
+   #endif
+
+   friend class ipcdetail::interprocess_tester;
+   friend class ipcdetail::raw_mapped_region_creator;
+   void dont_close_on_destruction();
+   #if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+   template<int Dummy>
+   static void destroy_syncs_in_range(const void *addr, std::size_t size);
+   #endif
+   /// @endcond
+};
+
+///@cond
+
+inline void swap(mapped_region &x, mapped_region &y)
+{  x.swap(y);  }
+
+inline mapped_region::~mapped_region()
+{  this->priv_close(); }
+
+inline std::size_t mapped_region::get_size()  const
+{  return m_size; }
+
+inline mode_t mapped_region::get_mode()  const
+{  return m_mode;   }
+
+inline void*    mapped_region::get_address()  const
+{  return m_base; }
+
+inline void*    mapped_region::priv_map_address()  const
+{  return static_cast<char*>(m_base) - m_page_offset; }
+
+inline std::size_t mapped_region::priv_map_size()  const
+{  return m_size + m_page_offset; }
+
+inline bool mapped_region::priv_flush_param_check
+   (std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const
+{
+   //Check some errors
+   if(m_base == 0)
+      return false;
+
+   if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){
+      return false;
+   }
+
+   //Update flush size if the user does not provide it
+   if(numbytes == 0){
+      numbytes = m_size - mapping_offset;
+   }
+   addr = (char*)this->priv_map_address() + mapping_offset;
+   numbytes += m_page_offset;
+   return true;
+}
+
+inline bool mapped_region::priv_shrink_param_check
+   (std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes)
+{
+   //Check some errors
+   if(m_base == 0 || bytes > m_size){
+      return false;
+   }
+   else if(bytes == m_size){
+      this->priv_close();
+      return true;
+   }
+   else{
+      const std::size_t page_size = mapped_region::get_page_size();
+      if(from_back){
+         const std::size_t new_pages = (m_size + m_page_offset - bytes - 1)/page_size + 1;
+         shrink_page_start = static_cast<char*>(this->priv_map_address()) + new_pages*page_size;
+         shrink_page_bytes = m_page_offset + m_size - new_pages*page_size;
+         m_size -= bytes;
+      }
+      else{
+         shrink_page_start = this->priv_map_address();
+         m_page_offset += bytes;
+         shrink_page_bytes = (m_page_offset/page_size)*page_size;
+         m_page_offset = m_page_offset % page_size;
+         m_size -= bytes;
+         m_base  = static_cast<char *>(m_base) + bytes;
+         assert(shrink_page_bytes%page_size == 0);
+      }
+      return true;
+   }
+}
+
+inline void mapped_region::priv_size_from_mapping_size
+   (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size)
+{
+   //Check if mapping size fits in the user address space
+   //as offset_t is the maximum file size and its signed.
+   if(mapping_size < offset ||
+      boost::uintmax_t(mapping_size - (offset - page_offset)) >
+         boost::uintmax_t(std::size_t(-1))){
+      error_info err(size_error);
+      throw interprocess_exception(err);
+   }
+   size = static_cast<std::size_t>(mapping_size - (offset - page_offset));
+}
+
+inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, const void *&address)
+{
+   //We can't map any offset so we have to obtain system's
+   //memory granularity
+   const std::size_t page_size  = mapped_region::get_page_size();
+
+   //We calculate the difference between demanded and valid offset
+   //(always less than a page in std::size_t, thus, representable by std::size_t)
+   const std::size_t page_offset =
+      static_cast<std::size_t>(offset - (offset / page_size) * page_size);
+   //Update the mapping address
+   if(address){
+      address = static_cast<const char*>(address) - page_offset;
+   }
+   return page_offset;
+}
+
+#if defined (BOOST_INTERPROCESS_WINDOWS)
+
+inline mapped_region::mapped_region()
+   :  m_base(0), m_size(0), m_page_offset(0), m_mode(read_only)
+   ,  m_file_or_mapping_hnd(ipcdetail::invalid_file())
+{}
+
+template<int dummy>
+inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
+{
+   winapi::system_info info;
+   get_system_info(&info);
+   return std::size_t(info.dwAllocationGranularity);
+}
+
+template<class MemoryMappable>
+inline mapped_region::mapped_region
+   (const MemoryMappable &mapping
+   ,mode_t mode
+   ,offset_t offset
+   ,std::size_t size
+   ,const void *address)
+   :  m_base(0), m_size(0), m_page_offset(0), m_mode(mode)
+   ,  m_file_or_mapping_hnd(ipcdetail::invalid_file())
+{
+   mapping_handle_t mhandle = mapping.get_mapping_handle();
+   {
+      file_handle_t native_mapping_handle = 0;
+
+      //Set accesses
+      //For "create_file_mapping"
+      unsigned long protection = 0;
+      //For "mapviewoffile"
+      unsigned long map_access = 0;
+
+      switch(mode)
+      {
+         case read_only:
+         case read_private:
+            protection   |= winapi::page_readonly;
+            map_access   |= winapi::file_map_read;
+         break;
+         case read_write:
+            protection   |= winapi::page_readwrite;
+            map_access   |= winapi::file_map_write;
+         break;
+         case copy_on_write:
+            protection   |= winapi::page_writecopy;
+            map_access   |= winapi::file_map_copy;
+         break;
+         default:
+            {
+               error_info err(mode_error);
+               throw interprocess_exception(err);
+            }
+         break;
+      }
+
+      //For file mapping (including emulated shared memory through temporary files),
+      //the device is a file handle so we need to obtain file's size and call create_file_mapping
+      //to obtain the mapping handle.
+      //For files we don't need the file mapping after mapping the memory, as the file is there
+      //so we'll program the handle close
+      void * handle_to_close = winapi::invalid_handle_value;
+      if(!mhandle.is_shm){
+         //Create mapping handle
+         native_mapping_handle = winapi::create_file_mapping
+            ( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle())
+            , protection, 0, 0, 0);
+
+         //Check if all is correct
+         if(!native_mapping_handle){
+            error_info err = winapi::get_last_error();
+            throw interprocess_exception(err);
+         }
+         handle_to_close = native_mapping_handle;
+      }
+      else{
+         //For windows_shared_memory the device handle is already a mapping handle
+         //and we need to maintain it
+         native_mapping_handle = mhandle.handle;
+      }
+      //RAII handle close on scope exit
+      const winapi::handle_closer close_handle(handle_to_close);
+      (void)close_handle;
+
+      const offset_t page_offset = priv_page_offset_addr_fixup(offset, address);
+
+      //Obtain mapping size if user provides 0 size
+      if(size == 0){
+         offset_t mapping_size;
+         if(!winapi::get_file_mapping_size(native_mapping_handle, mapping_size)){
+            error_info err = winapi::get_last_error();
+            throw interprocess_exception(err);
+         }
+         //This can throw
+         priv_size_from_mapping_size(mapping_size, offset, page_offset, size);
+      }
+
+
+      //Map with new offsets and size
+      void *base = winapi::map_view_of_file_ex
+                                 (native_mapping_handle,
+                                 map_access,
+                                 offset - page_offset,
+                                 static_cast<std::size_t>(page_offset + size),
+                                 const_cast<void*>(address));
+      //Check error
+      if(!base){
+         error_info err = winapi::get_last_error();
+         throw interprocess_exception(err);
+      }
+
+      //Calculate new base for the user
+      m_base = static_cast<char*>(base) + page_offset;
+      m_page_offset = page_offset;
+      m_size = size;
+   }
+   //Windows shared memory needs the duplication of the handle if we want to
+   //make mapped_region independent from the mappable device
+   //
+   //For mapped files, we duplicate the file handle to be able to FlushFileBuffers
+   if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_or_mapping_hnd)){
+      error_info err = winapi::get_last_error();
+      this->priv_close();
+      throw interprocess_exception(err);
+   }
+}
+
+inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async)
+{
+   void *addr;
+   if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){
+      return false;
+   }
+   //Flush it all
+   if(!winapi::flush_view_of_file(addr, numbytes)){
+      return false;
+   }
+   //m_file_or_mapping_hnd can be a file handle or a mapping handle.
+   //so flushing file buffers has only sense for files...
+   else if(async && m_file_or_mapping_hnd != winapi::invalid_handle_value &&
+           winapi::get_file_type(m_file_or_mapping_hnd) == winapi::file_type_disk){
+      return winapi::flush_file_buffers(m_file_or_mapping_hnd);
+   }
+   return true;
+}
+
+inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back)
+{
+   void *shrink_page_start;
+   std::size_t shrink_page_bytes;
+   if(!this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){
+      return false;
+   }
+   else if(shrink_page_bytes){
+      //In Windows, we can't decommit the storage or release the virtual address space,
+      //the best we can do is try to remove some memory from the process working set. 
+      //With a bit of luck we can free some physical memory.
+      unsigned long old_protect_ignored;
+      bool b_ret = winapi::virtual_unlock(shrink_page_start, shrink_page_bytes)
+                           || (winapi::get_last_error() == winapi::error_not_locked);
+      (void)old_protect_ignored;
+      //Change page protection to forbid any further access
+      b_ret = b_ret && winapi::virtual_protect
+         (shrink_page_start, shrink_page_bytes, winapi::page_noaccess, old_protect_ignored);
+      return b_ret;
+   }
+   else{
+      return true;
+   }
+}
+
+inline bool mapped_region::advise(advice_types)
+{
+   //Windows has no madvise/posix_madvise equivalent
+   return false;
+}
+
+inline void mapped_region::priv_close()
+{
+   if(m_base){
+      void *addr = this->priv_map_address();
+      #if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+      mapped_region::destroy_syncs_in_range<0>(addr, m_size);
+      #endif
+      winapi::unmap_view_of_file(addr);
+      m_base = 0;
+   }
+   if(m_file_or_mapping_hnd != ipcdetail::invalid_file()){
+      winapi::close_handle(m_file_or_mapping_hnd);
+      m_file_or_mapping_hnd = ipcdetail::invalid_file();
+   }
+}
+
+inline void mapped_region::dont_close_on_destruction()
+{}
+
+#else    //#if (defined BOOST_INTERPROCESS_WINDOWS)
+
+inline mapped_region::mapped_region()
+   :  m_base(0), m_size(0), m_page_offset(0), m_mode(read_only), m_is_xsi(false)
+{}
+
+template<int dummy>
+inline std::size_t mapped_region::page_size_holder<dummy>::get_page_size()
+{  return std::size_t(sysconf(_SC_PAGESIZE)); }
+
+template<class MemoryMappable>
+inline mapped_region::mapped_region
+   ( const MemoryMappable &mapping
+   , mode_t mode
+   , offset_t offset
+   , std::size_t size
+   , const void *address)
+   : m_base(0), m_size(0), m_page_offset(0), m_mode(mode), m_is_xsi(false)
+{
+   mapping_handle_t map_hnd = mapping.get_mapping_handle();
+
+   //Some systems dont' support XSI shared memory
+   #ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+   if(map_hnd.is_xsi){
+      //Get the size
+      ::shmid_ds xsi_ds;
+      int ret = ::shmctl(map_hnd.handle, IPC_STAT, &xsi_ds);
+      if(ret == -1){
+         error_info err(system_error_code());
+         throw interprocess_exception(err);
+      }
+      //Compare sizess
+      if(size == 0){
+         size = (std::size_t)xsi_ds.shm_segsz;
+      }
+      else if(size != (std::size_t)xsi_ds.shm_segsz){
+         error_info err(size_error);
+         throw interprocess_exception(err);
+      }
+      //Calculate flag
+      int flag = 0;
+      if(m_mode == read_only){
+         flag |= SHM_RDONLY;
+      }
+      else if(m_mode != read_write){
+         error_info err(mode_error);
+         throw interprocess_exception(err);
+      }
+      //Attach memory
+      void *base = ::shmat(map_hnd.handle, (void*)address, flag);
+      if(base == (void*)-1){
+         error_info err(system_error_code());
+         throw interprocess_exception(err);
+      }
+      //Update members
+      m_base   = base;
+      m_size   = size;
+      m_mode   = mode;
+      m_page_offset = 0;
+      m_is_xsi = true;
+      return;
+   }
+   #endif   //ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+
+   //We calculate the difference between demanded and valid offset
+   const offset_t page_offset = priv_page_offset_addr_fixup(offset, address);
+
+   if(size == 0){
+      struct ::stat buf;
+      if(0 != fstat(map_hnd.handle, &buf)){
+         error_info err(system_error_code());
+         throw interprocess_exception(err);
+      }
+      //This can throw
+      priv_size_from_mapping_size(buf.st_size, offset, page_offset, size);
+   }
+
+   //Create new mapping
+   int prot    = 0;
+   int flags   = 
+      #ifdef MAP_NOSYNC
+      //Avoid excessive syncing in BSD systems
+      MAP_NOSYNC;
+      #else
+      0;
+      #endif
+
+   switch(mode)
+   {
+      case read_only:
+         prot  |= PROT_READ;
+         flags |= MAP_SHARED;
+      break;
+
+      case read_private:
+         prot  |= (PROT_READ);
+         flags |= MAP_PRIVATE;
+      break;
+
+      case read_write:
+         prot  |= (PROT_WRITE | PROT_READ);
+         flags |= MAP_SHARED;
+      break;
+
+      case copy_on_write:
+         prot  |= (PROT_WRITE | PROT_READ);
+         flags |= MAP_PRIVATE;
+      break;
+
+      default:
+         {
+            error_info err(mode_error);
+            throw interprocess_exception(err);
+         }
+      break;
+   }
+
+   //Map it to the address space
+   void* base = mmap ( const_cast<void*>(address)
+                     , static_cast<std::size_t>(page_offset + size)
+                     , prot
+                     , flags
+                     , mapping.get_mapping_handle().handle
+                     , offset - page_offset);
+
+   //Check if mapping was successful
+   if(base == MAP_FAILED){
+      error_info err = system_error_code();
+      throw interprocess_exception(err);
+   }
+
+   //Calculate new base for the user
+   m_base = static_cast<char*>(base) + page_offset;
+   m_page_offset = page_offset;
+   m_size   = size;
+
+   //Check for fixed mapping error
+   if(address && (base != address)){
+      error_info err(busy_error);
+      this->priv_close();
+      throw interprocess_exception(err);
+   }
+}
+
+inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back)
+{
+   void *shrink_page_start = 0;
+   std::size_t shrink_page_bytes = 0;
+   if(m_is_xsi || !this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){
+      return false;
+   }
+   else if(shrink_page_bytes){
+      //In UNIX we can decommit and free virtual address space.
+      return 0 == munmap(shrink_page_start, shrink_page_bytes);
+   }
+   else{
+      return true;
+   }
+}
+
+inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async)
+{
+   void *addr;
+   if(m_is_xsi || !this->priv_flush_param_check(mapping_offset, addr, numbytes)){
+      return false;
+   }
+   //Flush it all
+   return msync(addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0;
+}
+
+inline bool mapped_region::advise(advice_types advice)
+{
+   int unix_advice = 0;
+   //Modes; 0: none, 2: posix, 1: madvise
+   const unsigned int mode_none = 0;
+   const unsigned int mode_padv = 1;
+   const unsigned int mode_madv = 2;
+   unsigned int mode = mode_none;
+   //Choose advice either from POSIX (preferred) or native Unix
+   switch(advice){
+      case advice_normal:
+         #if defined(POSIX_MADV_NORMAL)
+         unix_advice = POSIX_MADV_NORMAL;
+         mode = mode_padv;
+         #elif defined(MADV_NORMAL)
+         unix_advice = MADV_NORMAL;
+         mode = mode_madv;
+         #endif
+      break;
+      case advice_sequential:
+         #if defined(POSIX_MADV_SEQUENTIAL)
+         unix_advice = POSIX_MADV_SEQUENTIAL;
+         mode = mode_padv;
+         #elif defined(MADV_SEQUENTIAL)
+         unix_advice = MADV_SEQUENTIAL;
+         mode = mode_madv;
+         #endif
+      break;
+      case advice_random:
+         #if defined(POSIX_MADV_RANDOM)
+         unix_advice = POSIX_MADV_RANDOM;
+         mode = mode_padv;
+         #elif defined(MADV_RANDOM)
+         unix_advice = MADV_RANDOM;
+         mode = mode_madv;
+         #endif
+      break;
+      case advice_willneed:
+         #if defined(POSIX_MADV_WILLNEED)
+         unix_advice = POSIX_MADV_WILLNEED;
+         mode = mode_padv;
+         #elif defined(MADV_WILLNEED)
+         unix_advice = MADV_WILLNEED;
+         mode = mode_madv;
+         #endif
+      break;
+      case advice_dontneed:
+         #if defined(POSIX_MADV_DONTNEED)
+         unix_advice = POSIX_MADV_DONTNEED;
+         mode = mode_padv;
+         #elif defined(MADV_DONTNEED) && defined(BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS)
+         unix_advice = MADV_DONTNEED;
+         mode = mode_madv;
+         #endif
+      break;
+      default:
+      return false;
+   }
+   switch(mode){
+      #if defined(POSIX_MADV_NORMAL)
+         case mode_padv:
+         return 0 == posix_madvise(this->priv_map_address(), this->priv_map_size(), unix_advice);
+      #endif
+      #if defined(MADV_NORMAL)
+         case mode_madv:
+         return 0 == madvise(
+            #if defined(BOOST_INTERPROCESS_MADVISE_USES_CADDR_T)
+            (caddr_t)
+            #endif
+            this->priv_map_address(), this->priv_map_size(), unix_advice);
+      #endif
+      default:
+      return false;
+
+   }
+}
+
+inline void mapped_region::priv_close()
+{
+   if(m_base != 0){
+      #ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+      if(m_is_xsi){
+         int ret = ::shmdt(m_base);
+         BOOST_ASSERT(ret == 0);
+         (void)ret;
+         return;
+      }
+      #endif //#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
+      munmap(this->priv_map_address(), this->priv_map_size());
+      m_base = 0;
+   }
+}
+
+inline void mapped_region::dont_close_on_destruction()
+{  m_base = 0;   }
+
+#endif   //##if (defined BOOST_INTERPROCESS_WINDOWS)
+
+template<int dummy>
+const std::size_t mapped_region::page_size_holder<dummy>::PageSize
+   = mapped_region::page_size_holder<dummy>::get_page_size();
+
+inline std::size_t mapped_region::get_page_size()
+{
+   if(!page_size_holder<0>::PageSize)
+      return page_size_holder<0>::get_page_size();
+   else
+      return page_size_holder<0>::PageSize;
+}
+
+inline void mapped_region::swap(mapped_region &other)
+{
+   ipcdetail::do_swap(this->m_base, other.m_base);
+   ipcdetail::do_swap(this->m_size, other.m_size);
+   ipcdetail::do_swap(this->m_page_offset, other.m_page_offset);
+   ipcdetail::do_swap(this->m_mode,  other.m_mode);
+   #if (defined BOOST_INTERPROCESS_WINDOWS)
+   ipcdetail::do_swap(this->m_file_or_mapping_hnd, other.m_file_or_mapping_hnd);
+   #else
+   ipcdetail::do_swap(this->m_is_xsi, other.m_is_xsi);
+   #endif
+}
+
+//!No-op functor
+struct null_mapped_region_function
+{
+   bool operator()(void *, std::size_t , bool) const
+      {   return true;   }
+};
+
+/// @endcond
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif   //BOOST_INTERPROCESS_MAPPED_REGION_HPP
+
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+
+#ifndef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
+#define BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
+
+#if defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+#  include <boost/interprocess/sync/windows/sync_utils.hpp>
+#  include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
+
+namespace boost {
+namespace interprocess {
+
+template<int Dummy>
+inline void mapped_region::destroy_syncs_in_range(const void *addr, std::size_t size)
+{
+   ipcdetail::sync_handles &handles =
+      ipcdetail::windows_intermodule_singleton<ipcdetail::sync_handles>::get();
+   handles.destroy_syncs_in_range(addr, size);
+}
+
+}  //namespace interprocess {
+}  //namespace boost {
+
+#endif   //defined(BOOST_INTERPROCESS_WINDOWS) && !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
+
+#endif   //#ifdef BOOST_INTERPROCESS_MAPPED_REGION_EXT_HPP
+
+#endif   //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
+

+ 0 - 0
mainline/tests/system/test_boost_parts/sources/interprocess/mem_algo/detail/mem_algo_common.hpp


Some files were not shown because too many files changed in this diff