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
... | ... |
@@ -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 |
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 |
-} |
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 ¤t_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; |
|