Browse code

Commit made by the Bioconductor Git-SVN bridge. Consists of 1 commit.

Commit information:

Commit id: 967ff13a84539345f77c75211d0c204a3f3d0edc
Commit message: good job everybody
Committed by: Laurent
Author Name: Laurent
Commit date: 2014-06-22 06:54:49 +0100
Author date: 2014-06-22 06:54:49 +0100



git-svn-id: https://hedgehog.fhcrc.org/bioconductor/trunk/madman/Rpacks/mzR@91685 bc3139a8-67e5-0310-9ffc-ced21a209358

s.neumann authored on 22/06/2014 05:56:07
Showing 74 changed files

... ...
@@ -1,26 +1,27 @@
1
-Package: mzR
2
-Type: Package
3
-Title: parser for netCDF, mzXML, mzData and mzML files (mass
4
-        spectrometry data)
5
-Version: 1.11.2
6
-Author: Bernd Fischer, Steffen Neumann, Laurent Gatto, Qiang Kou
7
-Maintainer: Bernd Fischer <bernd.fischer@embl.de>, Steffen Neumann
8
-	    <sneumann@ipb-halle.de>, Laurent Gatto <lg390@cam.ac.uk>, 
9
-	    Qiang Kou <qkou@umail.iu.edu>
10
-Description: mzR provides a unified API to the common file formats and
11
-        parsers available for mass spectrometry data. It comes with a
12
-        wrapper for the ISB random access parser for mass spectrometry
13
-        mzXML, mzData and mzML files. The package contains the original
14
-        code written by the ISB, and a subset of the proteowizard
15
-        library for mzML. The netCDF reading code has previously been
16
-        used in XCMS.
17
-License: Artistic-2.0
18
-LazyLoad: yes
19
-Depends: Rcpp (>= 0.10.1), methods, utils
20
-Imports: Biobase
21
-Suggests: msdata (>= 0.1.9), RUnit, faahKO
22
-LinkingTo: Rcpp
23
-RcppModules: Ramp
24
-SystemRequirements: GNU make, NetCDF, zlib
25
-biocViews: Infrastructure, DataImport, Proteomics, Metabolomics,
26
-        MassSpectrometry
1
+Package: mzR
2
+Type: Package
3
+Title: parser for netCDF, mzXML, mzData and mzML files (mass
4
+        spectrometry data)
5
+Version: 1.11.3
6
+Author: Bernd Fischer, Steffen Neumann, Laurent Gatto, Qiang Kou
7
+Maintainer: Bernd Fischer <bernd.fischer@embl.de>, Steffen Neumann
8
+ <sneumann@ipb-halle.de>, Laurent Gatto <lg390@cam.ac.uk>,
9
+ Qiang Kou <qkou@umail.iu.edu>
10
+Description: mzR provides a unified API to the common file formats and
11
+        parsers available for mass spectrometry data. It comes with a
12
+        wrapper for the ISB random access parser for mass spectrometry
13
+        mzXML, mzData and mzML files. The package contains the original
14
+        code written by the ISB, and a subset of the proteowizard
15
+        library for mzML. The netCDF reading code has previously been
16
+        used in XCMS.
17
+License: Artistic-2.0
18
+LazyLoad: yes
19
+Depends: Rcpp (>= 0.10.1), methods, utils
20
+Imports: Biobase
21
+Suggests: msdata (>= 0.1.9), RUnit, faahKO
22
+LinkingTo: Rcpp
23
+RcppModules: Ramp
24
+SystemRequirements: GNU make, NetCDF, zlib
25
+biocViews: Infrastructure, DataImport, Proteomics, Metabolomics,
26
+        MassSpectrometry
27
+Packaged: 2014-06-21 21:42:58 UTC; Administrator
... ...
@@ -1,3 +1,7 @@
1
+CHANGES IN VERSION 1.11.3
2
+-------------------------
3
+ o Updated pwiz and fixed building on all platforms [2014-06-22 Sun]
4
+
1 5
 CHANGES IN VERSION 1.11.2
2 6
 -------------------------
3 7
  o adding missed src files [2014-05-28 Tue]
4 8
deleted file mode 100644
... ...
@@ -1,144 +0,0 @@
1
-rampInit <- function() {
2
-
3
-    result <- .C("RampRInit",
4
-                 PACKAGE = "mzR")
5
-}
6
-
7
-rampPrintFiles <- function() {
8
-
9
-    result <- .C("RampRPrintFiles",
10
-                 PACKAGE = "mzR")
11
-}
12
-
13
-rampIsFile <- function(filename) {
14
-
15
-    # The C version doesn't do anything extra
16
-    #.C("RampRIsFile",
17
-    #   as.character(filename),
18
-    #   isfile = logical(1),
19
-    #   PACKAGE = "mzR")$isfile
20
-
21
-    if (!file.exists(filename))
22
-        return(FALSE)
23
-    text <- readChar(filename, 1024)
24
-
25
-    length(text) > 0
26
-}
27
-
28
-rampOpen <- function(filename) {
29
-
30
-    result <- .C("RampROpen",
31
-                 as.character(filename),
32
-                 rampid = integer(1),
33
-                 status = integer(1),
34
-                 PACKAGE = "mzR")
35
-
36
-    if (result$status)
37
-        return(result$status)
38
-
39
-    return(result$rampid)
40
-}
41
-
42
-rampClose <- function(rampid) {
43
-
44
-    result <- .C("RampRClose",
45
-                 as.integer(rampid),
46
-                 PACKAGE = "mzR")
47
-}
48
-
49
-rampCloseAll <- function() {
50
-
51
-    result <- .C("RampRCloseAll",
52
-                 PACKAGE = "mzR")
53
-}
54
-
55
-rampNumScans <- function(rampid) {
56
-
57
-    result <- .C("RampRNumScans",
58
-                 as.integer(rampid),
59
-                 numscans = integer(1),
60
-                 status = integer(1),
61
-                 PACKAGE = "mzR")
62
-
63
-    if (result$status)
64
-        return(NA)
65
-
66
-    return(result$numscans)
67
-}
68
-
69
-rampScanHeaders <- function(rampid) {
70
-
71
-    .Call("RampRScanHeaders",
72
-          as.integer(rampid),
73
-          PACKAGE = "mzR")
74
-}
75
-
76
-rampSIPeaks <- function(rampid, seqNum, peaksCount) {
77
-
78
-    if (!is.integer(seqNum))
79
-        seqNum <- as.integer(seqNum)
80
-    if (!is.integer(peaksCount))
81
-        peaksCount <- as.integer(peaksCount)
82
-    .Call("RampRSIPeaks",
83
-          as.integer(rampid),
84
-          seqNum,
85
-          peaksCount,
86
-          PACKAGE = "mzR")
87
-}
88
-
89
-rampRawData <- function(rampid) {
90
-
91
-    scanHeaders <- rampScanHeaders(rampid)
92
-
93
-    # Some of these checks work around buggy RAMP indexing code
94
-    scans <- scanHeaders$msLevel == 1 & scanHeaders$seqNum > 0 &
95
-             !duplicated(scanHeaders$acquisitionNum) &
96
-             scanHeaders$peaksCount > 0
97
-    if ("Full" %in% levels(scanHeaders$scanType))
98
-        scans <- scans & scanHeaders$scanType == "Full"
99
-
100
-    scans <- which(scans)
101
-
102
-    sipeaks <- rampSIPeaks(rampid, scans, scanHeaders$peaksCount[scans])
103
-
104
-    return(list(rt = scanHeaders$retentionTime[scans],
105
-                acquisitionNum = scanHeaders$acquisitionNum[scans],
106
-                tic = scanHeaders$totIonCurrent[scans],
107
-                scanindex = sipeaks$scanindex,
108
-                mz = sipeaks$mz,
109
-                intensity = sipeaks$intensity,
110
-                polarity = scanHeaders$polarity[scans]))
111
-}
112
-
113
-rampRawDataMSn <- function(rampid) {
114
-
115
-    # Check if we have MSn at all
116
-    scanHeaders <- rampScanHeaders(rampid)
117
-    if (max(scanHeaders[,"msLevel"]) < 2) {
118
-        warning("MSn spectra requested but not found")
119
-        return (NULL);
120
-    }
121
-
122
-    # Some of these checks work around buggy RAMP indexing code
123
-    scans <- ( scanHeaders$msLevel >= 2 & scanHeaders$seqNum > 0
124
-              & !duplicated(scanHeaders$acquisitionNum)
125
-              & scanHeaders$peaksCount > 0)
126
-
127
-    scans <- which(scans)
128
-
129
-    sipeaks <- rampSIPeaks(rampid, scans, scanHeaders$peaksCount[scans])
130
-
131
-    retdata <- list(rt = scanHeaders$retentionTime[scans],
132
-                    acquisitionNum = scanHeaders$acquisitionNum[scans],
133
-                    precursorNum=scanHeaders$precursorScanNum[scans],
134
-                    precursorMZ = scanHeaders$precursorMZ[scans],
135
-                    precursorIntensity = scanHeaders$precursorIntensity[scans],
136
-                    peaksCount=scanHeaders$peaksCount[scans],
137
-                    msLevel = scanHeaders$msLevel[scans],
138
-                    precursorCharge = scanHeaders$precursorCharge[scans],
139
-                    scanindex = sipeaks$scanindex, collisionEnergy = scanHeaders$collisionEnergy[scans],
140
-                    mz = sipeaks$mz,
141
-                    intensity =sipeaks$intensity);
142
-
143
-    return(retdata)
144
-}
... ...
@@ -1,4 +1,4 @@
1
-BUILT_RCPP_VERSION = package_version("0.11.1")
1
+BUILT_RCPP_VERSION = package_version("0.11.2")
2 2
 
3 3
 .onLoad <-
4 4
     function(libname, pkgname) {
5 5
deleted file mode 100644
... ...
@@ -1,63 +0,0 @@
1
-test.oldramp.mzXML <- function() {
2
-    library(msdata)
3
-    library(mzR)
4
-    cdfpath <- system.file("threonine", package = "msdata")
5
-    filename <- list.files(cdfpath, pattern="threonine_i2_e35_pH_tree.mzXML",
6
-                       full.names=TRUE, recursive = TRUE)
7
-
8
-    rampid <- mzR:::rampOpen(filename)
9
-    if (rampid < 0)
10
-       stop("Could not open mzXML/mzData file")
11
-
12
-    on.exit(mzR:::rampClose(rampid))
13
-    rawdata <- mzR:::rampRawData(rampid)
14
-    mzR:::rampClose(rampid)
15
-}
16
-
17
-test.oldramp.mzML <- function() {
18
-    library(msdata)
19
-    library(mzR)
20
-    cdfpath <- system.file("microtofq", package = "msdata")
21
-    filename <- list.files(cdfpath, pattern="MM14.mzML",
22
-                       full.names=TRUE, recursive = TRUE)
23
-
24
-    rampid <- mzR:::rampOpen(filename)
25
-    if (rampid < 0)
26
-       stop("Could not open mzXML/mzData file")
27
-
28
-    on.exit(mzR:::rampClose(rampid))
29
-    rawdata <- mzR:::rampRawData(rampid)
30
-    mzR:::rampClose(rampid)
31
-}
32
-
33
-test.oldramp.mzData <- function() {
34
-    library(msdata)
35
-    library(mzR)
36
-    cdfpath <- system.file("microtofq", package = "msdata")
37
-    filename <- list.files(cdfpath, pattern="MM14.mzdata$",
38
-                       full.names=TRUE, recursive = TRUE)
39
-
40
-    rampid <- mzR:::rampOpen(filename)
41
-    if (rampid < 0)
42
-       stop("Could not open mzXML/mzData file")
43
-
44
-    on.exit(mzR:::rampClose(rampid))
45
-    rawdata <- mzR:::rampRawData(rampid)
46
-    mzR:::rampClose(rampid)
47
-}
48
-
49
-test.oldramp.mzData.gz <- function() {
50
-    library(msdata)
51
-    library(mzR)
52
-    cdfpath <- system.file("microtofq", package = "msdata")
53
-    filename <- list.files(cdfpath, pattern="MM14.mzdata.gz",
54
-                       full.names=TRUE, recursive = TRUE)
55
-
56
-    rampid <- mzR:::rampOpen(filename)
57
-    if (rampid < 0)
58
-       stop("Could not open mzXML/mzData file")
59
-
60
-    on.exit(mzR:::rampClose(rampid))
61
-    rawdata <- mzR:::rampRawData(rampid)
62
-    mzR:::rampClose(rampid)
63
-}
... ...
@@ -73,7 +73,7 @@ PWIZOBJECTS=\
73 73
 
74 74
 MZROBJECTS=cramp.o  ramp_base64.o  ramp.o  RcppRamp.o RcppRampModule.o rnetCDF.o 
75 75
 
76
-OBJECTS= $(MZROBJECTS) $(PWIZOBJECTS) rampR.o
76
+OBJECTS= $(MZROBJECTS) $(PWIZOBJECTS) R_init_mzR.o
77 77
 
78 78
 ##
79 79
 ## R complains about assert(), hence -D_NODEBUG
... ...
@@ -22,11 +22,13 @@ PWIZOBJECTS=\
22 22
 ./pwiz/utility/minimxml/SAXParser.o \
23 23
 ./boost/iostreams/src/zlib.o \
24 24
 ./boost/iostreams/src/file_descriptor.o \
25
-./boost/thread/src/pthread/once.o \
26
-./boost/thread/src/pthread/thread.o \
27 25
 ./boost/filesystem/src/operations.o \
28 26
 ./boost/filesystem/src/path.o \
27
+./boost/filesystem/src/path_traits.o \
29 28
 ./boost/filesystem/src/utf8_codecvt_facet.o \
29
+./boost/filesystem/src/windows_file_codecvt.o \
30
+./boost/filesystem/src/codecvt_error_category.o \
31
+./boost/thread/src/win32/thread.o \
30 32
 ./pwiz/data/common/MemoryIndex.o \
31 33
 ./pwiz/data/common/CVTranslator.o \
32 34
 ./pwiz/data/common/cv.o \
... ...
@@ -53,7 +55,6 @@ PWIZOBJECTS=\
53 55
 ./pwiz/data/msdata/SpectrumList_BTDX.o \
54 56
 ./pwiz/data/msdata/SpectrumInfo.o \
55 57
 ./pwiz/data/msdata/RAMPAdapter.o \
56
-#./pwiz/data/msdata/ramp/wglob.o \
57 58
 ./pwiz/data/msdata/LegacyAdapter.o \
58 59
 ./pwiz/data/msdata/SpectrumIterator.o \
59 60
 ./pwiz/data/msdata/MSDataFile.o \
... ...
@@ -70,21 +71,21 @@ PWIZOBJECTS=\
70 71
 ./pwiz/utility/misc/SHA1.o \
71 72
 ./pwiz/utility/misc/SHA1Calculator.o \
72 73
 ./pwiz/utility/misc/sha1calc.o \
74
+./pwiz/data/msdata/ramp/wglob.o \
73 75
 ./random_access_gzFile.o
74 76
 
75
-MZROBJECTS=cramp.o  ramp_base64.o  ramp.o  RcppRamp.o RcppRampModule.o rnetCDF.o
76 77
 
77
-OBJECTS= $(MZROBJECTS) $(PWIZOBJECTS) rampR.o
78
+MZROBJECTS=cramp.o  ramp_base64.o  ramp.o  RcppRamp.o RcppRampModule.o rnetCDF.o 
78 79
 
79
-PWIZ_LDFLAGS= -lpwiz
80
-PWIZ_LDFLAGS=-lpthread 
81
-PWIZ_CPPFLAGS=-I./boost_aux/ -I./boost -I. -DHAVE_PWIZ_MZML_LIB # -DWINDOWS_NATIVE
80
+OBJECTS= $(MZROBJECTS) $(PWIZOBJECTS) R_init_mzR.o
81
+
82
+PWIZ_CPPFLAGS=-I./boost_aux/ -I./boost -I. -DHAVE_PWIZ_MZML_LIB -fpermissive -DWINDOWS_NATIVE
82 83
 
83 84
 ## Use the R_HOME indirection to support installations of multiple R version
84
-PKG_CPPFLAGS=-D_LARGEFILE_SOURCE $(PWIZ_CPPFLAGS)
85
-PKG_CFLAGS=-D_LARGEFILE_SOURCE -I./win/$(R_ARCH) -D_MSC_VER -DWIN32_LEAN_AND_MEAN -fgnu89-inline
85
+PKG_CPPFLAGS=-D_LARGEFILE_SOURCE $(PWIZ_CPPFLAGS)  # last include only for cross-compiling
86
+PKG_CFLAGS=-D_LARGEFILE_SOURCE -I./win/$(R_ARCH) -D_MSC_VER  -fgnu89-inline
86 87
 
87
-PKG_LIBS = $(shell $(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()" ) $(PWIZ_LDFLAGS) -L./win/$(R_ARCH) -lws2_32 -lnetcdf -lz
88
+PKG_LIBS = $(shell $(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()" ) $(PWIZ_LDFLAGS) -L./win/$(R_ARCH) -lws2_32 -lnetcdf -lz 
88 89
 
89 90
 all: clean $(SHLIB)
90 91
 
91 92
new file mode 100644
... ...
@@ -0,0 +1,19 @@
1
+#include <R_ext/Rdynload.h>
2
+#include "rnetCDF.h"
3
+
4
+static const R_CMethodDef cMethods[] = {
5
+    {"NetCDFStrError", (DL_FUNC) &NetCDFStrError, 3},
6
+    {"NetCDFOpen", (DL_FUNC) &NetCDFOpen, 3},
7
+    {"NetCDFClose", (DL_FUNC) &NetCDFClose, 2},
8
+    {"NetCDFVarID", (DL_FUNC) &NetCDFVarID, 4},
9
+    {"NetCDFVarLen", (DL_FUNC) &NetCDFVarLen, 4},
10
+    {"NetCDFVarDouble", (DL_FUNC) &NetCDFVarDouble, 4},
11
+    {"NetCDFVarInt", (DL_FUNC) &NetCDFVarInt, 4},
12
+    {"NetCDFMSPoints", (DL_FUNC) &NetCDFMSPoints, 7},
13
+    {NULL, NULL, 0}
14
+};
15
+
16
+void R_init_mzR(DllInfo * info)
17
+{
18
+    R_registerRoutines(info, cMethods, NULL, NULL, NULL);
19
+}
... ...
@@ -1,8 +1,21 @@
1 1
 #ifndef _mzR_RCPP_RAMP_H
2 2
 #define _mzR_RCPP_RAMP_H
3 3
 
4
-#include "cramp.h"
5 4
 #include "Rcpp.h"
5
+// Taken from http://tolstoy.newcastle.edu.au/R/e2/devel/06/11/1242.html
6
+// and http://stackoverflow.com/questions/11588765/using-rcpp-with-windows-specific-includes
7
+// Undefine the Realloc macro, which is defined by both R and by Windows stuff
8
+// Also need to undefine the Free macro
9
+#if defined(__MINGW32__)
10
+#undef Realloc
11
+#undef Free
12
+#endif
13
+
14
+#include "cramp.h"
15
+
16
+#if defined(__MINGW32__)
17
+#include <windows.h>
18
+#endif
6 19
 
7 20
 class RcppRamp {
8 21
 
9 22
new file mode 100644
... ...
@@ -0,0 +1,63 @@
1
+// (C) Copyright 2012 Vicente J. Botet Escriba
2
+// Use, modification and distribution are subject to the
3
+// Boost Software License, Version 1.0. (See accompanying file
4
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+#include <boost/thread/detail/config.hpp>
7
+#ifndef BOOST_NO_EXCEPTIONS
8
+
9
+
10
+#include <boost/thread/future_error_code.hpp>
11
+
12
+namespace boost
13
+{
14
+
15
+  namespace thread_detail
16
+  {
17
+
18
+    class  future_error_category :
19
+      public boost::system::error_category
20
+    {
21
+    public:
22
+        virtual const char* name() const BOOST_NOEXCEPT;
23
+        virtual std::string message(int ev) const;
24
+    };
25
+
26
+    const char*
27
+    future_error_category::name() const BOOST_NOEXCEPT
28
+    {
29
+        return "future";
30
+    }
31
+
32
+    std::string
33
+    future_error_category::message(int ev) const
34
+    {
35
+        switch (BOOST_SCOPED_ENUM_NATIVE(future_errc)(ev))
36
+        {
37
+        case future_errc::broken_promise:
38
+            return std::string("The associated promise has been destructed prior "
39
+                          "to the associated state becoming ready.");
40
+        case future_errc::future_already_retrieved:
41
+            return std::string("The future has already been retrieved from "
42
+                          "the promise or packaged_task.");
43
+        case future_errc::promise_already_satisfied:
44
+            return std::string("The state of the promise has already been set.");
45
+        case future_errc::no_state:
46
+            return std::string("Operation not permitted on an object without "
47
+                          "an associated state.");
48
+        }
49
+        return std::string("unspecified future_errc value\n");
50
+    }
51
+    future_error_category future_error_category_var;
52
+  }
53
+
54
+  BOOST_THREAD_DECL
55
+  const system::error_category&
56
+  future_category() BOOST_NOEXCEPT
57
+  {
58
+      return thread_detail::future_error_category_var;
59
+  }
60
+
61
+}
62
+#endif
63
+
0 64
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+// (C) Copyright Michael Glassford 2004.
2
+// (C) Copyright 2007 Anthony Williams
3
+// Use, modification and distribution are subject to the
4
+// Boost Software License, Version 1.0. (See accompanying file
5
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+#include <boost/thread/detail/config.hpp>
8
+
9
+#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE))
10
+
11
+namespace boost
12
+{
13
+    /*
14
+    This file is a "null" implementation of tss cleanup; it's
15
+    purpose is to to eliminate link errors in cases
16
+    where it is known that tss cleanup is not needed.
17
+    */
18
+
19
+    void tss_cleanup_implemented(void)
20
+    {
21
+        /*
22
+        This function's sole purpose is to cause a link error in cases where
23
+        automatic tss cleanup is not implemented by Boost.Threads as a
24
+        reminder that user code is responsible for calling the necessary
25
+        functions at the appropriate times (and for implementing an a
26
+        tss_cleanup_implemented() function to eliminate the linker's
27
+        missing symbol error).
28
+
29
+        If Boost.Threads later implements automatic tss cleanup in cases
30
+        where it currently doesn't (which is the plan), the duplicate
31
+        symbol error will warn the user that their custom solution is no
32
+        longer needed and can be removed.
33
+        */
34
+    }
35
+
36
+}
37
+
38
+#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)
0 39
new file mode 100644
... ...
@@ -0,0 +1,769 @@
1
+// Distributed under the Boost Software License, Version 1.0. (See
2
+// accompanying file LICENSE_1_0.txt or copy at
3
+// http://www.boost.org/LICENSE_1_0.txt)
4
+// (C) Copyright 2007 Anthony Williams
5
+// (C) Copyright 2007 David Deakins
6
+// (C) Copyright 2011-2013 Vicente J. Botet Escriba
7
+
8
+#ifndef _WIN32_WINNT
9
+#define _WIN32_WINNT 0x400
10
+#endif
11
+
12
+#ifndef WINVER
13
+#define WINVER 0x400
14
+#endif
15
+//#define BOOST_THREAD_VERSION 3
16
+
17
+#include <boost/thread/thread_only.hpp>
18
+#include <boost/thread/once.hpp>
19
+#include <boost/thread/tss.hpp>
20
+#include <boost/thread/condition_variable.hpp>
21
+#include <boost/thread/detail/tss_hooks.hpp>
22
+#include <boost/thread/future.hpp>
23
+
24
+#include <boost/assert.hpp>
25
+#include <boost/cstdint.hpp>
26
+#if defined BOOST_THREAD_USES_DATETIME
27
+#include <boost/date_time/posix_time/conversion.hpp>
28
+#endif
29
+#include <memory>
30
+#include <algorithm>
31
+#ifndef UNDER_CE
32
+#include <process.h>
33
+#endif
34
+#include <stdio.h>
35
+#include <windows.h>
36
+
37
+namespace boost
38
+{
39
+  namespace detail
40
+  {
41
+    thread_data_base::~thread_data_base()
42
+    {
43
+        for (notify_list_t::iterator i = notify.begin(), e = notify.end();
44
+                i != e; ++i)
45
+        {
46
+            i->second->unlock();
47
+            i->first->notify_all();
48
+        }
49
+        for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
50
+                i != e; ++i)
51
+        {
52
+            (*i)->make_ready();
53
+        }
54
+    }
55
+  }
56
+
57
+    namespace
58
+    {
59
+#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
60
+        boost::once_flag current_thread_tls_init_flag;
61
+#else
62
+        boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
63
+#endif
64
+#if defined(UNDER_CE)
65
+        // Windows CE does not define the TLS_OUT_OF_INDEXES constant.
66
+#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
67
+#endif
68
+        DWORD current_thread_tls_key=TLS_OUT_OF_INDEXES;
69
+
70
+        void create_current_thread_tls_key()
71
+        {
72
+            //tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
73
+            current_thread_tls_key=TlsAlloc();
74
+            BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
75
+        }
76
+
77
+        void cleanup_tls_key()
78
+        {
79
+            if(current_thread_tls_key!=TLS_OUT_OF_INDEXES)
80
+            {
81
+                TlsFree(current_thread_tls_key);
82
+                current_thread_tls_key=TLS_OUT_OF_INDEXES;
83
+            }
84
+        }
85
+
86
+        void set_current_thread_data(detail::thread_data_base* new_data)
87
+        {
88
+            boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
89
+            if (current_thread_tls_key!=TLS_OUT_OF_INDEXES)
90
+            {
91
+                BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
92
+            }
93
+            else
94
+            {
95
+                BOOST_VERIFY(false);
96
+                //boost::throw_exception(thread_resource_error());
97
+            }
98
+        }
99
+
100
+    }
101
+    namespace detail
102
+    {
103
+      thread_data_base* get_current_thread_data()
104
+      {
105
+          if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
106
+          {
107
+              return 0;
108
+          }
109
+          return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
110
+      }
111
+    }
112
+    namespace
113
+    {
114
+#ifndef BOOST_HAS_THREADEX
115
+// Windows CE doesn't define _beginthreadex
116
+
117
+        struct ThreadProxyData
118
+        {
119
+            typedef unsigned (__stdcall* func)(void*);
120
+            func start_address_;
121
+            void* arglist_;
122
+            ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {}
123
+        };
124
+
125
+        DWORD WINAPI ThreadProxy(LPVOID args)
126
+        {
127
+            std::auto_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args));
128
+            DWORD ret=data->start_address_(data->arglist_);
129
+            return ret;
130
+        }
131
+
132
+        //typedef void* uintptr_t;
133
+
134
+        inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
135
+                                              void* arglist, unsigned initflag, unsigned* thrdaddr)
136
+        {
137
+            DWORD threadID;
138
+            ThreadProxyData* data = new ThreadProxyData(start_address,arglist);
139
+            HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
140
+                                        data,initflag,&threadID);
141
+            if (hthread==0) {
142
+              delete data;
143
+              return 0;
144
+            }
145
+            *thrdaddr=threadID;
146
+            return reinterpret_cast<uintptr_t const>(hthread);
147
+        }
148
+
149
+#endif
150
+
151
+    }
152
+
153
+    namespace detail
154
+    {
155
+        struct thread_exit_callback_node
156
+        {
157
+            boost::detail::thread_exit_function_base* func;
158
+            thread_exit_callback_node* next;
159
+
160
+            thread_exit_callback_node(boost::detail::thread_exit_function_base* func_,
161
+                                      thread_exit_callback_node* next_):
162
+                func(func_),next(next_)
163
+            {}
164
+        };
165
+
166
+    }
167
+
168
+    namespace
169
+    {
170
+        void run_thread_exit_callbacks()
171
+        {
172
+            detail::thread_data_ptr current_thread_data(detail::get_current_thread_data(),false);
173
+            if(current_thread_data)
174
+            {
175
+                while(! current_thread_data->tss_data.empty() || current_thread_data->thread_exit_callbacks)
176
+                {
177
+                    while(current_thread_data->thread_exit_callbacks)
178
+                    {
179
+                        detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks;
180
+                        current_thread_data->thread_exit_callbacks=current_node->next;
181
+                        if(current_node->func)
182
+                        {
183
+                            (*current_node->func)();
184
+                            boost::detail::heap_delete(current_node->func);
185
+                        }
186
+                        boost::detail::heap_delete(current_node);
187
+                    }
188
+                    for(std::map<void const*,detail::tss_data_node>::iterator next=current_thread_data->tss_data.begin(),
189
+                            current,
190
+                            end=current_thread_data->tss_data.end();
191
+                        next!=end;)
192
+                    {
193
+                        current=next;
194
+                        ++next;
195
+                        if(current->second.func && (current->second.value!=0))
196
+                        {
197
+                            (*current->second.func)(current->second.value);
198
+                        }
199
+                        current_thread_data->tss_data.erase(current);
200
+                    }
201
+                }
202
+
203
+                set_current_thread_data(0);
204
+            }
205
+        }
206
+
207
+        unsigned __stdcall thread_start_function(void* param)
208
+        {
209
+            detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param));
210
+            set_current_thread_data(thread_info);
211
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
212
+            BOOST_TRY
213
+            {
214
+#endif
215
+                thread_info->run();
216
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
217
+            }
218
+            BOOST_CATCH(thread_interrupted const&)
219
+            {
220
+            }
221
+// Removed as it stops the debugger identifying the cause of the exception
222
+// Unhandled exceptions still cause the application to terminate
223
+//             BOOST_CATCH(...)
224
+//             {
225
+//                 std::terminate();
226
+//             }
227
+            BOOST_CATCH_END
228
+#endif
229
+            run_thread_exit_callbacks();
230
+            return 0;
231
+        }
232
+    }
233
+
234
+    thread::thread() BOOST_NOEXCEPT
235
+    {}
236
+
237
+    bool thread::start_thread_noexcept()
238
+    {
239
+        uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
240
+        if(!new_thread)
241
+        {
242
+            return false;
243
+//            boost::throw_exception(thread_resource_error());
244
+        }
245
+        intrusive_ptr_add_ref(thread_info.get());
246
+        thread_info->thread_handle=(detail::win32::handle)(new_thread);
247
+        ResumeThread(thread_info->thread_handle);
248
+        return true;
249
+    }
250
+
251
+    bool thread::start_thread_noexcept(const attributes& attr)
252
+    {
253
+      //uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
254
+      uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
255
+      if(!new_thread)
256
+      {
257
+        return false;
258
+//          boost::throw_exception(thread_resource_error());
259
+      }
260
+      intrusive_ptr_add_ref(thread_info.get());
261
+      thread_info->thread_handle=(detail::win32::handle)(new_thread);
262
+      ResumeThread(thread_info->thread_handle);
263
+      return true;
264
+    }
265
+
266
+    thread::thread(detail::thread_data_ptr data):
267
+        thread_info(data)
268
+    {}
269
+
270
+    namespace
271
+    {
272
+        struct externally_launched_thread:
273
+            detail::thread_data_base
274
+        {
275
+            externally_launched_thread()
276
+            {
277
+                ++count;
278
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
279
+                interruption_enabled=false;
280
+#endif
281
+            }
282
+            ~externally_launched_thread() {
283
+              BOOST_ASSERT(notify.empty());
284
+              notify.clear();
285
+              BOOST_ASSERT(async_states_.empty());
286
+              async_states_.clear();
287
+            }
288
+
289
+            void run()
290
+            {}
291
+            void notify_all_at_thread_exit(condition_variable*, mutex*)
292
+            {}
293
+
294
+        private:
295
+            externally_launched_thread(externally_launched_thread&);
296
+            void operator=(externally_launched_thread&);
297
+        };
298
+
299
+        void make_external_thread_data()
300
+        {
301
+            externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
302
+            BOOST_TRY
303
+            {
304
+                set_current_thread_data(me);
305
+            }
306
+            BOOST_CATCH(...)
307
+            {
308
+                detail::heap_delete(me);
309
+                BOOST_RETHROW
310
+            }
311
+            BOOST_CATCH_END
312
+        }
313
+
314
+        detail::thread_data_base* get_or_make_current_thread_data()
315
+        {
316
+            detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
317
+            if(!current_thread_data)
318
+            {
319
+                make_external_thread_data();
320
+                current_thread_data=detail::get_current_thread_data();
321
+            }
322
+            return current_thread_data;
323
+        }
324
+
325
+    }
326
+
327
+    thread::id thread::get_id() const BOOST_NOEXCEPT
328
+    {
329
+    #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
330
+      detail::thread_data_ptr local_thread_info=(get_thread_info)();
331
+      return local_thread_info?local_thread_info->id:0;
332
+      //return const_cast<thread*>(this)->native_handle();
333
+    #else
334
+        return thread::id((get_thread_info)());
335
+    #endif
336
+    }
337
+
338
+    bool thread::joinable() const BOOST_NOEXCEPT
339
+    {
340
+        return (get_thread_info)() ? true : false;
341
+    }
342
+    bool thread::join_noexcept()
343
+    {
344
+
345
+        detail::thread_data_ptr local_thread_info=(get_thread_info)();
346
+        if(local_thread_info)
347
+        {
348
+            this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
349
+            release_handle();
350
+            return true;
351
+        }
352
+        else
353
+        {
354
+          return false;
355
+        }
356
+    }
357
+
358
+#if defined BOOST_THREAD_USES_DATETIME
359
+    bool thread::timed_join(boost::system_time const& wait_until)
360
+    {
361
+      return do_try_join_until(get_milliseconds_until(wait_until));
362
+    }
363
+#endif
364
+    bool thread::do_try_join_until_noexcept(uintmax_t milli, bool& res)
365
+    {
366
+      detail::thread_data_ptr local_thread_info=(get_thread_info)();
367
+      if(local_thread_info)
368
+      {
369
+          if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli))
370
+          {
371
+            res=false;
372
+            return true;
373
+          }
374
+          release_handle();
375
+          res=true;
376
+          return true;
377
+      }
378
+      else
379
+      {
380
+        return false;
381
+      }
382
+    }
383
+
384
+    void thread::detach()
385
+    {
386
+        release_handle();
387
+    }
388
+
389
+    void thread::release_handle()
390
+    {
391
+        thread_info=0;
392
+    }
393
+
394
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
395
+    void thread::interrupt()
396
+    {
397
+        detail::thread_data_ptr local_thread_info=(get_thread_info)();
398
+        if(local_thread_info)
399
+        {
400
+            local_thread_info->interrupt();
401
+        }
402
+    }
403
+
404
+    bool thread::interruption_requested() const BOOST_NOEXCEPT
405
+    {
406
+        detail::thread_data_ptr local_thread_info=(get_thread_info)();
407
+        return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
408
+    }
409
+
410
+    unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
411
+    {
412
+        //SYSTEM_INFO info={{0}};
413
+        SYSTEM_INFO info;
414
+        GetSystemInfo(&info);
415
+        return info.dwNumberOfProcessors;
416
+    }
417
+#endif
418
+
419
+    thread::native_handle_type thread::native_handle()
420
+    {
421
+        detail::thread_data_ptr local_thread_info=(get_thread_info)();
422
+        return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value;
423
+    }
424
+
425
+    detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
426
+    {
427
+        return thread_info;
428
+    }
429
+
430
+    namespace this_thread
431
+    {
432
+        namespace
433
+        {
434
+            LARGE_INTEGER get_due_time(detail::timeout const&  target_time)
435
+            {
436
+                LARGE_INTEGER due_time={{0,0}};
437
+                if(target_time.relative)
438
+                {
439
+                    unsigned long const elapsed_milliseconds=detail::win32::GetTickCount64()-target_time.start;
440
+                    LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds);
441
+                    LONGLONG const hundred_nanoseconds_in_one_millisecond=10000;
442
+
443
+                    if(remaining_milliseconds>0)
444
+                    {
445
+                        due_time.QuadPart=-(remaining_milliseconds*hundred_nanoseconds_in_one_millisecond);
446
+                    }
447
+                }
448
+                else
449
+                {
450
+                    SYSTEMTIME target_system_time={0,0,0,0,0,0,0,0};
451
+                    target_system_time.wYear=target_time.abs_time.date().year();
452
+                    target_system_time.wMonth=target_time.abs_time.date().month();
453
+                    target_system_time.wDay=target_time.abs_time.date().day();
454
+                    target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours();
455
+                    target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes();
456
+                    target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds();
457
+
458
+                    if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time)))
459
+                    {
460
+                        due_time.QuadPart=0;
461
+                    }
462
+                    else
463
+                    {
464
+                        long const hundred_nanoseconds_in_one_second=10000000;
465
+                        posix_time::time_duration::tick_type const ticks_per_second=
466
+                            target_time.abs_time.time_of_day().ticks_per_second();
467
+                        if(ticks_per_second>hundred_nanoseconds_in_one_second)
468
+                        {
469
+                            posix_time::time_duration::tick_type const
470
+                                ticks_per_hundred_nanoseconds=
471
+                                ticks_per_second/hundred_nanoseconds_in_one_second;
472
+                            due_time.QuadPart+=
473
+                                target_time.abs_time.time_of_day().fractional_seconds()/
474
+                                ticks_per_hundred_nanoseconds;
475
+                        }
476
+                        else
477
+                        {
478
+                            due_time.QuadPart+=
479
+                                target_time.abs_time.time_of_day().fractional_seconds()*
480
+                                (hundred_nanoseconds_in_one_second/ticks_per_second);
481
+                        }
482
+                    }
483
+                }
484
+                return due_time;
485
+            }
486
+        }
487
+
488
+
489
+        bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
490
+        {
491
+            detail::win32::handle handles[3]={0};
492
+            unsigned handle_count=0;
493
+            unsigned wait_handle_index=~0U;
494
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
495
+            unsigned interruption_index=~0U;
496
+#endif
497
+            unsigned timeout_index=~0U;
498
+            if(handle_to_wait_for!=detail::win32::invalid_handle_value)
499
+            {
500
+                wait_handle_index=handle_count;
501
+                handles[handle_count++]=handle_to_wait_for;
502
+            }
503
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
504
+            if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled)
505
+            {
506
+                interruption_index=handle_count;
507
+                handles[handle_count++]=detail::get_current_thread_data()->interruption_handle;
508
+            }
509
+#endif
510
+            detail::win32::handle_manager timer_handle;
511
+
512
+#ifndef UNDER_CE
513
+            unsigned const min_timer_wait_period=20;
514
+
515
+            if(!target_time.is_sentinel())
516
+            {
517
+                detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
518
+                if(time_left.milliseconds > min_timer_wait_period)
519
+                {
520
+                    // for a long-enough timeout, use a waitable timer (which tracks clock changes)
521
+                    timer_handle=CreateWaitableTimer(NULL,false,NULL);
522
+                    if(timer_handle!=0)
523
+                    {
524
+                        LARGE_INTEGER due_time=get_due_time(target_time);
525
+
526
+                        bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
527
+                        if(set_time_succeeded)
528
+                        {
529
+                            timeout_index=handle_count;
530
+                            handles[handle_count++]=timer_handle;
531
+                        }
532
+                    }
533
+                }
534
+                else if(!target_time.relative)
535
+                {
536
+                    // convert short absolute-time timeouts into relative ones, so we don't race against clock changes
537
+                    target_time=detail::timeout(time_left.milliseconds);
538
+                }
539
+            }
540
+#endif
541
+
542
+            bool const using_timer=timeout_index!=~0u;
543
+            detail::timeout::remaining_time time_left(0);
544
+
545
+            do
546
+            {
547
+                if(!using_timer)
548
+                {
549
+                    time_left=target_time.remaining_milliseconds();
550
+                }
551
+
552
+                if(handle_count)
553
+                {
554
+                    unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds);
555
+                    if(notified_index<handle_count)
556
+                    {
557
+                        if(notified_index==wait_handle_index)
558
+                        {
559
+                            return true;
560
+                        }
561
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
562
+                        else if(notified_index==interruption_index)
563
+                        {
564
+                            detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
565
+                            throw thread_interrupted();
566
+                        }
567
+#endif
568
+                        else if(notified_index==timeout_index)
569
+                        {
570
+                            return false;
571
+                        }
572
+                    }
573
+                }
574
+                else
575
+                {
576
+                    detail::win32::Sleep(time_left.milliseconds);
577
+                }
578
+                if(target_time.relative)
579
+                {
580
+                    target_time.milliseconds-=detail::timeout::max_non_infinite_wait;
581
+                }
582
+            }
583
+            while(time_left.more);
584
+            return false;
585
+        }
586
+
587
+        thread::id get_id() BOOST_NOEXCEPT
588
+        {
589
+        #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
590
+          return detail::win32::GetCurrentThreadId();
591
+        #else
592
+            return thread::id(get_or_make_current_thread_data());
593
+        #endif
594
+        }
595
+
596
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
597
+        void interruption_point()
598
+        {
599
+            if(interruption_enabled() && interruption_requested())
600
+            {
601
+                detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
602
+                throw thread_interrupted();
603
+            }
604
+        }
605
+
606
+        bool interruption_enabled() BOOST_NOEXCEPT
607
+        {
608
+            return detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled;
609
+        }
610
+
611
+        bool interruption_requested() BOOST_NOEXCEPT
612
+        {
613
+            return detail::get_current_thread_data() && (detail::win32::WaitForSingleObject(detail::get_current_thread_data()->interruption_handle,0)==0);
614
+        }
615
+#endif
616
+
617
+        void yield() BOOST_NOEXCEPT
618
+        {
619
+            detail::win32::Sleep(0);
620
+        }
621
+
622
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
623
+        disable_interruption::disable_interruption() BOOST_NOEXCEPT:
624
+            interruption_was_enabled(interruption_enabled())
625
+        {
626
+            if(interruption_was_enabled)
627
+            {
628
+                detail::get_current_thread_data()->interruption_enabled=false;
629
+            }
630
+        }
631
+
632
+        disable_interruption::~disable_interruption() BOOST_NOEXCEPT
633
+        {
634
+            if(detail::get_current_thread_data())
635
+            {
636
+                detail::get_current_thread_data()->interruption_enabled=interruption_was_enabled;
637
+            }
638
+        }
639
+
640
+        restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
641
+        {
642
+            if(d.interruption_was_enabled)
643
+            {
644
+                detail::get_current_thread_data()->interruption_enabled=true;
645
+            }
646
+        }
647
+
648
+        restore_interruption::~restore_interruption() BOOST_NOEXCEPT
649
+        {
650
+            if(detail::get_current_thread_data())
651
+            {
652
+                detail::get_current_thread_data()->interruption_enabled=false;
653
+            }
654
+        }
655
+#endif
656
+    }
657
+
658
+    namespace detail
659
+    {
660
+        void add_thread_exit_function(thread_exit_function_base* func)
661
+        {
662
+            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
663
+            thread_exit_callback_node* const new_node=
664
+                heap_new<thread_exit_callback_node>(
665
+                    func,current_thread_data->thread_exit_callbacks);
666
+            current_thread_data->thread_exit_callbacks=new_node;
667
+        }
668
+
669
+        tss_data_node* find_tss_data(void const* key)
670
+        {
671
+            detail::thread_data_base* const current_thread_data(get_current_thread_data());
672
+            if(current_thread_data)
673
+            {
674
+                std::map<void const*,tss_data_node>::iterator current_node=
675
+                    current_thread_data->tss_data.find(key);
676
+                if(current_node!=current_thread_data->tss_data.end())
677
+                {
678
+                    return &current_node->second;
679
+                }
680
+            }
681
+            return NULL;
682
+        }
683
+
684
+        void* get_tss_data(void const* key)
685
+        {
686
+            if(tss_data_node* const current_node=find_tss_data(key))
687
+            {
688
+                return current_node->value;
689
+            }
690
+            return NULL;
691
+        }
692
+
693
+        void add_new_tss_node(void const* key,
694
+                              boost::shared_ptr<tss_cleanup_function> func,
695
+                              void* tss_data)
696
+        {
697
+            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
698
+            current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data)));
699
+        }
700
+
701
+        void erase_tss_node(void const* key)
702
+        {
703
+            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
704
+            current_thread_data->tss_data.erase(key);
705
+        }
706
+
707
+        void set_tss_data(void const* key,
708
+                          boost::shared_ptr<tss_cleanup_function> func,
709
+                          void* tss_data,bool cleanup_existing)
710
+        {
711
+            if(tss_data_node* const current_node=find_tss_data(key))
712
+            {
713
+                if(cleanup_existing && current_node->func && (current_node->value!=0))
714
+                {
715
+                    (*current_node->func)(current_node->value);
716
+                }
717
+                if(func || (tss_data!=0))
718
+                {
719
+                    current_node->func=func;
720
+                    current_node->value=tss_data;
721
+                }
722
+                else
723
+                {
724
+                    erase_tss_node(key);
725
+                }
726
+            }
727
+            else if(func || (tss_data!=0))
728
+            {
729
+                add_new_tss_node(key,func,tss_data);
730
+            }
731
+        }
732
+    }
733
+    BOOST_THREAD_DECL void __cdecl on_process_enter()
734
+    {}
735
+
736
+    BOOST_THREAD_DECL void __cdecl on_thread_enter()
737
+    {}
738
+
739
+    BOOST_THREAD_DECL void __cdecl on_process_exit()
740
+    {
741
+        boost::cleanup_tls_key();
742
+    }
743
+
744
+    BOOST_THREAD_DECL void __cdecl on_thread_exit()
745
+    {
746
+        boost::run_thread_exit_callbacks();
747
+    }
748
+
749
+    BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
750
+    {
751
+      detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
752
+      if(current_thread_data)
753
+      {
754
+        current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
755
+      }
756
+    }
757
+//namespace detail {
758
+//
759
+//    void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
760
+//    {
761
+//      detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
762
+//      if(current_thread_data)
763
+//      {
764
+//        current_thread_data->make_ready_at_thread_exit(as);
765
+//      }
766
+//    }
767
+//}
768
+}
769
+
0 770
new file mode 100644
... ...
@@ -0,0 +1,130 @@
1
+// Copyright (C) 2001-2003
2
+// William E. Kempf
3
+//
4
+//  Distributed under the Boost Software License, Version 1.0. (See accompanying 
5
+//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+// boostinspect:nounnamed
8
+
9
+namespace {
10
+const int MILLISECONDS_PER_SECOND = 1000;
11
+const int NANOSECONDS_PER_SECOND = 1000000000;
12
+const int NANOSECONDS_PER_MILLISECOND = 1000000;
13
+
14
+const int MICROSECONDS_PER_SECOND = 1000000;
15
+const int NANOSECONDS_PER_MICROSECOND = 1000;
16
+
17
+inline void to_time(int milliseconds, boost::xtime& xt)
18
+{
19
+    int res = 0;
20
+    res = boost::xtime_get(&xt, boost::TIME_UTC_);
21
+    assert(res == boost::TIME_UTC_);
22
+
23
+    xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
24
+    xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
25
+        NANOSECONDS_PER_MILLISECOND);
26
+
27
+    if (xt.nsec >= NANOSECONDS_PER_SECOND)
28
+    {
29
+        ++xt.sec;
30
+        xt.nsec -= NANOSECONDS_PER_SECOND;
31
+    }
32
+}
33
+
34
+#if defined(BOOST_HAS_PTHREADS)
35
+inline void to_timespec(const boost::xtime& xt, timespec& ts)
36
+{
37
+    ts.tv_sec = static_cast<int>(xt.sec);
38
+    ts.tv_nsec = static_cast<int>(xt.nsec);
39
+    if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
40
+    {
41
+        ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
42
+        ts.tv_nsec %= NANOSECONDS_PER_SECOND;
43
+    }
44
+}
45
+
46
+inline void to_time(int milliseconds, timespec& ts)
47
+{
48
+    boost::xtime xt;
49
+    to_time(milliseconds, xt);
50
+    to_timespec(xt, ts);
51
+}
52
+
53
+inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
54
+{
55
+    boost::xtime cur;
56
+    int res = 0;
57
+    res = boost::xtime_get(&cur, boost::TIME_UTC_);
58
+    assert(res == boost::TIME_UTC_);
59
+
60
+    if (boost::xtime_cmp(xt, cur) <= 0)
61
+    {
62
+        ts.tv_sec = 0;
63
+        ts.tv_nsec = 0;
64
+    }
65
+    else
66
+    {
67
+        ts.tv_sec = xt.sec - cur.sec;
68
+        ts.tv_nsec = xt.nsec - cur.nsec;
69
+
70
+        if( ts.tv_nsec < 0 )
71
+        {
72
+            ts.tv_sec -= 1;
73
+            ts.tv_nsec += NANOSECONDS_PER_SECOND;
74
+        }
75
+        if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
76
+        {
77
+            ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
78
+            ts.tv_nsec %= NANOSECONDS_PER_SECOND;
79
+        }
80
+    }
81
+}
82
+#endif
83
+
84
+inline void to_duration(boost::xtime xt, int& milliseconds)
85
+{
86
+    boost::xtime cur;
87
+    int res = 0;
88
+    res = boost::xtime_get(&cur, boost::TIME_UTC_);
89
+    assert(res == boost::TIME_UTC_);
90
+
91
+    if (boost::xtime_cmp(xt, cur) <= 0)
92
+        milliseconds = 0;
93
+    else
94
+    {
95
+        if (cur.nsec > xt.nsec)
96
+        {
97
+            xt.nsec += NANOSECONDS_PER_SECOND;
98
+            --xt.sec;
99
+        }
100
+        milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
101
+            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
102
+                NANOSECONDS_PER_MILLISECOND);
103
+    }
104
+}
105
+
106
+inline void to_microduration(boost::xtime xt, int& microseconds)
107
+{
108
+    boost::xtime cur;
109
+    int res = 0;
110
+    res = boost::xtime_get(&cur, boost::TIME_UTC_);
111
+    assert(res == boost::TIME_UTC_);
112
+
113
+    if (boost::xtime_cmp(xt, cur) <= 0)
114
+        microseconds = 0;
115
+    else
116
+    {
117
+        if (cur.nsec > xt.nsec)
118
+        {
119
+            xt.nsec += NANOSECONDS_PER_SECOND;