Revision: 424
http://proteowizard.svn.sourceforge.net/proteowizard/?rev=424&view=rev
Author: chambm
Date: 2008-10-14 22:27:18 +0000 (Tue, 14 Oct 2008)
Log Message:
-----------
- refactored sloppy (and broken) thread safety code in AminoAcid, Chemistry, and Peptide to use thread_specific_singleton
- added thread safety unit testing using boost::thread
- changed AminoAcid and Peptide unit tests to use average masses based on NIST/Unimod atomic weights
- changed unit_assert_equal to allow equality to epsilon (to support epsilon values of 0)
Modified Paths:
--------------
trunk/pwiz/pwiz/utility/misc/unit.hpp
trunk/pwiz/pwiz/utility/proteome/AminoAcid.cpp
trunk/pwiz/pwiz/utility/proteome/AminoAcid.hpp
trunk/pwiz/pwiz/utility/proteome/AminoAcidTest.cpp
trunk/pwiz/pwiz/utility/proteome/Chemistry.cpp
trunk/pwiz/pwiz/utility/proteome/Chemistry.hpp
trunk/pwiz/pwiz/utility/proteome/ChemistryTest.cpp
trunk/pwiz/pwiz/utility/proteome/Digestion.cpp
trunk/pwiz/pwiz/utility/proteome/Peptide.cpp
trunk/pwiz/pwiz/utility/proteome/PeptideTest.cpp
Modified: trunk/pwiz/pwiz/utility/misc/unit.hpp
===================================================================
--- trunk/pwiz/pwiz/utility/misc/unit.hpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/misc/unit.hpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -66,7 +66,7 @@
#define unit_assert_equal(x, y, epsilon) \
- (!(fabs((x)-(y)) < (epsilon)) ? throw std::runtime_error(unit_assert_equal_message(__FILE__, __LINE__, (x), (y), (epsilon))) : 0)
+ (!(fabs((x)-(y)) <= (epsilon)) ? throw std::runtime_error(unit_assert_equal_message(__FILE__, __LINE__, (x), (y), (epsilon))) : 0)
#define unit_assert_matrices_equal(A, B, epsilon) \
Modified: trunk/pwiz/pwiz/utility/proteome/AminoAcid.cpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/AminoAcid.cpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/AminoAcid.cpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -119,6 +119,7 @@
PWIZ_API_DECL Info::Info() : impl_(new Impl) {}
+PWIZ_API_DECL Info::Info(boost::restricted) : impl_(new Impl) {}
PWIZ_API_DECL Info::~Info() {} // automatic destruction of impl_
PWIZ_API_DECL const Info::Record& Info::operator[](Type type) const {return impl_->record(type);}
Modified: trunk/pwiz/pwiz/utility/proteome/AminoAcid.hpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/AminoAcid.hpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/AminoAcid.hpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -29,6 +29,7 @@
#include "Chemistry.hpp"
#include <string>
#include <memory>
+#include "boost/utility/thread_specific_singleton.hpp"
namespace pwiz {
@@ -69,13 +70,15 @@
/// class for accessing information about the amino acids
-class PWIZ_API_DECL Info
+class PWIZ_API_DECL Info : public boost::thread_specific_singleton<Info>
{
public:
Info();
~Info();
+ Info(boost::restricted);
+
/// struct for holding data for a single amino acid
struct Record
{
Modified: trunk/pwiz/pwiz/utility/proteome/AminoAcidTest.cpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/AminoAcidTest.cpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/AminoAcidTest.cpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -28,11 +28,14 @@
#include <stdexcept>
#include <functional>
#include <algorithm>
+#include "boost/thread/thread.hpp"
+#include "boost/thread/barrier.hpp"
using namespace std;
using namespace pwiz::util;
using namespace pwiz::proteome;
+using namespace pwiz::proteome::Chemistry;
using namespace pwiz::proteome::Chemistry::Element;
using namespace pwiz::proteome::AminoAcid;
@@ -50,16 +53,16 @@
{
if (!os) return;
- Chemistry::Formula residueFormula = record.formula;
-
*os << record.symbol << ": "
<< setw(14) << record.name << " "
<< setw(11) << record.formula << " "
<< setprecision(3)
<< setw(5) << record.abundance << " "
- << fixed
- << setw(7) << record.formula.monoisotopicMass() << " "
- << setw(7) << residueFormula.monoisotopicMass() << endl;
+ << fixed << setprecision(6)
+ << setw(10) << record.formula.monoisotopicMass() << " "
+ << setw(10) << record.formula.molecularWeight() << " "
+ << setw(10) << record.residueFormula.monoisotopicMass() << " "
+ << setw(10) << record.residueFormula.molecularWeight() << endl;
}
@@ -70,31 +73,32 @@
char symbol;
};
+// masses copied from http://www.unimod.org/xml/unimod.xml
TestAminoAcid testAminoAcids[] =
{
- { 71.03711, 71.07880, 'A' }, // Alanine
- { 103.0092, 103.1388, 'C' }, // Cysteine
- { 115.0269, 115.0886, 'D' }, // Aspartic acid
- { 129.0426, 129.1155, 'E' }, // Glutamic acid
- { 147.0684, 147.1766, 'F' }, // Phenylalanine
- { 57.02146, 57.05190, 'G' }, // Glycine
- { 137.0589, 137.1411, 'H' }, // Histidine
- { 113.0841, 113.1594, 'I' }, // Isoleucine
- { 128.0949, 128.1741, 'K' }, // Lysine
- { 113.0841, 113.1594, 'L' }, // Leucine
- { 131.0405, 131.1926, 'M' }, // Methionine
- { 114.0429, 114.1038, 'N' }, // Asparagine
- { 97.05276, 97.11670, 'P' }, // Proline
- { 128.0586, 128.1307, 'Q' }, // Glutamine
- { 156.1011, 156.1875, 'R' }, // Arginine
- { 87.03203, 87.07820, 'S' }, // Serine
- { 101.0477, 101.1051, 'T' }, // Threonine
- { 186.0793, 186.2132, 'W' }, // Tryptophan
- { 163.0633, 163.1760, 'Y' }, // Tyrosine
- { 99.06841, 99.13260, 'V' }, // Valine
- { 114.0429, 114.1038, 'B' }, // AspX
- { 128.0586, 128.1307, 'Z' }, // GlutX
- { 114.0919, 114.1674, 'X' } // Unknown (Averagine)
+ { 71.0371140, 71.07790, 'A' }, // Alanine
+ { 156.101111, 156.1857, 'R' }, // Arginine
+ { 114.042927, 114.1026, 'N' }, // Asparagine
+ { 115.026943, 115.0874, 'D' }, // Aspartic acid
+ { 103.009185, 103.1429, 'C' }, // Cysteine
+ { 129.042593, 129.1140, 'E' }, // Glutamic acid
+ { 128.058578, 128.1292, 'Q' }, // Glutamine
+ { 57.0214640, 57.05130, 'G' }, // Glycine
+ { 137.058912, 137.1393, 'H' }, // Histidine
+ { 113.084064, 113.1576, 'I' }, // Isoleucine
+ { 113.084064, 113.1576, 'L' }, // Leucine
+ { 128.094963, 128.1723, 'K' }, // Lysine
+ { 131.040485, 131.1961, 'M' }, // Methionine
+ { 147.068414, 147.1739, 'F' }, // Phenylalanine
+ { 97.0527640, 97.11520, 'P' }, // Proline
+ { 87.0320280, 87.07730, 'S' }, // Serine
+ { 101.047679, 101.1039, 'T' }, // Threonine
+ { 186.079313, 186.2099, 'W' }, // Tryptophan
+ { 163.063329, 163.1733, 'Y' }, // Tyrosine
+ { 99.0684140, 99.13110, 'V' }, // Valine
+ { 114.042927, 114.1026, 'B' }, // AspX
+ { 128.058578, 128.1292, 'Z' }, // GlutX
+ { 114.091900, 114.1674, 'X' } // Unknown (Averagine)
};
@@ -102,6 +106,24 @@
{
AminoAcid::Info info;
+ // get a copy of all the records
+
+ vector<AminoAcid::Info::Record> records;
+
+ for (char symbol='A'; symbol<='Z'; symbol++)
+ {
+ try
+ {
+ const AminoAcid::Info::Record& record = info[symbol];
+ records.push_back(record);
+ }
+ catch (exception&)
+ {}
+ }
+
+ for (vector<AminoAcid::Info::Record>::iterator it=records.begin(); it!=records.end(); ++it)
+ printRecord(os_, *it);
+
unit_assert(info[Alanine].residueFormula[C] == 3);
unit_assert(info[Alanine].residueFormula[H] == 5);
unit_assert(info[Alanine].residueFormula[N] == 1);
@@ -120,8 +142,8 @@
{
TestAminoAcid& aa = testAminoAcids[i];
Chemistry::Formula residueFormula = info[aa.symbol].residueFormula;
- unit_assert_equal(residueFormula.monoisotopicMass(), aa.monoMass, 0.01);
- unit_assert_equal(residueFormula.molecularWeight(), aa.avgMass, 0.01);
+ unit_assert_equal(residueFormula.monoisotopicMass(), aa.monoMass, 0.00001);
+ unit_assert_equal(residueFormula.molecularWeight(), aa.avgMass, 0.0001);
//set<char> mmNames = mm2n.getNames(aa.monoMass, EPSILON);
//set<char> amNames = am2n.getNames(aa.avgMass, EPSILON);
//unit_assert(mmNames.count(aa.symbol) > 0);
@@ -129,21 +151,6 @@
}
- // get a copy of all the records
-
- vector<AminoAcid::Info::Record> records;
-
- for (char symbol='A'; symbol<='Z'; symbol++)
- {
- try
- {
- const AminoAcid::Info::Record& record = info[symbol];
- records.push_back(record);
- }
- catch (exception&)
- {}
- }
-
// compute some averages
double averageMonoisotopicMass = 0;
@@ -156,7 +163,6 @@
for (vector<AminoAcid::Info::Record>::iterator it=records.begin(); it!=records.end(); ++it)
{
const AminoAcid::Info::Record& record = *it;
- printRecord(os_, record);
Chemistry::Formula residueFormula = record.residueFormula;
averageMonoisotopicMass += residueFormula.monoisotopicMass() * record.abundance;
@@ -186,6 +192,29 @@
}
+void testThreadSafetyWorker(boost::barrier* testBarrier)
+{
+ testBarrier->wait(); // wait until all threads have started
+
+ // test thread-specific singleton access with instance
+ unit_assert(AminoAcid::Info::instance->operator[](Glycine).symbol == 'G');
+
+ // test thread-specific singleton access with lease
+ AminoAcid::Info::lease info;
+ unit_assert(info->operator[](Glycine).symbol == 'G');
+}
+
+void testThreadSafety()
+{
+ const int testThreadCount = 100;
+ boost::barrier testBarrier(testThreadCount);
+ boost::thread_group testThreadGroup;
+ for (int i=0; i < testThreadCount; ++i)
+ testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier));
+ testThreadGroup.join_all();
+}
+
+
int main(int argc, char* argv[])
{
try
@@ -193,6 +222,7 @@
if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout;
if (os_) *os_ << "AminoAcidTest\n";
test();
+ testThreadSafety();
return 0;
}
catch (exception& e)
Modified: trunk/pwiz/pwiz/utility/proteome/Chemistry.cpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/Chemistry.cpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/Chemistry.cpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -35,6 +35,7 @@
#include "utility/misc/String.hpp"
#include "boost/thread/tss.hpp"
+//extern "C" void tss_cleanup_implemented() {} // workaround for TSS linker error?
using namespace std;
@@ -88,55 +89,45 @@
const Info::Record& record(Type type) const;
private:
- // keep only one copy of the data per thread
- static boost::thread_specific_ptr< vector<Record> > data_;
+ vector<Record> data_;
void initializeData();
};
Info::Impl::Impl()
{
+ //cout << "[Chemistry::Element::Info::initialize()]" << endl;
initializeData();
}
-
const Info::Record& Info::Impl::record(Type type) const
{
- if (data_->size() < size_t(type))
+ if (data_.size() <= size_t(type))
throw runtime_error("[Chemistry::Element::Info::Impl::record()] Record not found.");
- return (*data_)[type];
+ return data_[type];
}
-
-boost::thread_specific_ptr< vector<Info::Record> > Info::Impl::data_;
-
-
void Info::Impl::initializeData()
{
- if (!data_.get())
- {
- data_.reset(new vector<Info::Record>);
+ // iterate through the ChemistryData array and put it in our own data structure
+ ChemistryData::Element* it = ChemistryData::elements();
+ ChemistryData::Element* end = ChemistryData::elements() + ChemistryData::elementsSize();
- // iterate through the ChemistryData array and put it in our own data structure
- ChemistryData::Element* it = ChemistryData::elements();
- ChemistryData::Element* end = ChemistryData::elements() + ChemistryData::elementsSize();
+ data_.resize(ChemistryData::elementsSize());
- data_->resize(ChemistryData::elementsSize());
+ for (; it!=end; ++it)
+ {
+ Info::Record record;
+ record.type = it->type;
+ record.symbol = it->symbol;
+ record.atomicNumber = it->atomicNumber;
+ record.atomicWeight = it->atomicWeight;
+
+ for (ChemistryData::Isotope* p=it->isotopes; p<it->isotopes+it->isotopesSize; ++p)
+ record.isotopes.push_back(MassAbundance(p->mass, p->abundance));
- for (; it!=end; ++it)
- {
- Info::Record record;
- record.type = it->type;
- record.symbol = it->symbol;
- record.atomicNumber = it->atomicNumber;
- record.atomicWeight = it->atomicWeight;
-
- for (ChemistryData::Isotope* p=it->isotopes; p<it->isotopes+it->isotopesSize; ++p)
- record.isotopes.push_back(MassAbundance(p->mass, p->abundance));
-
- (*data_)[it->type] = record;
- }
+ data_[it->type] = record;
}
}
@@ -144,6 +135,7 @@
// Info implementation
PWIZ_API_DECL Info::Info() : impl_(new Impl) {}
+PWIZ_API_DECL Info::Info(boost::restricted) : impl_(new Impl) {}
PWIZ_API_DECL Info::~Info() {} // auto destruction of impl_
PWIZ_API_DECL const Info::Record& Info::operator[](Type type) const {return impl_->record(type);}
@@ -191,8 +183,6 @@
class Formula::Impl
{
- static auto_ptr<Element::Info> info_;
-
public:
Impl(const string& formula);
@@ -201,7 +191,7 @@
{
if (dirty)
{
- Element::Info& info = *info_;
+ Element::Info::lease info;
dirty = false;
monoMass = avgMass = 0;
@@ -210,7 +200,7 @@
int count = CHONSP_data[i];
if (count != 0)
{
- const Element::Info::Record& r = info[Element::Type(i)];
+ const Element::Info::Record& r = info->operator[](Element::Type(i));
if (!r.isotopes.empty())
monoMass += r.isotopes[0].mass * count;
avgMass += r.atomicWeight * count;
@@ -219,7 +209,7 @@
for (Data::const_iterator it=data.begin(); it!=data.end(); ++it)
{
- const Element::Info::Record& r = info[it->first];
+ const Element::Info::Record& r = info->operator[](it->first);
if (!r.isotopes.empty())
monoMass += r.isotopes[0].mass * it->second;
avgMass += r.atomicWeight * it->second;
@@ -235,7 +225,6 @@
bool dirty; // true if masses need updating
};
-auto_ptr<Element::Info> Formula::Impl::info_;
Formula::Impl::Impl(const string& formula)
: monoMass(0), avgMass(0), dirty(false)
@@ -254,8 +243,7 @@
const string& digits_ = "-0123456789";
const string& letters_ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (!info_.get()) info_.reset(new Element::Info);
- Element::Info& info = *info_;
+ Element::Info::lease info;
string::size_type index = 0;
while (index < formula.size())
@@ -287,7 +275,7 @@
index = formula.find_first_not_of(whitespace_, indexCountEnd);
- const Element::Info::Record& r = info[type];
+ const Element::Info::Record& r = info->operator[](type);
if (!r.isotopes.empty())
monoMass += r.isotopes[0].mass * count;
avgMass += r.atomicWeight * count;
Modified: trunk/pwiz/pwiz/utility/proteome/Chemistry.hpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/Chemistry.hpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/Chemistry.hpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -31,6 +31,7 @@
#include <memory>
#include <vector>
#include "utility/misc/virtual_map.hpp"
+#include "boost/utility/thread_specific_singleton.hpp"
namespace pwiz {
@@ -98,13 +99,15 @@
/// class for obtaining information about elements
-class PWIZ_API_DECL Info
+class PWIZ_API_DECL Info : public boost::thread_specific_singleton<Info>
{
public:
Info();
~Info();
+ Info(boost::restricted);
+
/// structure for holding info about an element
struct Record
{
Modified: trunk/pwiz/pwiz/utility/proteome/ChemistryTest.cpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/ChemistryTest.cpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/ChemistryTest.cpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -29,11 +29,14 @@
#include <iomanip>
#include <stdexcept>
#include <iterator>
+#include "boost/thread/thread.hpp"
+#include "boost/thread/barrier.hpp"
using namespace std;
using namespace pwiz::util;
using namespace pwiz::proteome;
+using namespace Chemistry;
ostream* os_ = 0;
@@ -41,7 +44,6 @@
void testMassAbundance()
{
- using namespace Chemistry;
MassAbundance ma(1, 2);
MassAbundance ma2(1, 4);
unit_assert(ma != ma2);
@@ -60,30 +62,31 @@
const TestFormula testFormulaData[] =
{
- { "C1H2N3O4S5", 1, 2, 3, 4, 5, 279.864884, 280.374890 },
- { "C1H 2N3O4 S5", 1, 2, 3, 4, 5, 279.864884, 280.374890 },
+ { "C1H2N3O4S5", 1, 2, 3, 4, 5, 279.864884, 280.36928 },
+ { "C1H 2N3O4 S5", 1, 2, 3, 4, 5, 279.864884, 280.36928 },
{ "H-42", 0, -42, 0, 0, 0, -42.328651, -42.333512 },
- { "N2C-1", -1, 0, 2, 0, 0, 28.006148-12, 28.013486-12.010736 }
+ { "N2C-1", -1, 0, 2, 0, 0, 28.006148-12, 28.013486-12.0107 },
+ { "C39H67N11O10", 39, 67, 11, 10, 0, 849.507238, 850.01698 }
};
const int testFormulaDataSize = sizeof(testFormulaData)/sizeof(TestFormula);
void testFormula()
{
- using namespace Chemistry;
-
for (int i=0; i < testFormulaDataSize; ++i)
{
const TestFormula& testFormula = testFormulaData[i];
Formula formula(testFormula.formula);
- unit_assert(round(formula.monoisotopicMass()) == round(testFormula.monoMass));
- unit_assert(round(formula.molecularWeight()) == round(testFormula.avgMass));
+ const double EPSILON = 0.001;
+
+ unit_assert_equal(formula.monoisotopicMass(), testFormula.monoMass, EPSILON);
+ unit_assert_equal(formula.molecularWeight(), testFormula.avgMass, EPSILON);
if (os_) *os_ << formula << " " << formula.monoisotopicMass() << " " << formula.molecularWeight() << endl;
formula[Element::C] += 2;
- unit_assert(round(formula.monoisotopicMass()) == round(testFormula.monoMass+24));
- unit_assert(round(formula.molecularWeight()) == round(testFormula.avgMass+24));
+ unit_assert_equal(formula.monoisotopicMass(), testFormula.monoMass+24, EPSILON);
+ unit_assert_equal(formula.molecularWeight(), testFormula.avgMass+12.0107*2, EPSILON);
if (os_) *os_ << formula << " " << formula.monoisotopicMass() << " " << formula.molecularWeight() << endl;
//const Formula& constFormula = formula;
@@ -92,14 +95,14 @@
// test copy constructor and operator!=
Formula formula2 = formula;
formula2[Element::C] -= 2;
- unit_assert(round(formula.monoisotopicMass()) == round(testFormula.monoMass+24));
- unit_assert(round(formula2.monoisotopicMass()) == round(testFormula.monoMass));
+ unit_assert_equal(formula.monoisotopicMass(), testFormula.monoMass+24, EPSILON);
+ unit_assert_equal(formula2.monoisotopicMass(), testFormula.monoMass, EPSILON);
if (os_) *os_ << "formula: " << formula << endl;
if (os_) *os_ << "formula2: " << formula2 << endl;
// test operator= and operator==
formula2 = formula;
- unit_assert(round(formula.monoisotopicMass()) == round(formula2.monoisotopicMass()));
+ unit_assert_equal(formula.monoisotopicMass(), formula2.monoisotopicMass(), EPSILON);
if (os_) *os_ << "formula: " << formula << endl;
if (os_) *os_ << "formula2: " << formula2 << endl;
@@ -118,8 +121,7 @@
void testFormulaOperations()
{
- using namespace Chemistry;
- using namespace Element;
+ using namespace Element;
Formula water("H2O1");
Formula a("C1 H2 N3 O4 S5");
@@ -142,7 +144,6 @@
void testInfo()
{
- using namespace Chemistry;
Element::Info info;
if (os_)
@@ -156,23 +157,18 @@
void infoExample()
{
- using namespace Chemistry;
- using namespace Element;
-
- Info info;
+ Element::Info info;
if (os_)
{
- *os_ << "Sulfur isotopes: " << info[S].isotopes.size() << endl
- << info[S].isotopes;
+ *os_ << "Sulfur isotopes: " << info[Element::S].isotopes.size() << endl
+ << info[Element::S].isotopes;
}
}
void testPolysiloxane()
{
- using namespace Chemistry;
-
Formula formula("Si6C12H36O6");
if (os_)
@@ -186,6 +182,29 @@
}
+void testThreadSafetyWorker(boost::barrier* testBarrier)
+{
+ testBarrier->wait(); // wait until all threads have started
+
+ // test thread-specific singleton access with instance
+ unit_assert_equal(Element::Info::instance->operator[](Element::C).atomicNumber, 6.0, 0);
+
+ // test thread-specific singleton access with lease
+ Element::Info::lease info;
+ unit_assert_equal(info->operator[](Element::C).atomicNumber, 6.0, 0);
+}
+
+void testThreadSafety()
+{
+ const int testThreadCount = 100;
+ boost::barrier testBarrier(testThreadCount);
+ boost::thread_group testThreadGroup;
+ for (int i=0; i < testThreadCount; ++i)
+ testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier));
+ testThreadGroup.join_all();
+}
+
+
int main(int argc, char* argv[])
{
@@ -199,6 +218,7 @@
testInfo();
infoExample();
testPolysiloxane();
+ testThreadSafety();
return 0;
}
catch (exception& e)
Modified: trunk/pwiz/pwiz/utility/proteome/Digestion.cpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/Digestion.cpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/Digestion.cpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -133,13 +133,10 @@
class Digestion::Motif::Impl
{
- //static auto_ptr<AminoAcid::Info> info_;
-
public:
Impl(const string& motif)
: motif_(motif)
{
- //if (!info_.get()) info_.reset(new AminoAcid::Info);
parseMotif();
}
@@ -189,7 +186,6 @@
private:
inline void parseMotif()
{
- //AminoAcid::Info& info = *info_;
vector<char> multiResidueBlock;
int multiResidueBlockMode = 0; // 0=off 1=contained residues are included 2=contained residues are excluded
bool parsedSiteDelimiter = false;
@@ -277,9 +273,7 @@
vector<IsValidAA> cFilters_;
};
-//auto_ptr<AminoAcid::Info> Digestion::Motif::Impl::info_;
-
PWIZ_API_DECL
Digestion::Motif::Motif(const string& motif)
: impl_(new Impl(motif))
Modified: trunk/pwiz/pwiz/utility/proteome/Peptide.cpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/Peptide.cpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/Peptide.cpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -29,7 +29,7 @@
#include <iostream>
#include <climits>
#include "utility/misc/Exception.hpp"
-#include "boost/thread/tss.hpp"
+#include "boost/utility/thread_specific_singleton.hpp"
extern "C" void tss_cleanup_implemented() {} // workaround for TSS linker error?
@@ -43,8 +43,6 @@
class Peptide::Impl
{
- static boost::thread_specific_ptr<AminoAcid::Info> info_;
-
public:
Impl(Peptide* peptide, const std::string& sequence)
@@ -83,6 +81,10 @@
}
}
+ ~Impl()
+ {
+ }
+
inline const string& sequence() const
{
return sequence_;
@@ -92,7 +94,7 @@
{
const static Formula H1("H1");
const static Formula O1H1("O1H1");
- AminoAcid::Info& info = *info_;
+ AminoAcid::Info::lease info;
Formula formula;
ModificationMap::const_iterator modItr = mods_.begin();
@@ -114,7 +116,7 @@
for (size_t i=0, end=sequence_.length(); i < end; ++i)
{
- formula += info[sequence_[i]].residueFormula; // add AA residue formula
+ formula += info->operator[](sequence_[i]).residueFormula; // add AA residue formula
// add modification formulae
if (modified && modItr != mods_.end() && modItr->first == (int) i)
@@ -177,14 +179,12 @@
inline void calculateMasses()
{
- if (!info_.get()) info_.reset(new AminoAcid::Info);
Formula unmodifiedFormula = formula(false);
monoMass_ = unmodifiedFormula.monoisotopicMass();
avgMass_ = unmodifiedFormula.molecularWeight();
}
};
-boost::thread_specific_ptr<AminoAcid::Info> Peptide::Impl::info_;
PWIZ_API_DECL Peptide::Peptide(const string& sequence) : impl_(new Impl(this, sequence)) {}
PWIZ_API_DECL Peptide::Peptide(const char* sequence) : impl_(new Impl(this, sequence)) {}
@@ -258,41 +258,19 @@
{
public:
Impl(const Peptide& peptide, bool mono, bool modified)
- : NTerminalDeltaMass(0), CTerminalDeltaMass(0),
- aMass(mono ? aMonoMass : aAvgMass),
- bMass(mono ? bMonoMass : bAvgMass),
- cMass(mono ? cMonoMass : cAvgMass),
- xMass(mono ? xMonoMass : xAvgMass),
- yMass(mono ? yMonoMass : yAvgMass),
- zMass(mono ? zMonoMass : zAvgMass)
+ : NTerminalDeltaMass(0), CTerminalDeltaMass(0)
{
- if (aFormula.formula().empty())
- {
- aFormula = Formula("C-1O-1");
- bFormula = Formula(""); // proton only
- cFormula = Formula("N1H3");
- xFormula = Formula("C1O1H-2") + Formula("H2O1");
- yFormula = Formula("H2O1");
- zFormula = Formula("N-1H-3") + Formula("H2O1");
+ StaticData::lease staticData;
+ aMass = (mono ? staticData->aFormula.monoisotopicMass() : staticData->aFormula.molecularWeight());
+ bMass = (mono ? staticData->bFormula.monoisotopicMass() : staticData->bFormula.molecularWeight());
+ cMass = (mono ? staticData->cFormula.monoisotopicMass() : staticData->cFormula.molecularWeight());
+ xMass = (mono ? staticData->xFormula.monoisotopicMass() : staticData->xFormula.molecularWeight());
+ yMass = (mono ? staticData->yFormula.monoisotopicMass() : staticData->yFormula.molecularWeight());
+ zMass = (mono ? staticData->zFormula.monoisotopicMass() : staticData->zFormula.molecularWeight());
- aMonoMass = aFormula.monoisotopicMass();
- bMonoMass = bFormula.monoisotopicMass();
- cMonoMass = cFormula.monoisotopicMass();
- xMonoMass = xFormula.monoisotopicMass();
- yMonoMass = yFormula.monoisotopicMass();
- zMonoMass = zFormula.monoisotopicMass();
-
- aAvgMass = aFormula.molecularWeight();
- bAvgMass = bFormula.molecularWeight();
- cAvgMass = cFormula.molecularWeight();
- xAvgMass = xFormula.molecularWeight();
- yAvgMass = yFormula.molecularWeight();
- zAvgMass = zFormula.molecularWeight();
- }
-
const string& sequence = peptide.sequence();
maxLength = sequence.length();
- AminoAcid::Info info;
+ AminoAcid::Info::lease info;
const ModificationMap& mods = peptide.modifications();
ModificationMap::const_iterator modItr = mods.begin();
@@ -312,7 +290,7 @@
masses.resize(maxLength, 0);
for (size_t i=0, end=maxLength; i < end; ++i)
{
- const Formula& f = info[sequence[i]].residueFormula;
+ const Formula& f = info->operator[](sequence[i]).residueFormula;
mass += (mono ? f.monoisotopicMass() : f.molecularWeight());
if (modified && modItr != mods.end() && modItr->first == (int) i)
{
@@ -338,6 +316,14 @@
}
}
+ Impl(const Impl& other)
+ {
+ }
+
+ ~Impl()
+ {
+ }
+
inline double a(size_t length, size_t charge) const
{
return charge == 0 ? NTerminalDeltaMass+f(length)+aMass
@@ -382,26 +368,32 @@
double NTerminalDeltaMass;
double CTerminalDeltaMass;
- double& aMass;
- double& bMass;
- double& cMass;
- double& xMass;
- double& yMass;
- double& zMass;
+ double aMass;
+ double bMass;
+ double cMass;
+ double xMass;
+ double yMass;
+ double zMass;
- static Chemistry::Formula aFormula;
- static Chemistry::Formula bFormula;
- static Chemistry::Formula cFormula;
- static Chemistry::Formula xFormula;
- static Chemistry::Formula yFormula;
- static Chemistry::Formula zFormula;
+ struct StaticData : public boost::thread_specific_singleton<StaticData>
+ {
+ StaticData(boost::restricted)
+ {
+ aFormula = Formula("C-1O-1");
+ bFormula = Formula(""); // proton only
+ cFormula = Formula("N1H3");
+ xFormula = Formula("C1O1H-2") + Formula("H2O1");
+ yFormula = Formula("H2O1");
+ zFormula = Formula("N-1H-3") + Formula("H2O1");
+ }
- static double aMonoMass, aAvgMass;
- static double bMonoMass, bAvgMass;
- static double cMonoMass, cAvgMass;
- static double xMonoMass, xAvgMass;
- static double yMonoMass, yAvgMass;
- static double zMonoMass, zAvgMass;
+ Chemistry::Formula aFormula;
+ Chemistry::Formula bFormula;
+ Chemistry::Formula cFormula;
+ Chemistry::Formula xFormula;
+ Chemistry::Formula yFormula;
+ Chemistry::Formula zFormula;
+ };
};
PWIZ_API_DECL
@@ -419,27 +411,6 @@
PWIZ_API_DECL Fragmentation::~Fragmentation() {}
-Chemistry::Formula Fragmentation::Impl::aFormula;
-Chemistry::Formula Fragmentation::Impl::bFormula;
-Chemistry::Formula Fragmentation::Impl::cFormula;
-Chemistry::Formula Fragmentation::Impl::xFormula;
-Chemistry::Formula Fragmentation::Impl::yFormula;
-Chemistry::Formula Fragmentation::Impl::zFormula;
-
-double Fragmentation::Impl::aMonoMass;
-double Fragmentation::Impl::bMonoMass;
-double Fragmentation::Impl::cMonoMass;
-double Fragmentation::Impl::xMonoMass;
-double Fragmentation::Impl::yMonoMass;
-double Fragmentation::Impl::zMonoMass;
-
-double Fragmentation::Impl::aAvgMass;
-double Fragmentation::Impl::bAvgMass;
-double Fragmentation::Impl::cAvgMass;
-double Fragmentation::Impl::xAvgMass;
-double Fragmentation::Impl::yAvgMass;
-double Fragmentation::Impl::zAvgMass;
-
PWIZ_API_DECL double Fragmentation::a(size_t length, size_t charge) const
{
return impl_->a(length, charge);
Modified: trunk/pwiz/pwiz/utility/proteome/PeptideTest.cpp
===================================================================
--- trunk/pwiz/pwiz/utility/proteome/PeptideTest.cpp 2008-10-14 21:52:21 UTC (rev 423)
+++ trunk/pwiz/pwiz/utility/proteome/PeptideTest.cpp 2008-10-14 22:27:18 UTC (rev 424)
@@ -27,7 +27,9 @@
#include <iostream>
#include <iomanip>
#include <algorithm>
-#include "utility/misc/String.hpp"
+#include "utility/misc/String.hpp"
+#include "boost/thread/thread.hpp"
+#include "boost/thread/barrier.hpp"
using namespace std;
@@ -89,10 +91,10 @@
TestPeptide testPeptides[] =
{
- { "ELK", 388.2322, 389.24005, 195.12396, 388.4643, 389.4723, 195.2401 },
- { "DEERLICKER", 1289.6398, 1290.6477, 645.8278, 1290.4571, 1291.465, 646.2365 },
- { "ELVISLIVES", 1100.6329, 1101.6408, 551.3243, 1101.3056, 1102.3135, 551.6607 },
- { "THEQICKRWNFMPSVERTHELAYDG", 3046.4178, 3047.4257, 1524.2168, 3048.4004, 3049.4083, 1525.2082 },
+ { "ELK", 388.2322, 389.24005, 195.12396, 388.45918, 389.4665, 195.2369 },
+ { "DEERLICKER", 1289.6398, 1290.6477, 645.8278, 1290.44644, 1291.4537, 646.2305 },
+ { "ELVISLIVES", 1100.6329, 1101.6408, 551.3243, 1101.29052, 1102.2978, 551.6525 },
+ { "THEQICKRWNFMPSVERTHELAYDG", 3046.4178, 3047.4257, 1524.2168, 3048.37046, 3049.3777, 1525.1925 },
//{ "(THEQICKBRWNFXMPSVERTHELAZYDG)", 3402.5874, 3404.7792 }
};
@@ -103,7 +105,7 @@
for (size_t i=0; i < testPeptidesSize; ++i)
{
const TestPeptide& p = testPeptides[i];
- double BIG_EPSILON = 0.05;
+ double BIG_EPSILON = 0.001;
Peptide peptide(p.sequence);
if (os_) *os_ << peptide.sequence() << ": " << peptide.formula() <<
@@ -163,54 +165,54 @@
// M+16
{ "MEERKAT",
"0 0",
- 879.41205, 879.98369
+ 879.41205, 879.97844
},
// C+57
{ "THEQICKRWNFMPSVERTHELAYDG",
"1 5",
- 3103.43929, 3105.45241
+ 3103.43929, 3105.4218
},
// C+57, M+16
{ "THEQICKRWNFMPSVERTHELAYDG",
"0 11 1 5",
- 3119.43419, 3121.45181
+ 3119.43419, 3121.4212
},
// C+57, Q-17
{ "QICKRWNFMPSVERTHELAYDG",
"2 0 1 2",
- 2719.26356, 2721.06016
+ 2719.26356, 2721.0341
},
// no mods
- { "ELVISLIVES", 0, 1100.63293, 1101.30557 },
+ { "ELVISLIVES", 0, 1100.63293, 1101.29052 },
// E-17
{ "ELVISLIVES",
"3 0",
- 1083.60638, 1084.27497
+ 1083.60638, 1084.26
},
// no mods
- { "PINGPNG", 0, 667.32898, 667.71964 },
+ { "PINGPNG", 0, 667.32898, 667.7112 },
// N-17
{ "PINGPNG",
"4 2",
- 650.30243, 650.68904
+ 650.30243, 650.6807
},
//{ "(QINT)",,}, // Q-17
// no mods
- { "MISSISSIPPI", 0, 1143.62099, 1144.3918 },
+ { "MISSISSIPPI", 0, 1143.62099, 1144.3815 },
// S+80, S+80
{ "MISSISSIPPI",
"5 3 5 5",
- 1303.55365, 1304.3516
+ 1303.55365, 1304.3413
}
};
@@ -246,7 +248,7 @@
if (os_) *os_ << peptide.sequence() << ": " << peptide.monoisotopicMass() << " " << peptide.molecularWeight() << endl;
if (os_) *os_ << peptide2.sequence() << ": " << peptide2.monoisotopicMass() << " " << peptide2.molecularWeight() << endl;
- double BIG_EPSILON = 0.05;
+ double BIG_EPSILON = 0.001;
unit_assert_equal(peptide.formula(true).monoisotopicMass(), p.monoMass, BIG_EPSILON);
unit_assert_equal(peptide.formula(true).molecularWeight(), p.avgMass, BIG_EPSILON);
@@ -501,6 +503,25 @@
}
+void testThreadSafetyWorker(boost::barrier* testBarrier)
+{
+ testBarrier->wait(); // wait until all threads have started
+
+ peptideTest();
+ fragmentTest();
+}
+
+void testThreadSafety()
+{
+ const int testThreadCount = 100;
+ boost::barrier testBarrier(testThreadCount);
+ boost::thread_group testThreadGroup;
+ for (int i=0; i < testThreadCount; ++i)
+ testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier));
+ testThreadGroup.join_all();
+}
+
+
int main(int argc, char* argv[])
{
try
@@ -512,6 +533,7 @@
peptideTest();
modificationTest();
fragmentTest();
+ testThreadSafety();
return 0;
}
catch (exception& e)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|