[Fawkes Git] branch/thofmann/syncpoint: 575 revs updated. (0.5.0-3136-g75ef4c9)

Till Hofmann hofmann at kbsg.rwth-aachen.de
Thu Apr 14 16:02:57 CEST 2016


Changes have been pushed for the project "Fawkes Robotics Software Framework".

Gitweb: http://git.fawkesrobotics.org/fawkes.git
Trac:   http://trac.fawkesrobotics.org

The branch, thofmann/syncpoint has been updated
  discards  1523e57c3a7fef6c177e0795eb24425dd78c71aa (commit)
  discards  560d38c3b0985fafd6a81cdd4b65ea48d8ce7ec2 (commit)
  discards  d4c9010c2377f6b5a535141b2e7d9d1cd8033a66 (commit)
  discards  16914f6a12f6cbd8a447126d16e5db02c911dee3 (commit)
  discards  33369ead9ab3d860e015d1a677430f93c2e9016b (commit)
  discards  f23c5414e87a1f641a331d4d79da04cf31f7bf87 (commit)
  discards  823dcc4b6169526d755a9888502e19e5197dc8e6 (commit)
  discards  3dcc5cca983a2b92fc132c967960007a286464e0 (commit)
  discards  6c65416999f89c5a2dca00e0b7276c3201ac61cf (commit)
  discards  1d68e10670eb937ee4e566b0a5c85e7ddf5305b5 (commit)
  discards  62f1ca3d44898806199c8275195f66a53b919523 (commit)
  discards  f2aa7598ce2b21ed6f07d636ad4781214a3edd60 (commit)
  discards  0a6e3d8759c7f3e0e19f1c0a0ccbc12e5441e721 (commit)
  discards  d3a3c3f8c4f473f60beb8c19b6a93a09592cf417 (commit)
  discards  d6cc08992c48b11ec28b838020999cece196cc59 (commit)
  discards  4cfb7b6ae2da7183a90287a5a382aec1682428ed (commit)
  discards  3eadbb6bb4668a4a0c117f8d88d52bba322d0e78 (commit)
  discards  3a8fe61c000bb6e4a6d91377a8d0f4f7518aa3d8 (commit)
  discards  2799cc4dfceba21ab5c899d8c9c1c10aff3ff834 (commit)
  discards  07ab97edade45b82f95b43685725632857f63368 (commit)
  discards  88871afe726ba967d84c282a2fab85090e96e1a5 (commit)
  discards  2a2ffe694d56c7a841ead1242c15dd71d15244f9 (commit)
  discards  7c660826641dc3074b1aa691d78ee8a991d5eb9a (commit)
  discards  c0f2c11810660deaa450147ada823eda5ae4ca76 (commit)
  discards  04733f8498b9be513b9f682af8668df7e3e9e458 (commit)
  discards  0559502d117222da453c2ee2aeeba8bd8448ec37 (commit)
  discards  ddb6a6eda4bf3975494a9009db485af3e50eeabc (commit)
  discards  7eeefa2164f1352edea54bee34b5ff559ca405f8 (commit)
  discards  32c086c39206bc47b2e2f4582ea17631c05aeb83 (commit)
  discards  b435ceed3106b5b9a1bdc436d37faacaee68c329 (commit)
  discards  bec4c4a859d83daf2c8796a8a4db5247f4d6298f (commit)
  discards  318f72509d5542232546a19979564b6ed0e6e10d (commit)
  discards  44343fc2b426b42318901d6da405648b91434874 (commit)
  discards  cd7335a11c35e28b6daccedeb6e675967d91f811 (commit)
  discards  01494b2d34faf608f265038b5df688f9b5758034 (commit)
  discards  73f34034d07f340752258b9c221093ff8731f278 (commit)
  discards  c63920b49f70e34946f9f7aca605b57c22e04beb (commit)
  discards  93e43c2f22169f662c234036d12a698434b4075d (commit)
  discards  5ed80bbd3e33956e875c7eb2ec9de6d76613e9e0 (commit)
  discards  2a0bd0dfbf50ecabd667b1d62c9cef8c9442e9c6 (commit)
  discards  ae603dfe9f55d93ee5330e006329befc8ea87e88 (commit)
  discards  59f2463c1df961da427102b593d86e4b10486531 (commit)
  discards  5f83da0643c9cd9c0f3779621aab7a576ca6d7c8 (commit)
  discards  1ad151504829895eed7319d6be684318ed3fb3e1 (commit)
  discards  376005aa043f7dadc8b7be5298408030c086f52b (commit)
  discards  6a3a44a246955abe188825198d78732307ba1fa8 (commit)
  discards  19c8ee00920b879dd39257b9c45a470c3017b9aa (commit)
  discards  192b0ab8e11fcdd985f0631442498aef0d7d0e0f (commit)
  discards  65dae37fe1fde15d22bb1d797fe50bf257bd8a28 (commit)
  discards  2fb5a36cc12906892639c01bfd882ceef96a99e2 (commit)
  discards  88646d7403d8905c7bd56342d408a3d53ef6e107 (commit)
  discards  23c8d35ecb4fd0d4bc2867cd6ba172ccb327379f (commit)
  discards  97e887d0e7aa91c3ee0d464298185ab943681040 (commit)
        to  75ef4c9845fb8c627a68e7c2cc1b08347031d480 (commit)
       via  adbd3195c18ccfe7b226a2bdc46c87de56e63127 (commit)
       via  2ebd7b36ae3206417a572d4ebee89101e25e2398 (commit)
       via  99bae6ef6ecf55d5a23d6e8cba5e7a398ddbd7a0 (commit)
       via  079607de1b7e1984cfaf894e681dcc4d2ce186bf (commit)
       via  538921a69e8de75af25c8c1fe668f37a24584cd1 (commit)
       via  d8c6b2fb2e4e6f1e0fb2dab22df63c7e5a36b982 (commit)
       via  e934ffeda8801a63f34b11ef7b4929d5e9242b76 (commit)
       via  d9015159e01589dbceff325c128552449547ca20 (commit)
       via  02c0acce00d0e93f58ae9f9e9e5a64eda3172dc5 (commit)
       via  2376ae52c96155c82e6baa14b80a257f27131959 (commit)
       via  92cce9b6a954673987eecb99fd2cdf94ddc4bada (commit)
       via  a17fd5fbe197492267b5ae91d3b634c7001eaedd (commit)
       via  fcf2e6e6b71683289689689aa5fc043b8cef22da (commit)
       via  d5d546f8b2d67c2688490e20cbc4aa2a86bad7a3 (commit)
       via  da417c46f10118cf7acf0fca929a639ba4efcb63 (commit)
       via  4c27def80e1cb4ef9e8886dbed0174aca621a01c (commit)
       via  a6e660a15e7d31cb69e8cab458e64b882e0753b1 (commit)
       via  231d81d17b6909f3c9d72c75377a6a556b6a3070 (commit)
       via  ca44a7c2f46539939aaeb9d84c0be65bb162bb9c (commit)
       via  52878ce9e059f6f544febde918b7b2c493498575 (commit)
       via  dfc3f07724456e3de0399e4ab419f2149e5280a6 (commit)
       via  f3e862f439fdcaf3cc635af57c1bc21730e86d93 (commit)
       via  f6843ce0bdcfec0363666adac078bcf0c50f9d65 (commit)
       via  9c4748595bcf1dd2ff16c29a847ac700eb433484 (commit)
       via  58a1459aa0627f1f3a4c23151641d0c58f8daa09 (commit)
       via  0deb47a02429b9b89c7f9a822f0f836d41574fa3 (commit)
       via  4955dbe8617900c485755cc033717da41d012c27 (commit)
       via  6ac0e185729038a9a31a65977b24eb6f0d734603 (commit)
       via  ea1c1e9213fd28f2bf202e4df35fbba3a41f3244 (commit)
       via  d4dc9370bc1b5b0f4ec9e52b887ab3a643b1a4f3 (commit)
       via  8aa12b32e483992704904082cbc90127ad7e7edc (commit)
       via  a541425382acf929c0741c19097dc875de7a17b7 (commit)
       via  73a334157ab0993a6260dec806b3ca1d57f94d86 (commit)
       via  982cfe1407c64a6893c04d9ab74ece270197e45f (commit)
       via  6defe69477d0677fff7865fcb89b4fe9c4e27dde (commit)
       via  67b8437a605e6f8d39920a550b89b2756f52382d (commit)
       via  dfd84a96c252c1572236371f5430617646b2cb4c (commit)
       via  45a094a2b22ac3fb3e2d2d81e88c31e6d6d84bc6 (commit)
       via  c56c39c8e09d40b24184240c7b96fa964e882fb3 (commit)
       via  aed0e80779cf0d53ba5c78874c71b286f99ace3e (commit)
       via  1b4992fc956b4ba02f91ba1a01c83289954a1be3 (commit)
       via  ca3bec072cdafefcb9093667906fece4446f74fe (commit)
       via  b9090fd43ee68b23d6398932f4d6a2eea1cef4e2 (commit)
       via  35a9b1dc7bcceb2aafecf44f1cdba8cc690d0693 (commit)
       via  afdd6ec79e109c2fc9c711a2e209f13b8bc43362 (commit)
       via  3580b24d60a083758234e44b2609bd477ecdc88c (commit)
       via  6a1b95656137369e110ba7a02e8095efc4a68ed7 (commit)
       via  d30b3026298b0bc6295b0dae105ae07fda32276c (commit)
       via  a6dc56681f765eab2bc9bdde06d28348837f8054 (commit)
       via  fc80185a193952af7797c28b78e3bb81d4d5b7f1 (commit)
       via  4892df65ea09d66ab57a17bb8d2e3712a2d62a12 (commit)
       via  5be9ca5fc46ebafc8c653e8845829a86a1542305 (commit)
       via  a3ed12bb4662f3eecc7f1ca044ef4d9c4c4dd801 (commit)
       via  a06118fee013af4465c122a4c77b57dc2b6f0269 (commit)
       via  14a33397eaa1f78f29677ca0921fead1368e6bd4 (commit)
       via  a95c0e28a3ee76a4e3b946199fe14b74a1494e5f (commit)
       via  b90747e6065b00e08cf69dacac71dd508fc3cd28 (commit)
       via  6eb2b9a49c1eac2460284e3ceef0db22f67b9a0e (commit)
       via  89af27634082f8c434b3a814d93be68ad2d85677 (commit)
       via  0627fb6ba1d5e3808f09c81e0634ff7b5d013e69 (commit)
       via  95a6dd89b3b882db7cb90e98994b9362dd2fc54e (commit)
       via  72e4b768ac7a642bc774bc6ac4378e1295e94d94 (commit)
       via  88f267cec2575ddf18f909ded253f73c92637211 (commit)
       via  1660419ecad2614fb0aec5973ae37dc6c4c331f4 (commit)
       via  dcc9e4f715bf8fc2491f2809e05ff0acf4964c78 (commit)
       via  5d0dffd2bb41eb0cca42b68b02ab240c7a33b662 (commit)
       via  75e1161ff5d400fec46fe4492398f06a2f00a494 (commit)
       via  636b1131e007c39178f253c166c72e973851dbc7 (commit)
       via  9c505e9571b2bfffea5b582f50dd00a7104bf698 (commit)
       via  28a5fce8ba2b4fb8eb37b59be5e23e75f83755ab (commit)
       via  b836efea761380879a25db35638efef96a4c835f (commit)
       via  7ad884aadb71b230426c01907da42fd6c282dac5 (commit)
       via  b858a46ca9d8656b3e17a7103cff9d1b1fe03360 (commit)
       via  eb87fe3cbacda84d00e87082eb5f10786b44f2ba (commit)
       via  101017a51fa90700704c5bffd79ad88fb3172a4e (commit)
       via  5f23b4c8b654a23b24a57bbeaacf27ce605a4684 (commit)
       via  fec5f1070fba43b07b2f3d461a3abdcd99491b2e (commit)
       via  b3e0fa103425325624ad6138c8e74356bb9d2978 (commit)
       via  1a280daf55afdb8190a6226e0720333f1f13109b (commit)
       via  d6b5da2311a1861ac93d3bf6cbe8adc7dca2dce3 (commit)
       via  945b06c4ecc654641cd64540a48f75ce4afbcff9 (commit)
       via  cc731368ad2d382a9aefafd3a645af58639f98a9 (commit)
       via  e84a8631e7807dd1d838cb4290425ce888976d35 (commit)
       via  027bfae50d39e00aadb7d5b2e8d68ae33e3b4486 (commit)
       via  0252049a5b872580ce051ed1ee052d7c18c22636 (commit)
       via  d47081dbf4c90c2d1c679b5fbbd8915f66646aa7 (commit)
       via  32b089a9a142eb2ade7322f796b016abc689f205 (commit)
       via  bf12c756f342a7c4e91a6e69493529382e18042e (commit)
       via  c4cf06cdf3414a69a955b4327f4329efd1616221 (commit)
       via  de2016ee260201352925473f27e23b1aef93c07c (commit)
       via  973cffc83b71096038e57a8d7eb1e553359321b9 (commit)
       via  b0b2e915f5d80b24b35ed829b8c1dfbe6b20c249 (commit)
       via  f17a36d357edf2c040ba4cf1adcdda357cc5f291 (commit)
       via  4d7e27e39d157de45c188396f0bda627b43b697e (commit)
       via  d0eaf1475556061200e77d9ef70abecd7dd09e84 (commit)
       via  980b5d153fdabca7951befd84db5870fe7aee0e0 (commit)
       via  524e0c7ab04c31f88b75bfa0c781f3885e50c90f (commit)
       via  fa2e6e7b646cad0d84fb5aeea183dfc4d39cf049 (commit)
       via  ff87641af595750bae95811e4ff92b099d251d0b (commit)
       via  bfb16c4facdfb13688bb35d1aeecafe4c6207a5a (commit)
       via  9b50e9894a61441c01b850df15a5340ebbd36fe6 (commit)
       via  99cf97b0ba21a835a2c04eec6aa810abb3407f4d (commit)
       via  fe1ed26cff879a7cfc62f28b3912419c44c72061 (commit)
       via  3e4f1eb88ae0ae3df39762f2c373b5c23be5f3ad (commit)
       via  3861b2b2b99f79004a52a6099b544a4189990274 (commit)
       via  8440f28868807b87ff3b01f6d96717f30ee48c47 (commit)
       via  6d76eede970a8b3d108abec5e7252bb00c4fe3ef (commit)
       via  793b676ac236918efa7bdce6143ff74146ee5185 (commit)
       via  0548f14c41be9e5a6ee635288895d1111e9863f5 (commit)
       via  ab4a24d4bd31a04ba270a0d17dcedd9847410b3e (commit)
       via  3ad434a2e8ad279a23442fa28620acc23a2a59d9 (commit)
       via  ccd71f7a666d07c64015a5afc31daf577e8763eb (commit)
       via  d0a2b7f34daccf6e61e0c8cf1585d1b433307e2d (commit)
       via  c9caeaf87dbd9a498ba28bf4a1f34bfb09eba467 (commit)
       via  fa6ed69d5c86af7d5ff50e57cdfef50c296eddb7 (commit)
       via  15a2c6fa03fc97b1b62db4490570457ffda0ef63 (commit)
       via  bbfe1485e20c2f537b9d6d3c8577fae436481374 (commit)
       via  8f8c0b29a753595921226e8797dfbc60fd23c951 (commit)
       via  3ab02b187e1c33f2da297a1ba990e329d675328f (commit)
       via  85bba076eebeea8bd2d2b95d4c099a2a9ec68960 (commit)
       via  2b8a4542d1b19e513874fe347b7604eb5ce9163d (commit)
       via  fd65940dfe6e70a3cfa8b8db872a94310b5a0e36 (commit)
       via  01000b84b2ed3d3fd0a22e887701e9eb44d80ef5 (commit)
       via  45f2190d578cedefed154f56b97c4040891eee05 (commit)
       via  94d8f045d3d5df09b9f52a3459f671f7f661cf88 (commit)
       via  153994eb36a9c783f3f830e85ac18f2b45786efc (commit)
       via  aa34182e37c6f7ec151414ce2fdcc92190bd319d (commit)
       via  d079f6a6e51436860cfce9687862559e414f50fd (commit)
       via  ee1b544ac631ba4778c33c7511422ab0d0dfc0b6 (commit)
       via  f8174bf8e8f7f841c96bd30d154e806bafc93db1 (commit)
       via  a41b9405292dc89362acfdf723ac8d969f756e9f (commit)
       via  4b517197ce742490b550731f26e8fbaba30f494b (commit)
       via  ecd232ca92faf98a67134776bd7175dad6270cfd (commit)
       via  f4f2f821eb66038ac5820bd22f6fe9124366ea89 (commit)
       via  f67bc4a989fc8c9309ec4d2654fcbd0d3931a59b (commit)
       via  b6a43184ad47a80ed39a7df6b08fbcb96c34729b (commit)
       via  2efe170dfea3930e4d9008cff2404200a7b87c89 (commit)
       via  eba06ac9e6042e7685588a0dbe1332e14f52f564 (commit)
       via  0912bdc9744ccb5bba852834906faebecb6ef3e4 (commit)
       via  144884f6756b3adbff0a3333df399a5d458ef25c (commit)
       via  bb45875ddaad34051162834511ea0c7b23bd8992 (commit)
       via  59d32b9ccc828c2492f573ebce7a2d7ae5c0280a (commit)
       via  e97d2473e73af4e1e75d8fc0a7f516847ddbc102 (commit)
       via  4ed92791edcfbc38b0c698ecfd23102f67c3f016 (commit)
       via  9f5977a078604a5d325ecb3a53dcaf87529b2beb (commit)
       via  7fefb2d0a99a1b3b7c219dcf06b08a80275c85e0 (commit)
       via  37805c7bba610c3894eb8fc45a3fb6dc38f54ff7 (commit)
       via  5add554fddc8e14fb0866158929a750b7b3bf5c6 (commit)
       via  4ab90c40868caf406aeb5b500a73b8c51bac4511 (commit)
       via  1d133dfe368ed2db4dd91e80ef508aacf0012ddb (commit)
       via  f4d4ca508675f46f12dc6d0394c19f04f6bb920f (commit)
       via  63fa0c3a28ecc5d650068f40c72d02cfe23c1532 (commit)
       via  70800bb6f4cd6b9c487f5f383e2193bbd0b770b2 (commit)
       via  6b28191f0fc864c07cd987e67064f3e7f4549c47 (commit)
       via  b058a6fc117a99c1da01e5fc461d1cbc8af4cc65 (commit)
       via  3e8958c65d2ffd1c4af2c89b54edf2ec9c61f625 (commit)
       via  2ab4566dfd3fb81d36d399eab1d7d951af0f42db (commit)
       via  36fe5f807bd87008b1dc5982daf0b07b5196c0cc (commit)
       via  f81eb2e2dce08775803f4bac6805225e03830cb7 (commit)
       via  9df204b424347e9eca033c9c685a006d2d4793d7 (commit)
       via  395a30283815304b5f80e975c21a0292fd27432f (commit)
       via  3bc2a57bb7033d2b5de2d85951530f46b775d68b (commit)
       via  fc6f354abe5784bb1abe471828caca91a9d7fd83 (commit)
       via  26d9f036dfb118137c9c731f27b34dcc244ccd73 (commit)
       via  ec22c8fefa8c5f8246b5745db8056273fc4f4197 (commit)
       via  73afbe66fc741e4d3781c0c9174226233bdd9650 (commit)
       via  7ffb5c29aa35d3261b131a11ca602f9d438b0a81 (commit)
       via  3556a06be49b93cbfb3b77a97636ce6d5975e317 (commit)
       via  69a776a92f515b95ff8aa3ee9766b44d7f5dec2d (commit)
       via  57dd007eab226df1d60f5aa7af980454e02849a9 (commit)
       via  7e84b02da221505199cfa413a676169cb1fde738 (commit)
       via  b4e55c4b0f68d38294b6237a79303af51e8f1fa1 (commit)
       via  fab38fdb7f2ab1868d221da4888501d787078a99 (commit)
       via  ef928eb955b6cf5577d7973db0f177fde231a24d (commit)
       via  46ca3c0035335d52077a3ca0f7cdadd70092d598 (commit)
       via  90420b82ccea6170105703bf151fd62833c9f5db (commit)
       via  d0d7ce9e7458553541d7ce87ca6fd3cda90769c4 (commit)
       via  844c187ee920943d589f8cd7ac154a008c8cd5d3 (commit)
       via  6658acd309bbece93431eb14bba702620237b386 (commit)
       via  a2208c70475057b20eec43f5fd107be1d1ad0e6d (commit)
       via  7962b51766f3eefcd89de75152cb76cdecd264ae (commit)
       via  109d3be0306349bc1ce998c530cf1d838c6df0bc (commit)
       via  1817c727bbbcaa1b0f0f0be8a7fd8760fff9704d (commit)
       via  1ecc0ff58b1632e280f0ce8dc039a81e639a49b4 (commit)
       via  b7f33af8e9900fd9ee615b008c17e6f821146f60 (commit)
       via  76189f564b35fb8eb67b8060b0db99bfa7707d9b (commit)
       via  a232b5e5ff72745ae1fcd63f44e428c2848849b5 (commit)
       via  d983be7fb9eb27f216cf1f5550b19f8c19cde71f (commit)
       via  931ff7c92306bd1ea0811ed3a60b4d941524a69f (commit)
       via  9e0909dae4ee17b83fd6881389ba6131f29693a8 (commit)
       via  89f177505ee2a9ef2d6916627f2f7f335f07b16d (commit)
       via  c48778aac5121170f0e972c22e838d86f53fc8bd (commit)
       via  d992a3b330e8c727279931a9ef911df03b01416d (commit)
       via  634455a61c2ff6542b5c1b5cc97b72c32a414e93 (commit)
       via  beb1e553dce0c235403211a5035acb6526ce1675 (commit)
       via  360017bfd1f45ecfd0a89730c793de5762d90029 (commit)
       via  6b119addb015d555b1e33a0e0694f63dac1cb10b (commit)
       via  560dfd29d96c108c40e6356ed40a3c5fd1637c85 (commit)
       via  f0aba89265053e1aef0cbc62c929d840573ed2e0 (commit)
       via  32a8c773adb81070d9e06d19f7dda5a79f533f91 (commit)
       via  b723b55c3886858c4b1f40192e2bd0ef6a6787c2 (commit)
       via  806d001c90a858876892747fa173e924f3ac35ce (commit)
       via  c9136eea9c82f964f21a0487303006d0de26774e (commit)
       via  0b2ca838282601fee0481e2d01fb2c3659eab73a (commit)
       via  32b80153c2832b85c9b33df58f725c7b209052ba (commit)
       via  f32f2d3ca3db513485a2d929d378bb0b0dc000b5 (commit)
       via  d707320febdf4d8dec0389dd6e6f325405b5aa29 (commit)
       via  ba13b5f2cfd4fa805083f84fa11267a9572dc5cd (commit)
       via  3af0e8754dc6a689a9be0e8cda4843680c29aaf5 (commit)
       via  5d5bebb6b65378863684ea8111e2188487e0a0eb (commit)
       via  d42fde12bfcc2aaeb05edc9508dfb889dad7598e (commit)
       via  5151cb40b2f01f86ad774bd52e4d407044ec8ded (commit)
       via  94e696393d53c3230f550b15e6fc7aedf8f36ac8 (commit)
       via  63474c0a585cd2f05af55b0629eaadf2a7c311fc (commit)
       via  adfe75a869a315d8449fe1024b42461537dca837 (commit)
       via  3ffa5d3159c7c4417ff606628fde73ab14f625a7 (commit)
       via  23e4fc446edb44df0770617338919ca3fd70d9a1 (commit)
       via  abd26764e9ea2bc4cc2c68a829e3628cbf674870 (commit)
       via  0da4e95759a996e0a9e7ef194bd2f97940342323 (commit)
       via  908ec4d438f316c93f1259b993b535b2def3487f (commit)
       via  fd9f734057e2fd0126546f5c40d0bc490c927536 (commit)
       via  32a4682fb1c2935fff1dd2706ae99b8e0526fb11 (commit)
       via  0d3227df3d0d3d070aa604d636bdf70d81df296f (commit)
       via  d7c2294fd04bce6bec1e945084baf2e9b7b785b1 (commit)
       via  4626be753b2e0be021ef83329bc1729ac44e206d (commit)
       via  6174f3e7aaa580d0f40d8ef4c0ded5b10a7b1104 (commit)
       via  d74716e553f040275b4c7bb5d287b633a55cf7a8 (commit)
       via  79c4525684d3f1cdd075fd26d6f0364ee55d7c82 (commit)
       via  6c374ae9fc96bd58e8fd73bf024b7f68ef241d98 (commit)
       via  fcc092bf496e0849ce2eada13feeb0c7d08698bc (commit)
       via  557a849d24cdac0368c2a5a5b37d84c2cb19e454 (commit)
       via  95e4889740591f47a96124be5a238b8983f3531b (commit)
       via  a2e3dbeb0639974afdd5b609ea15e11f138b13f2 (commit)
       via  03965f294b70cd50a1e0bbb744c0a9e691a85b58 (commit)
       via  725a1828244649479271d783a4f5af9ab95df758 (commit)
       via  6160d93f1736ae0a9d5f38166bf4b9ee9b7694fd (commit)
       via  d04740699a0dfc9b0b7bf3199259489e4fd11c5b (commit)
       via  3263c91250f9fb1e35a2ff8922898fcc6a61353e (commit)
       via  9b88afc746b3b859a82863ac7fd8ddfe7dccea26 (commit)
       via  5ec87b99557e392f626fb2a28ea592cc315dcf4f (commit)
       via  2efe9c3d666e585bfbd6ac9f6f5d404192b54688 (commit)
       via  aeeb9348501ec8ff37547800d592358fcf7fe2ba (commit)
       via  a8f8a59014f07a1bb23e073f963a6208d046ca8b (commit)
       via  5c3f9e5ca5aef109207549c276d6f49e4af56659 (commit)
       via  dd7aaceca180bbcca0d0ed54fe6df8a99f459d7d (commit)
       via  6a2ce7a636ffb30829c6117689cfdf7cd4894eca (commit)
       via  c995c94040f20189d446f134c4dc4451f408d211 (commit)
       via  8f7cc9f13a85d5fd0c2fb750db1f40848d3c8f26 (commit)
       via  3f66ec4dda0bb16c726668548691a3c0596623ae (commit)
       via  5d427dcb736dea94ba11de07666a37e718ed1917 (commit)
       via  ade1a106826f848868238ca0c4b128099b5e5ce9 (commit)
       via  6b4a71e3a72549e1f1076b8edc737e12c2742d11 (commit)
       via  6d500235f663dc984ac179185b2a8603da75a090 (commit)
       via  3e159134318847b3f4528ea2f1952a80086ef744 (commit)
       via  ad7f05d34fd0e36f665681fa37485b174a600d58 (commit)
       via  389cb581e9bcbd4d146e583baff753b92f02bbf7 (commit)
       via  473bba8e5ca06ffc155753b6283b8b1f8b645858 (commit)
       via  9de97e835145232b5c03eb9b63226242b48e2c53 (commit)
       via  d3d675716978ec2d98f127d683ed627b1e14b54b (commit)
       via  965a3abf94754cfc462e899f2d606c17d0c6aa73 (commit)
       via  77f5d1898fa0985f8927bf6248aeb5478f98252b (commit)
       via  db9b327459738b8a4b1864ac62b9ac82c9782e0e (commit)
       via  58395300d66612fbfa6ccc515a3b6e595f3af255 (commit)
       via  86c1d768b8b163b0c42e7e51ab28aedfda72eafc (commit)
       via  37e1d72ff987b7843d3e668855c5d50113cc3bbc (commit)
       via  6fae1515ec761081b9df155540f969732be1fc0a (commit)
       via  a08ba46d65a28031f2466fff93e135600cf5bc49 (commit)
       via  0d0f4b98b6c881b856292fdd0b63fd2477500d66 (commit)
       via  7419a787c6bb0553b001d06f810b127e7c6c8207 (commit)
       via  058f49bcebe9d4a21ca2c9567566019e5ef864f3 (commit)
       via  e315080136dc0c19ff29c7ccaa883fbad5680dd9 (commit)
       via  589b3182b58dbd6d658e01d255814562cafd5c44 (commit)
       via  c477527bb27ac51594f3da4665cf5b88153cda5c (commit)
       via  757722859c0cb5aeaad026e72b6f15369658f8ee (commit)
       via  6b22ce09ba3a94e703df80c0b1268dff3bc8dec3 (commit)
       via  afb5f08cbb4958a68ec77a6058ac9064935f4f19 (commit)
       via  f0603350dbb15189073f05235038ae3fc66fe4f8 (commit)
       via  18d7fbe86d567ea4621db72798e0284266a2279d (commit)
       via  217d638777d746950dc6bd29254f422e974ab0ad (commit)
       via  7339c2ec18273505d99e87f9f0ad7eb491985199 (commit)
       via  3581ce9d86872e2ea4abf25c579f9e1e9ad57747 (commit)
       via  0af92e540405f109a432c39952fa97926698d883 (commit)
       via  9096131761d72bf035fc5b3d3f089cf61778f900 (commit)
       via  6e22630aeb707bf43c9975b72561957d23cb81ab (commit)
       via  3ccd29b355f64f7bad349e81fa63351bf0610ec2 (commit)
       via  fa7954b6eefc627899af1adc4a92330d473739e4 (commit)
       via  f6ef958ca7af8add8bc7e83aaeda90d93168c1e4 (commit)
       via  6574bbdcad7f066ddd5938416879a88a2871dab3 (commit)
       via  f601db2dd87a78f3a0d77e189651d40574192b55 (commit)
       via  d5c497cdc99a3bd89e2aeafa1d4bd01b208e16de (commit)
       via  2fa05379607bf9b843318563a4c94b6bea814a29 (commit)
       via  17a8379a8de236e19f9202cdc57cef02efd85fdd (commit)
       via  842b059bae792d482c18899d197414142b24e1ea (commit)
       via  ae5db02b1f165d5622d7cc76f7e0cb4a0a07af27 (commit)
       via  fb844a3ac72b1b508f7a37cb20b109f0ef5f3dfc (commit)
       via  c98fe7b3bcc56d11386988c60d7a2f1eb02f6c28 (commit)
       via  21173cf1746b246aa038a45cfe775bb2d214ce24 (commit)
       via  2f23a1d35f1363bbfd0f087b1e09b7346ac52be1 (commit)
       via  0d35cff7a8f6bb2610950e9bc4d957fdff8f46ce (commit)
       via  6576c91976e17731a61a517ea77210cb6ec36d69 (commit)
       via  64d1df5bd88d1a6b13de1c5d3d089d13db04d8f9 (commit)
       via  736730d82320071ea0ca14904673e2d1205ab01b (commit)
       via  6cd17f8ff33fda492ed16e4a01c1dd82bed32460 (commit)
       via  890023c2626db8643b4c613c031a2b2e9c7a241e (commit)
       via  af1f09d6a6763586784d72278f3e38368f4e3410 (commit)
       via  a05d89d8d073f484fe958fb59db37ee66b91c4d9 (commit)
       via  f26d328604cfbce53a5e66ba8df87a393482264b (commit)
       via  6a0902741b31f2c1c4f916d2aa3d51a90ee6640c (commit)
       via  23a7d638118a9c57e2672f2227342b7cdcb4bc43 (commit)
       via  e7987f926359c10d9dd4bd1b976639c4303a4fda (commit)
       via  d08005576dfc534046c22399a58b94ac24d7dec1 (commit)
       via  3c0982fdb3195d0a3a006c93f91db310f95ab653 (commit)
       via  35e0bb48fd2da063955efa32453ca02d9bc07bd5 (commit)
       via  9b0969135c05be5fbe52864e10ba3c042cfef2ec (commit)
       via  889189f45c61ee1f1bef64f40a26ac6c6ea8b5d2 (commit)
       via  7503d78b390ff42e807f21374f6f4d82bdfdeeda (commit)
       via  871d2cfecc4cff794c025427fa95453c5898faaf (commit)
       via  adc0c0d1a9b5bdf76cde6335e15515d62ccf20ef (commit)
       via  78334921a667137111990b53997105d1db3fa123 (commit)
       via  1992c2cf1de7aebe5d8864aacb91021fccb8a363 (commit)
       via  be1052920d153aacff076e27a43e72711a5e7045 (commit)
       via  7d284abe20d3ef006d2f97fc226f05cc674e2f78 (commit)
       via  eea985f32b1baec9c95de848659e275d27e81896 (commit)
       via  a09d281b68787048050d9306b0cfc8ca16f6593b (commit)
       via  9c6f098f4af675cf9b89f00dab2d9d8755266c08 (commit)
       via  fd5c7dd1e49b9b0018efdac1e06e5935966ec0e7 (commit)
       via  c0338e1376b1858d74dfbfe5c26dbd3a547efff2 (commit)
       via  81b600b9ac008d12f8aad5f5ea034fb0b36db5ab (commit)
       via  e518ec0abda9142c22fc97ab19f33c9947920229 (commit)
       via  5ec483e0ac0a951f2c048332ea32bd96d0fd04b8 (commit)
       via  0863b900815a5dd94f839cc33f333e2327f46822 (commit)
       via  dce12cfe03bb9b9e41dab76405b3e0c547d15850 (commit)
       via  17deeb6c80a26e1bd44b8fef8c080a6215c79f7b (commit)
       via  d2bbd313fb0dffd1f3d1653da5d4ce363e07f67e (commit)
       via  e343a16e880ea90dded82369478fb2e512e17496 (commit)
       via  04dd049e9ea3579c8bc48971f3f3d415c5572a09 (commit)
       via  943ec03d1605fbcd5c4755791183752e0e4a6cfe (commit)
       via  f5f8d881321e765f69539ce22d821a11f65848d8 (commit)
       via  39b4b3cb9713172872b06e83726608ba83b390e4 (commit)
       via  9a8f0e6705f14dbffff984cfd13822686b588514 (commit)
       via  7c80f831932af8ed7b2726e7c12301521874565b (commit)
       via  f0717f6cac46b8e41c9e6892c77d267c6a1bb9f4 (commit)
       via  59b6161f5287a5ee626caf551aa31a073545e5b7 (commit)
       via  a632c7cd8a30e5c32e7555aaec417d2b9c0b4c2d (commit)
       via  6dee9c4e39dd6d866e223b81d66feb268dfc474b (commit)
       via  67dd319327e8002b2896154886e679fb8aab3c0a (commit)
       via  dce08271367c9d46414376ab2c6d3661ab9e71b2 (commit)
       via  90327a1646c144dedeef044e00b31fe84bcc4240 (commit)
       via  7c868566871d729075b6e29b128bf5545f573071 (commit)
       via  40ff91d33e6c333dcb52f6da9066a697b2f87305 (commit)
       via  0e176caee49c95fde26c631e8f9495b9970a5f65 (commit)
       via  b48ca7b41454e893b9bb4fb0a75341ac300b6c31 (commit)
       via  180c54f864a073fd349d38d7771d942cd28da2e6 (commit)
       via  7ad026dee67f7738f6a4da29a309b3d020d418fa (commit)
       via  d276db8b29010e91cd5eb930173b278995f84e0e (commit)
       via  ce75990ab96d18dd7c6ee5d9bab182d4533ed20b (commit)
       via  f6ff20e7688f964ba75e46f71c156d2004928ba3 (commit)
       via  765ddc70bf28d2b87fae804dff95a99e8225453b (commit)
       via  84234c8fca71707e3b72ac76ac9a5f5a2b449802 (commit)
       via  1a756b543682db9df581f7940f4b5c0375aed39e (commit)
       via  e20bbc1593e4cdc0ce9d5b708d5cbb361b9fbe85 (commit)
       via  8d30967f444946c9e9314719816cf062406f541a (commit)
       via  ecd687ad5050ef360607affe34b0379f55b8d932 (commit)
       via  6e71c367db4f3042353c345e9096170a2133f18e (commit)
       via  aa65673adac3a6e095189911627ea986fbae3580 (commit)
       via  76197b494459b3b879c0c76f6a73fdc1087d6bcb (commit)
       via  bd88964f154ad2f16cf70a8ce08a7ff3a5a7d07a (commit)
       via  0343db60348c62a6a9af6561c77bbf4889e4de7c (commit)
       via  f425dfa5c1a601ed864147d1abf14e9b00ccf012 (commit)
       via  963881abe9f43ec34660af5a86e94cbf12bf8e90 (commit)
       via  18479f95601c95a9ffb75d66ac418459a7574743 (commit)
       via  be3495d2b7a981374fa0f11051b92b44b01385a5 (commit)
       via  4e5eb57111e06eb3590cbc4139ce84cd9abfe48a (commit)
       via  ee437941093c190f35b6cce30a63731706624754 (commit)
       via  949bb0cb1ae9c0730e07882c328a98f1ec061120 (commit)
       via  e4a2e3ab2cf605089fd3ad7b6e33366b6aa959aa (commit)
       via  7f4301cb830b1f31b359d421460797d147f1a97d (commit)
       via  10d08746deb158f824353b439d1d7faa2652fde2 (commit)
       via  797c96cfc3d731de3b4a640288da56f57d724b59 (commit)
       via  5c3b417535b68756d346b6be9350274fee900fd3 (commit)
       via  f4f3b2745f1adf5b6d31c27766b5b36e29743802 (commit)
       via  ca180878e1aa0865cdcd9a5e8dff56c522a1858d (commit)
       via  8293dee8e6272a2d9b13805ae80988303bf90787 (commit)
       via  c69ebda005b5c2d37f33a28ee3c42fb3a5d7a4fc (commit)
       via  232a5db8c47c3736aaa642652dc01f9f8a827e70 (commit)
       via  fe3512462f462a02b2c1aa21d48e4b39c153ee8f (commit)
       via  439e412d9af03e844190f7ff85ad343bc0edaf83 (commit)
       via  03545347ff883f6adcf7dca5606044178b47a78f (commit)
       via  e1ba8991dc922da79b1a041ae3c7331f7da5fbf1 (commit)
       via  88965eebb804c9ac5202fba2ad0fedf0a15b5b04 (commit)
       via  521d1d343eac46afed9a362c085982ba83188459 (commit)
       via  83d84914318433022bbfde43f792888a4bf82833 (commit)
       via  1ec20226ac6fbdd5aeb2ea9ba6f6d1abb52c1335 (commit)
       via  0c0ff5e63c75d97c358e2ba3a4ce6f0ff0da605d (commit)
       via  0355c3753064ed15a40f6c09eb246c2a92a5bfa9 (commit)
       via  5a9086f98d32f78e5289c74bfb430d8f6bd3c652 (commit)
       via  fb5933cd063d5833ea3bdbdc2134ced4aa4c492e (commit)
       via  0ea6e987a7a9e66ccf6d880f70188d9779ac30f8 (commit)
       via  322d4f653e91dd703a98f876fb84aeb8fcb9dc6e (commit)
       via  d922348da4e9c36db1a5823ca36e23991b07593b (commit)
       via  2d85a4b9b1e867cef32e337ee2a73db21207f871 (commit)
       via  84fc867ff4ec8a810d9a75a8732b2cc68ac9106c (commit)
       via  a1b8b4a188805261d50c2d9a6cc29ea4185f7fa5 (commit)
       via  c64180f482365424375080016c1ed397d5d210fa (commit)
       via  61256b84916e279e4e40cea2af512aef6b5d515c (commit)
       via  8bc7d8074707a848d7e8da5196584c7b4bbe743c (commit)
       via  191b2b05f626ddcad2753756f7bdb0c62fee213a (commit)
       via  ab8dcefe9265931cf02119e2acec5fd71c1b85a8 (commit)
       via  830cd7c14dc42f5deff7ff0fd20e7e7d68027189 (commit)
       via  4acd5282f3d42683cedb2a45946441866a760ad0 (commit)
       via  8757e30d1889fd3c13d02f5c3b24bd1d76427463 (commit)
       via  28e76263dddf43c81b5ed30742035f36375b6507 (commit)
       via  0be6dd6d8ec757d0a44493928e5258fa4a9e849e (commit)
       via  668f0422b70f0dee77d9716201514dd67d0e44a7 (commit)
       via  2dcbccecf728a8bcf414f9aed89309a00ff1c215 (commit)
       via  e15e2aa727dbf03072e52ac1fb1f06266a18c423 (commit)
       via  033a9f1fb253cb86a8e51fcdeff8f80a3c3b5a5e (commit)
       via  838e5999e1319d9e3d6402298bed8125cf0fe74c (commit)
       via  c3084955bce439b062bf6ffa829ed50ddb64384b (commit)
       via  4f3f3e8006bfd93ca9f7f215dfaa7b76a2aa464c (commit)
       via  4658c51413b21bfdba77203806b37b66f18e6226 (commit)
       via  1664b9f6ed292f6cda0b51a4062f5671a5bce282 (commit)
       via  987d4199ebd5afaa16edb2700e4d10f6e6475c7a (commit)
       via  033d08babe26353e52ddf63bd52656246d258800 (commit)
       via  ba9103c890cb54b1ae5660266c9c94302f73d977 (commit)
       via  d7c59f881650ca4fcdbf211b0a7c029d0ffed4f9 (commit)
       via  767a7812018cece057fcda288e9d7a03e426aafe (commit)
       via  24d20a82ee02723bd53a390a93c8461ecad56949 (commit)
       via  00c05799e1a3c032edd4c9a3a4e61f2ccdfcc2bd (commit)
       via  86124f8e9d9fb8f10634765dd69ebfec8075dc40 (commit)
       via  006ef3d3f930c5926a07a11a4f17022f5927b2ff (commit)
       via  0680f6fb97a5a73420d2dcf22e24443541abe4a5 (commit)
       via  2980817835f351d3a9689bd70f0a296dd4f1cda8 (commit)
       via  12267fb1fe99b8d5ee1a54ebf4089e22113af3cf (commit)
       via  db55862bab26b9c9f3f249a0c37af4f10007a4fa (commit)
       via  0e1e1ffc5cd3077a72688ed342624580d1f532db (commit)
       via  3aa291d9edd9275009b3247cce97899508c9e28e (commit)
       via  b902137009c24e96a25280be851e2b6ac6e4aaa9 (commit)
       via  4c37b66a1a4cc5f4fe2264ad5b97c04d24a8eab4 (commit)
       via  7fa8f0ca371923329cb4d76186bea056bc614ec0 (commit)
       via  d153e2971c55b8ae92a4bd296ca594af9df6614f (commit)
       via  591bb62bae3d1ad865a029d71e47b20f47ceb58b (commit)
       via  87573d69b1a88b8c7e6b116efe22d42f4d750d4e (commit)
       via  e9c6eabbe90680ec55a929eab1395ac2600ec445 (commit)
       via  93da9a35ca3240b098cb930541902329b05f5280 (commit)
       via  c3412cd5c0f1eb255a44f7163825d006cbbdcbc0 (commit)
       via  5904f60061b31ae7ab2d938a2862ba72369cd57d (commit)
       via  9007c361a4164b44396703c25429dc822dfc5f9a (commit)
       via  01d8ff045080edad5da50292787f792009f1a38a (commit)
       via  0a445f28d6872724abcec5f993f099747d573136 (commit)
       via  34960755283b926473caaab006194fe25f2e5089 (commit)
       via  de33df5a773a3119794d974d67c5541ff0189d6f (commit)
       via  fbb58b084ff345aac53ce7d427a9d75741fb33ac (commit)
       via  f34273a6ca8fd19bb41b4e3896194b8e7d27b0cc (commit)
       via  7563a838416405473138d4afae9fb2404d26637d (commit)
       via  9566c70553d922ce851dd1d77f856cbdb55ccbf7 (commit)
       via  428ddbb250b6f033619bd5b98084227b0210431a (commit)
       via  d30b98786d91779bc867bd5033fcbe3598c9fcac (commit)
       via  79da572176e1c0034d03e8c87f93d56e456e07bf (commit)
       via  e503d4cc398163176b9ee09292e27395aa595d77 (commit)
       via  c2898569c7d0f008214631a4b2ea40175f7a7b49 (commit)
       via  43c1d01f1391d19e788c62fbcbace0a1aab6fc24 (commit)
       via  cd226c09c4699c5b37bf213e8818c23357f6230b (commit)
       via  ef7ec29b98c093f3fa1c7508a58cd7cc93552a3a (commit)
       via  692fa7068404923b510c469fd5cf52eb0717539a (commit)
       via  30a5acbff45629f18d6531e1ebadbe1fe0f7fba9 (commit)
       via  ee933d46b63a1f45e7d79e23b67a1c5d0e5f196b (commit)
       via  899c4d1aefea5f4b95d041f1b62c1174a97adc54 (commit)
       via  8dcaf0551dba484617d9acb1d486199c91346f58 (commit)
       via  b7d7b945317598b4eba6cdffd34934da4da4afcd (commit)
       via  6dd3325ed5ecb935a271b1a3881c85b438e2350c (commit)
       via  da39ec03cdd6aec5ad563dac926bb9b3dde4922b (commit)
       via  20b71641a93f8a3f6fc4400b4ce9c5b9eead18b9 (commit)
       via  89a93bf71a3dab94efc5a3f72feb3f44daebdb6d (commit)
       via  48d0708adc8a080d65d9713198a5a83e6fb07c18 (commit)
       via  d3b8f41d37c94ea69f268cc3014501f3a06d988f (commit)
       via  4f368196090019813cf64000aca71cde484b5376 (commit)
       via  56d88867c3928c43b6e815d6aa15caa73119f3c1 (commit)
       via  25ec6119561657ffaf49ca115fbd1ec2afff60aa (commit)
       via  77d70b596878e0516d68518fa295e8b3e2b0e8f8 (commit)
       via  366a4b98e8c6601a1e4669fa8d8e8dd818f758a6 (commit)
       via  14264a89cfad54fde811c2d0f3469617baa7b09e (commit)
       via  697448dc4fb6d3ef2c5e1cd2b1ca44b59e2a13d8 (commit)
       via  681231c94f8d73ad9bbec1854197457cae05081d (commit)
       via  0bbeb8478fff4bebbad830e708ae11e20df30416 (commit)
       via  98570975714f7e57f60ba703242c2bc7d5933a00 (commit)
       via  6f2c7d7ba845813b12bbee9b7789dfc105d2f06e (commit)
       via  237623b98628f4aea3c5d7d86f8895773170f863 (commit)
       via  bca65f7c3f48256ce1f2ee9742f8fdce56e9034b (commit)
       via  2bd10fef1351b9ea18e7c316c14f3f0228deefa2 (commit)
       via  4b04839b7f41e389bd09bbc181a41285cf59954b (commit)
       via  48b566475d19c32bcb106862c5be2c6ff7bf68ba (commit)
       via  b33b09ae202f528a560fbd96a6ed2fb4bf5df38b (commit)
       via  165de349dc1409b30f762f5c8df625e94051202e (commit)
       via  c3515687174adf1466f7e7330c420d9ae6caf9d3 (commit)
       via  4c10aa6ab9b24202a5fb423d0a0c252c8298fe2f (commit)
       via  84b92b0412ff218a5d18a1186773e0183fa37342 (commit)
       via  9738764e9d0f68cbd8e50a85f43f5dca8bd047f2 (commit)
       via  4f4284434bdc982aea13d2979ebe900a5ebfa3bf (commit)
       via  8892352e680cf2dc9def10813697dff3fef39793 (commit)
       via  3105e7c189e525d6ec8953426572edd380b14825 (commit)
       via  40c2c2a88c70e6c5318ddbc4cbb94944e79c7a71 (commit)
       via  35d34bea5e30f5dfa5ee675239031618adda4d41 (commit)
       via  1249f899db9feaf15d6d6028c1eea1609ea41798 (commit)
       via  41077922e6b9cfd57290f7c233274091290bab77 (commit)
       via  ce840aa3cdb26effe213d8cdf86decafc484cb3f (commit)
       via  9a00810f54000691f60c0dc9b3afffdbefcf0374 (commit)
       via  73a5a715bb3ff90cd1f8b2beb141a673588ae174 (commit)
       via  f10a4b1e9df29f715007e974c85324b3093bcfa0 (commit)
       via  250d74534277d318da871867d95aa6fcef272d8b (commit)
       via  be270c3887900fba583635104b5e4e89676bc1b0 (commit)
       via  bbc16cac7a067adadf2e7a7dcff1f5306a1ad91c (commit)
       via  26bb94be47d5584665cfa112099d69931ff8764f (commit)
       via  3114cb9254264e5dbd8d415e071ec78e9167321f (commit)
       via  7c8575afc469f99a45bb098e4cff32d0c65bd977 (commit)
       via  41dcd3e7efffcecd81852ac3a2d62b6e563bfbc2 (commit)
       via  cc2f373fb4201a103bbf352b0544cae7ddc7d530 (commit)
       via  289dc9acc025704102972478496c19e9de202948 (commit)
       via  38d3ebd01b5a1b8940cfd916eeff61d47f890e10 (commit)
       via  337b68c26fde2e1b6ee315c5e13f132f73f038b6 (commit)
       via  6d2bfcc5d0d977ebe879c49b60deddfcc737efa0 (commit)
       via  49584c8936d7a14fc5fb6de7590c692064734d20 (commit)
       via  ae6ab21021b0d4561d59ef38a292ccef9be27898 (commit)
       via  e88e8e4bc7cd470260be631c0a35b13b99fbabdc (commit)
       via  569823a06731c31b061f3078453e87e80c205f69 (commit)
       via  d0cd372ebe94da94306271db43b4e2cffa9330b7 (commit)
       via  f48080f4f9d3138f7295b2a888573a09b0e83691 (commit)
       via  40e81f8fd51c863b4cc2c3086f49090cf29f1578 (commit)
       via  79a4f97c1ce884724aa6e7a5f727cc474278c928 (commit)
       via  c1e474acac1dc85218a3bb475ff2d4379579a847 (commit)
       via  6eeb8fe90815fa9fe00c799a7436ee3606ad5fec (commit)
       via  2c9a9eb5e85fb226ff4eed0e8f688d202e3a9423 (commit)
       via  8c3be3465dffd0b00733030e9cdb1842edc2333a (commit)
       via  c07cb4ac1cf4bca423b912fea0ecedb93b98e413 (commit)
       via  207830554d0d1ac170ff0f43f31c1b16f4c58894 (commit)
       via  762fad70066fe4dcd0a7379352efe779691081ca (commit)
       via  311803249a4adbb9a04c33fbc399817ccda1797a (commit)
       via  19602144ce193599bcd6f9558d1b48246abc7594 (commit)
       via  295f3dc43ec37d1c91c1863701504ae1eda94525 (commit)
       via  691f6d8371991b5cbaa6933366b36e2626b2a878 (commit)
       via  cc11d7de0bc013d261519994f78bcb3a99389003 (commit)
       via  ddd7a7c2b4df489f6e855ddc979cd27ed43f5213 (commit)
       via  e39968fbe9fef03da122dc7360d10a2e7c62c613 (commit)
       via  d5259c7a91e7e34b803bc724137f4f46873526e0 (commit)
       via  1fe6cff6b99d3796435377d357bb80a7213a886c (commit)
       via  02648920aa2bc352a6747b1080fd44f1f45d18e0 (commit)
       via  1fa10cde38ad70ae2022b97ccf7b2e7e67908db4 (commit)
       via  10efb618041a441e7b63f6fa69ac66a275f48c01 (commit)
       via  96b36d6487bbab43dc5aadca3b269273b8269566 (commit)
       via  e93ec92c52c0c9fe06474c20192bfb7b9c04b2bc (commit)
       via  b2a6afc27b11f35b768ba5d28b5d8a9ff383700f (commit)
       via  454320a985cebf8e88d48d00c333ba6f42a9b2c4 (commit)
       via  70b67c1a749a3564a5f3bf0c321e90c2678812ec (commit)
       via  2944fc2c2b830f6f90eedb20142242cf2a1f90ba (commit)
       via  d946c9db8f00d06a1b4fc8947a161db47a1b11a4 (commit)
       via  9e4995493bd34f02a6e7bc8cc7cea59776038230 (commit)
       via  56659152f6482bec6801ab2b39a0a8ec90c15a6b (commit)
       via  e6326467227454e10881d51f725bbab0e54015ac (commit)
       via  3e4b756df166eb8aa9cca12d321bb53c49031f8a (commit)
       via  ec0cd369a445fbd898d64f96dad1907fae61d406 (commit)
       via  93791987169428f4011f105cc9a2ef41546efad1 (commit)
       via  68eff7225b181fd43caff745c99292a012809352 (commit)
       via  4507bef434b0695d6993169042c9e12f0082febd (commit)
       via  36592de2cc5a33e3a769761eca2027048cee664e (commit)
       via  b8c5d267a9ef3c8ba2fa5d7755460542868bd2e1 (commit)
       via  5eb674425dc654e194ab1c278b58b296de17686c (commit)
       via  b99133efadf3d1f6e9ffb21704b149e0037f992a (commit)
       via  07c2e40924da60e21bf7adf6510aa3d5308db0ee (commit)
       via  e6a36fca8bfe6654a0bb799bb2d14a536bb1f927 (commit)
       via  77a5ab9d6e24227d0f43aae56471c46536771713 (commit)
       via  50f9394a114315d412949ee6b2123e19678fd440 (commit)
       via  dbe51ab0ce83b8f3aa4174ba410db39733b0e646 (commit)
       via  268d0c3c3c6170a7e084b16e9213fcdf6a508dde (commit)
       via  a4ce7f516c011930ddbf339cad6d8d622c191841 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (1523e57c3a7fef6c177e0795eb24425dd78c71aa)
            \
             N -- N -- N (75ef4c9845fb8c627a68e7c2cc1b08347031d480)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

http://git.fawkesrobotics.org/fawkes.git/thofmann/syncpoint

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- *Log* ---------------------------------------------------------------
commit a06118fee013af4465c122a4c77b57dc2b6f0269
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Feb 3 15:04:05 2014 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:34:30 2016 +0200

    syncpoint: add SyncPoint library
    
    SyncPoints are used to synchronize threads dynamically to allow easy
    management of subsequent tasks. As an example, thread E generates data
    which is needed by thread W. Therefore, both threads share a SyncPoint.
    Thread W wait()s for the SyncPoint to be emitted.
    Once thread E is done, it emit()s the SyncPoint, which wakes up thread
    W.
    
    Currently, any thread which uses SyncPoints needs the SyncPointManager
    Aspect. Threads with this aspect have access to the syncpoint_manager.
    
    SyncPoints have to have absolute-path-style identifiers, e.g.
    '/some/syncpoint'.

http://git.fawkesrobotics.org/fawkes.git/commit/a06118f
http://trac.fawkesrobotics.org/changeset/a06118f

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit a3ed12bb4662f3eecc7f1ca044ef4d9c4c4dd801
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon May 5 15:42:19 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:34:30 2016 +0200

    syncpoint: add unit tests

http://git.fawkesrobotics.org/fawkes.git/commit/a3ed12b
http://trac.fawkesrobotics.org/changeset/a3ed12b

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 5be9ca5fc46ebafc8c653e8845829a86a1542305
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon May 5 15:56:39 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:24 2016 +0200

    syncpoint: add two simple test plugins

http://git.fawkesrobotics.org/fawkes.git/commit/5be9ca5
http://trac.fawkesrobotics.org/changeset/5be9ca5

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 4892df65ea09d66ab57a17bb8d2e3712a2d62a12
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Tue May 20 11:25:07 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:25 2016 +0200

    syncpoint: use mutexes in SyncPoint and SyncPointManager
    
    Both are called by multiple threads, therefore any calls have to be
    guarded by mutexes.

http://git.fawkesrobotics.org/fawkes.git/commit/4892df6
http://trac.fawkesrobotics.org/changeset/4892df6

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit fc80185a193952af7797c28b78e3bb81d4d5b7f1
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Tue May 20 11:27:41 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:25 2016 +0200

    syncpoint: Minor changes in exception descriptions

http://git.fawkesrobotics.org/fawkes.git/commit/fc80185
http://trac.fawkesrobotics.org/changeset/fc80185

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit a6dc56681f765eab2bc9bdde06d28348837f8054
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Tue May 20 11:31:45 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:25 2016 +0200

    syncpoint: throw exception if a waiting component calls wait() again

http://git.fawkesrobotics.org/fawkes.git/commit/a6dc566
http://trac.fawkesrobotics.org/changeset/a6dc566

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit d30b3026298b0bc6295b0dae105ae07fda32276c
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Tue May 20 11:42:47 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:25 2016 +0200

    syncpoint: add unit tests for multiple wait calls, multi-threading

http://git.fawkesrobotics.org/fawkes.git/commit/d30b302
http://trac.fawkesrobotics.org/changeset/d30b302

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 6a1b95656137369e110ba7a02e8095efc4a68ed7
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Tue May 20 14:40:22 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:26 2016 +0200

    syncpoint: add unit tests to test wait/emit calls with multi-threading

http://git.fawkesrobotics.org/fawkes.git/commit/6a1b956
http://trac.fawkesrobotics.org/changeset/6a1b956

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 3580b24d60a083758234e44b2609bd477ecdc88c
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Aug 15 19:49:05 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:26 2016 +0200

    syncpoint: add support for visualization
    
    Add all necessary data structures to the syncpoint library to be able to
    visualize call sequences. We now store all recent calls in a
    CircularBuffer and keep track of calling statistics (first call, last
    call, frequency, wait time). Furthermore, we use that data to generate a
    DOT graph. This could for example be used to show the call graph in
    webview.

http://git.fawkesrobotics.org/fawkes.git/commit/3580b24
http://trac.fawkesrobotics.org/changeset/3580b24

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit afdd6ec79e109c2fc9c711a2e209f13b8bc43362
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Aug 15 20:01:14 2014 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:26 2016 +0200

    webview: add SyncPoint visualization
    
    Visualize SyncPoints with a graph. This shows all currently used
    SyncPoints and visualizes emit and wait calls to those SyncPoints.
    Furthermore, some basic information such as last wait()/emit() call,
    average waiting time and emit frequency are shown.

http://git.fawkesrobotics.org/fawkes.git/commit/afdd6ec
http://trac.fawkesrobotics.org/changeset/afdd6ec

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 35a9b1dc7bcceb2aafecf44f1cdba8cc690d0693
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Jan 16 13:57:37 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:27 2016 +0200

    syncpoint: consistent variable naming

http://git.fawkesrobotics.org/fawkes.git/commit/35a9b1d
http://trac.fawkesrobotics.org/changeset/35a9b1d

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit b9090fd43ee68b23d6398932f4d6a2eea1cef4e2
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Jan 23 15:22:07 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:27 2016 +0200

    syncpoint: use std::string for identifiers, API change!
    
    Using char * for SyncPoint identifiers is cumbersome because all strings
    have to be copied during initialization. This also means that we would
    have a fixed length for identifier strings. In our test cases, where we
    start many threads simultaneously, the compiler often optimized the
    identifier strings such that two different identifier strings had the
    same address, which caused the identifier saved in the set of watchers
    to be changed, leading to a SyncPointAlreadyOpenedException for a new
    component. This can be avoided by copying all strings in the
    constructor, but using std::string avoids this problem alltogether.
    
    Note: This changes the API because all functions such as get_syncpoint,
    wait, and emit expect std::strings instead of char *.

http://git.fawkesrobotics.org/fawkes.git/commit/b9090fd
http://trac.fawkesrobotics.org/changeset/b9090fd

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit ca3bec072cdafefcb9093667906fece4446f74fe
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Jan 23 20:17:22 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:27 2016 +0200

    syncpoint: add method add_watcher
    
    In the SyncPointManager, instead of manipulating the watcher list
    directly, use the methode add_watcher.

http://git.fawkesrobotics.org/fawkes.git/commit/ca3bec0
http://trac.fawkesrobotics.org/changeset/ca3bec0

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 1b4992fc956b4ba02f91ba1a01c83289954a1be3
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Jan 23 20:26:31 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:28 2016 +0200

    syncpoint: initialize WaitCondition correctly, use MutexLocker
    
    The WaitCondition needs its own mutex, thus use its internal mutex. Use
    the MutexLocker to simplify mutex handling where possible.

http://git.fawkesrobotics.org/fawkes.git/commit/1b4992f
http://trac.fawkesrobotics.org/changeset/1b4992f

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit aed0e80779cf0d53ba5c78874c71b286f99ace3e
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Jan 23 20:41:01 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:28 2016 +0200

    syncpoint: remove errors reported by clang

http://git.fawkesrobotics.org/fawkes.git/commit/aed0e80
http://trac.fawkesrobotics.org/changeset/aed0e80

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit c56c39c8e09d40b24184240c7b96fa964e882fb3
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Sun Jan 25 00:10:42 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:28 2016 +0200

    syncpoint: update unit test
    
    -initalize and clean up threads correctly
    -always join threads before terminating a test
    -add a simple test to test the SyncPoint's watcher set
    -call wait() and emit() multiple times

http://git.fawkesrobotics.org/fawkes.git/commit/c56c39c
http://trac.fawkesrobotics.org/changeset/c56c39c

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 45a094a2b22ac3fb3e2d2d81e88c31e6d6d84bc6
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Sun Jan 25 02:27:48 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:28 2016 +0200

    syncpoint: add SyncBarriers
    
    SyncBarriers are similar to SyncPoints but serve a different purpose:
    Instead of a single emitter, multiple emitters can register for a
    SyncBarrier. Only if all registered emitters have emitted the barrier a
    waiter can continue. Also, if the barrier has already been emitted, a
    waiter does not block at all but instead wait returns immediately.
    
    The manager's reset_syncbarriers() method needs to be called every
    iteration. It resets every barrier such that all registered emmiters are
    again pending, i.e. waiters will block until the barrier is emitted
    again.

http://git.fawkesrobotics.org/fawkes.git/commit/45a094a
http://trac.fawkesrobotics.org/changeset/45a094a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit dfd84a96c252c1572236371f5430617646b2cb4c
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Jan 26 16:50:14 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:29 2016 +0200

    syncpoint: add SyncBarrier tests

http://git.fawkesrobotics.org/fawkes.git/commit/dfd84a9
http://trac.fawkesrobotics.org/changeset/dfd84a9

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 67b8437a605e6f8d39920a550b89b2756f52382d
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Jan 26 18:08:55 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:29 2016 +0200

    syncpoint: always reset pending emitters after SyncBarrier was released
    
    Until now, a SyncBarrier needed a central controller which reset the
    barrier every iteration. Now, reset the barrier immediately after it has
    been released, i.e. after every pending emitter has emitted the barrier.
    This allows us to remove any central component which controls the
    barrier, and we can define a control loop independently of the main
    thread.
    
    As an example, one could reconstruct a main loop in the following way:
     --- barrier: sensor_hook --- <---\
        |              |               |
        v              v               |
     sensor1        sensor2            |
        |              |               |
        v              v               |
     --- barrier: world_hook ---       |
                |                      |
                v                      |
         world state thread            |
                |                      |
                v                      |
     --- barrier: think_hook ---       |
         |      |     |                |
         v      v     v                |
       think1 think2 think3            |
         |      |     \                |
         \______\______\_______________/
    
    where barrier->thread are wait() calls, and thread->barrier are emit()
    calls.
    
    Note that this also means that if a thread waits on a barrier which has
    just been released, the thread will wait until it is released again.

http://git.fawkesrobotics.org/fawkes.git/commit/67b8437
http://trac.fawkesrobotics.org/changeset/67b8437

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 6defe69477d0677fff7865fcb89b4fe9c4e27dde
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Feb 2 13:19:21 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:29 2016 +0200

    syncpoint: only wait for a SyncBarrier if emitter exists
    
    A thread shall wait on a SyncBarrier until all registered emitters have
    emitted the barrier. If no barrier exists, this is always the case.
    Thus, return immediately instead of waiting for the barrier.

http://git.fawkesrobotics.org/fawkes.git/commit/6defe69
http://trac.fawkesrobotics.org/changeset/6defe69

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 982cfe1407c64a6893c04d9ab74ece270197e45f
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Feb 2 14:27:52 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:30 2016 +0200

    syncpoint: add additional identifier constraints
    
    We allow '/' to be a valid SyncPoint identifier, but we do not allow any
    other identifiers ending in '/' such as '/some/sp/'.

http://git.fawkesrobotics.org/fawkes.git/commit/982cfe1
http://trac.fawkesrobotics.org/changeset/982cfe1

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 73a334157ab0993a6260dec806b3ca1d57f94d86
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Feb 2 14:30:14 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:30 2016 +0200

    syncpoint: test additional identifier constraints

http://git.fawkesrobotics.org/fawkes.git/commit/73a3341
http://trac.fawkesrobotics.org/changeset/73a3341

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit a541425382acf929c0741c19097dc875de7a17b7
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 13 14:29:08 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:30 2016 +0200

    syncpoint: add SyncPoint hierarchy
    
    The hierarchy allows to wait for a SyncPoint which is somewhere upward
    in the path, e.g. a component waiting for '/some/topic' will be
    unblocked if a SyncPoint '/some/topic/sp' is emitted.
    This allows to wait for one of the subordinate components. Note this
    corresponds to OR: If ANY of the subordinate syncpoints is emitted, the
    waiter will unblock.
    
    In order to do so, automatically add a predecessor SyncPoint during
    SyncPoint creation and also automatically register the component for
    that SyncPoint. Additionally, any predecessor SyncPoint is emitted if a
    SyncPoint is emitted.

http://git.fawkesrobotics.org/fawkes.git/commit/a541425
http://trac.fawkesrobotics.org/changeset/a541425

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 8aa12b32e483992704904082cbc90127ad7e7edc
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 13 14:36:12 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:30 2016 +0200

    syncpoint: add test for SyncPoint hierarchy
    
    Add a test which creates a waiter for a parent SyncPoint and then emit
    that SyncPoint. Also adapt the other tests to the changes, as additional
    SyncPoints are now automatically created.

http://git.fawkesrobotics.org/fawkes.git/commit/8aa12b3
http://trac.fawkesrobotics.org/changeset/8aa12b3

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit d4dc9370bc1b5b0f4ec9e52b887ab3a643b1a4f3
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 13 15:15:09 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:31 2016 +0200

    syncpoint: add SyncBarrier hierarchy
    
    This is very similar to the SyncPoint hierarchy except that wait calls
    correspond to AND. If a component waits for '/test' and two emitter have
    registered for '/test/b1' and '/test/b2', then BOTH emitters have to
    emit in order to unblock the waiter.

http://git.fawkesrobotics.org/fawkes.git/commit/d4dc937
http://trac.fawkesrobotics.org/changeset/d4dc937

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit ea1c1e9213fd28f2bf202e4df35fbba3a41f3244
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 13 15:57:20 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:31 2016 +0200

    syncpoint: add test for SyncBarrier hierarchy
    
    Also adapt existing tests for the hierarchy.

http://git.fawkesrobotics.org/fawkes.git/commit/ea1c1e9
http://trac.fawkesrobotics.org/changeset/ea1c1e9

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 6ac0e185729038a9a31a65977b24eb6f0d734603
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 13 15:58:00 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:35:31 2016 +0200

    syncpoint: directly make a newly registered emitter pending
    
    This means a component which registers for a barrier is immediately
    waited for, and thus should also emit the barrier in the same loop.

http://git.fawkesrobotics.org/fawkes.git/commit/6ac0e18
http://trac.fawkesrobotics.org/changeset/6ac0e18

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 4955dbe8617900c485755cc033717da41d012c27
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Thu Feb 19 11:10:08 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:05 2016 +0200

    Revert "syncpoint: add two simple test plugins"
    
    This reverts commit f1ca3ad7a08a2804604be7e0dd333c7bb73ca0b5.
    
    The test plugin is not up-to-date and not used anymore.

http://git.fawkesrobotics.org/fawkes.git/commit/4955dbe
http://trac.fawkesrobotics.org/changeset/4955dbe

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 0deb47a02429b9b89c7f9a822f0f836d41574fa3
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Thu Feb 19 16:12:10 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:05 2016 +0200

    core: add ThreadLoopListener
    
    With the ThreadLoopListener, it is possible to do tasks right before the
    thread's loop() starts and right after the thread's loop() returned.
    In order to do so, you need to inherit from ThreadLoopListener,
    implement the pre_loop and post_loop methods and register your loop
    listener with the respective thread.

http://git.fawkesrobotics.org/fawkes.git/commit/0deb47a
http://trac.fawkesrobotics.org/changeset/0deb47a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 58a1459aa0627f1f3a4c23151641d0c58f8daa09
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Thu Feb 19 16:53:22 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:06 2016 +0200

    aspects: add SyncPointAspect
    
    The SyncPointAspect waits for a SyncPoint before
    every loop and/or emits a SyncPoint after every loop. The SyncPoints are
    created and managed by the aspect.
    
    There are two modes of operation for the input SyncPoint: If the aspect
    is initialized with WakeupType::WAIT_FOR_ONE, then the SyncPoint waits
    until ONE other component emits the SyncPoint. Similarly, if the aspect
    is initialized with WakeupType::WAIT_FOR_ALL, then the SyncPoint waits
    for ALL other components which have registered for the SyncPoint.
    
    Depending on the initialization, the thread may
    - only wait for a SyncPoint at the beginning of the loop and not emit a
      SyncPoint after the loop,
    - only emit a SyncPoint at the end of the loop but not wait for a
      SyncPoint at the beginning of the loop
    - both wait at the beginning of the loop and emit (a different)
      SyncPoint at the end of the loop

http://git.fawkesrobotics.org/fawkes.git/commit/58a1459
http://trac.fawkesrobotics.org/changeset/58a1459

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 9c4748595bcf1dd2ff16c29a847ac700eb433484
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 27 16:56:32 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:06 2016 +0200

    syncpoint: SyncPoints are now also barriers
    
    Instead of separating SyncPoints and SyncBarriers, make a SyncPoint also
    a barrier. This allows us to use the same SyncPoint in both ways, i.e.
    one thread may wait for a single emitter and another thread may wait for
    all registered emitters.
    
    Some functions now take an additional optional argument WakeupType
    which specifies the wakeup mode.
    
    SyncBarriers are now SyncPoints with the only difference that WakeupType
    defaults to WAIT_FOR_ALL.

http://git.fawkesrobotics.org/fawkes.git/commit/9c47485
http://trac.fawkesrobotics.org/changeset/9c47485

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit f6843ce0bdcfec0363666adac078bcf0c50f9d65
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 27 18:02:57 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:06 2016 +0200

    syncpoint: remove SyncBarriers
    
    SyncPoints now provide all functionality of SyncBarriers, thus
    SyncBarriers are obsolete.

http://git.fawkesrobotics.org/fawkes.git/commit/f6843ce
http://trac.fawkesrobotics.org/changeset/f6843ce

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit f3e862f439fdcaf3cc635af57c1bc21730e86d93
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 27 18:11:55 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:07 2016 +0200

    syncpoint: remove SyncBarrier support in aspects
    
    Always use SyncPoints. Adapt SyncPoint calls accordingly.

http://git.fawkesrobotics.org/fawkes.git/commit/f3e862f
http://trac.fawkesrobotics.org/changeset/f3e862f

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit dfc3f07724456e3de0399e4ab419f2149e5280a6
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 27 18:14:01 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:07 2016 +0200

    syncpoint: remove SyncBarriers from unit tests
    
    Adapt the tests to always use SyncPoints.

http://git.fawkesrobotics.org/fawkes.git/commit/dfc3f07
http://trac.fawkesrobotics.org/changeset/dfc3f07

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 52878ce9e059f6f544febde918b7b2c493498575
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 27 20:14:49 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:07 2016 +0200

    syncpoint: do not throw an exception if SyncPoint is already opened
    
    With hierarchical SyncPoints, the exception is thrown whenever one
    component opens two SyncPoints. Opening a SyncPoint multiple times does
    not really hurt, the exception was only a precaution.

http://git.fawkesrobotics.org/fawkes.git/commit/52878ce
http://trac.fawkesrobotics.org/changeset/52878ce

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit ca44a7c2f46539939aaeb9d84c0be65bb162bb9c
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Feb 27 20:20:15 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:07 2016 +0200

    core: properly lock loop_listeners before access

http://git.fawkesrobotics.org/fawkes.git/commit/ca44a7c
http://trac.fawkesrobotics.org/changeset/ca44a7c

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 231d81d17b6909f3c9d72c75377a6a556b6a3070
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Mar 4 17:02:55 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:08 2016 +0200

    aspects: make the BlockedTimingAspect a SyncPointAspect
    
    Use syncpoints for all BlockedTiming threads. For each hook, add a start
    and an end hook syncpoint. At the beginning of each hook, the main
    thread emits the start syncpoint. At the end of each hook, the main
    thread waits for the end syncpoint, which is emitted by all threads
    registered for the hook.
    
    This replaces the main loop with syncpoints. However, the main thread
    still has to manage all hooks, similar to before.
    
    In order to use the new main loop, each blocked timing thread currently
    needs to be changed to continuous mode. Otherwise, no changes are
    required.

http://git.fawkesrobotics.org/fawkes.git/commit/231d81d
http://trac.fawkesrobotics.org/changeset/231d81d

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit a6e660a15e7d31cb69e8cab458e64b882e0753b1
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Thu Mar 5 15:50:22 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:56 2016 +0200

    syncpoint: add syncpoint test plugin
    
    This plugin tests the BlockedTimingAspect with syncpoints. For each
    hook, it adds a test thread which simply sleeps for a random interval
    and then prints its name. This tests whether the threads are indeed
    woken up in the correct order.

http://git.fawkesrobotics.org/fawkes.git/commit/a6e660a
http://trac.fawkesrobotics.org/changeset/a6e660a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 4c27def80e1cb4ef9e8886dbed0174aca621a01c
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Mar 6 19:15:16 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:56 2016 +0200

    syncpoint: do not throw on multiple register calls
    
    We want to allow a component to register for multiple syncpoints, e.g.
    '/some/sp1' and '/some/sp2'. With hierarchical syncpoints, the component
    will also register for the syncpoint '/' when registering for the first
    syncpoint. When registering for the second syncpoint, an exception will
    be thrown as the component is already registered for '/'.
    Calling register for the same syncpoint multiple times doesn't do any
    damage, the exception was only a precaution and can thus be safely
    removed.

http://git.fawkesrobotics.org/fawkes.git/commit/4c27def
http://trac.fawkesrobotics.org/changeset/4c27def

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit da417c46f10118cf7acf0fca929a639ba4efcb63
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Mar 18 12:44:46 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:57 2016 +0200

    aspects: require continuous mode in blocked timing aspect
    
    Threads with the blocked timing aspect are not woken up by the main
    thread anymore. Instead, they should run continuously and wait at the
    beginning of the loop for the syncpoint.

http://git.fawkesrobotics.org/fawkes.git/commit/da417c4
http://trac.fawkesrobotics.org/changeset/da417c4

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit d5d546f8b2d67c2688490e20cbc4aa2a86bad7a3
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Mar 18 12:50:04 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:57 2016 +0200

    syncpoint: add equal operator for std::strings
    
    The identity of a SyncPoint is determined by its identifier string.
    Add an equal operator to compare a SyncPoint with a std::string. This
    allows us to use strings to search a SyncPoint in a container without
    having to create a SyncPoint just for comparison.

http://git.fawkesrobotics.org/fawkes.git/commit/d5d546f
http://trac.fawkesrobotics.org/changeset/d5d546f

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit fcf2e6e6b71683289689689aa5fc043b8cef22da
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Mar 18 12:53:35 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:57 2016 +0200

    syncpoint: fix calculation of call frequency

http://git.fawkesrobotics.org/fawkes.git/commit/fcf2e6e
http://trac.fawkesrobotics.org/changeset/fcf2e6e

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit a17fd5fbe197492267b5ae91d3b634c7001eaedd
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Mar 18 14:17:14 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:57 2016 +0200

    syncpoint: adapt visualization to the two types of wait calls
    
    A wait call can be either a wait_for_one or a wait_for_all call.
    Visualize both types of calls.

http://git.fawkesrobotics.org/fawkes.git/commit/a17fd5f
http://trac.fawkesrobotics.org/changeset/a17fd5f

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 92cce9b6a954673987eecb99fd2cdf94ddc4bada
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Tue Mar 24 21:47:08 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:58 2016 +0200

    aspects: BlockedTimingAspect with wait-for-wakeup and syncpoints
    
    Adapt the BlockedTimingAspect such that it expects the thread to be in
    wait-for-wakeup mode while using syncpoints. Since the thread is no
    longer woken up by the main thread, add a loop listener which wakes up
    the thread immediately after the loop returned. This recreated the
    expected behavior: After the thread finished its loop(), the loop
    listener immediately wakes up the thread, which then waits for the
    syncpoint at the beginning of the loop, before it continues with the
    next iteration.
    
    Since a thread is never woken up by the main thread, we still need to
    start the thread, otherwise it will never run. For now, we start the
    thread in the initializer of the BlockedTimingAspect.

http://git.fawkesrobotics.org/fawkes.git/commit/92cce9b
http://trac.fawkesrobotics.org/changeset/92cce9b

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 2376ae52c96155c82e6baa14b80a257f27131959
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Tue Mar 24 21:55:24 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:58 2016 +0200

    core: provide stubs for the ThreadLoopListener hooks
    
    A ThreadLoopListener may not always use both pre- and post-loop hooks.
    Provide stubs to allow to override only the reqired functions.

http://git.fawkesrobotics.org/fawkes.git/commit/2376ae5
http://trac.fawkesrobotics.org/changeset/2376ae5

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 02c0acce00d0e93f58ae9f9e9e5a64eda3172dc5
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Mar 25 10:28:23 2015 +0100
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:58 2016 +0200

    core: do not protect pre and post loop hooks with loop mutex
    
    The loop mutex should only protect the actual loop but not the pre and
    post loop hooks. Now, we can interrupt (and cancel) a thread which
    is currently in a pre or post loop hook.  As an example, we can cancel a
    thread which is currently waiting for a syncpoint in the pre loop.
    If the pre loop is protected with the mutex, cancelling the thread would
    not be possible.

http://git.fawkesrobotics.org/fawkes.git/commit/02c0acc
http://trac.fawkesrobotics.org/changeset/02c0acc

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit d9015159e01589dbceff325c128552449547ca20
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed May 20 15:50:43 2015 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:58 2016 +0200

    syncpoint: support components with multiple hierarchical syncpoints
    
    A component c1 may be an emitter for multiple syncpoints (e.g.
    '/test/sp1' and '/test/sp2'). In this case, the hierarchical syncpoints
    now work as follows:
    1. '/test' is emitted if '/test/sp1' or '/test/sp2' are emitted. If both
       syncpoints are emitted, '/test' is emitted twice
    2. The component is registered as emitter for 'test' twice. That means,
       any component waiting for '/test' will wait until 'c1' has emitted
       '/test' twice.
    3. '/test' is only released if all its successors ('/test/sp1' and
       '/test/sp2') have been released.

http://git.fawkesrobotics.org/fawkes.git/commit/d901515
http://trac.fawkesrobotics.org/changeset/d901515

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit e934ffeda8801a63f34b11ef7b4929d5e9242b76
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Thu May 21 14:24:19 2015 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:59 2016 +0200

    syncpoint: correctly manage pending components of predecessor syncpoints
    
    In general, the predecessor syncpoint should be emitted whenever a
    syncpoint is emitted. However, if the current component was not pending
    (i.e. it has already emitted the syncpoint), then the component should
    not be removed from the pending components of the predecessor syncpoint,
    and all components which wait_all() for the predecessor should not be
    unblocked, but the predecessor should still be emitted.
    
    This allows a component to register for multiple syncpoints and emit a
    single syncpoint multiple times. As an example, say the component 'c1'
    is registered as emitter for '/test/sp1' and '/test/sp2', and thus,
    because of the syncpoint hierarchy, it is also registered as emitter for
    '/test' twice, once for each successor syncpoint. Now c1 emits
    '/test/sp1' and since it was pending, it is removed from the pending
    components for both '/test/sp1' and '/test'. Then, if c1 *again* emits
    '/test/sp1', it is not pending anymore. Thus, it should not be removed
    from the pending components of '/test' (since now it is only pending
    because of the second syncpoint). If it were removed, then components
    which wait_all() for '/test' would be unblocked even though '/test/sp2'
    has never been emitted.

http://git.fawkesrobotics.org/fawkes.git/commit/e934ffe
http://trac.fawkesrobotics.org/changeset/e934ffe

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit d8c6b2fb2e4e6f1e0fb2dab22df63c7e5a36b982
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Jul 22 15:02:21 2015 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:59 2016 +0200

    core: release the loop listeners' mutex when joining the thread
    
    In order to allow proper finalization, the loop listeners' mutex must be
    unlocked in all cases while the thread is joined. Otherwise, if the
    mutex is still locked, any aspect using a loop listener cannot finalize,
    as the aspect tries to remove itself from the loop listeners during
    finalization, leading to a deadlock. Such a deadlock occurs especially
    often if the loop listener's pre_loop and post_loop calls do not return
    immediately (e.g. if pre_loop waits for a syncpoint).
    
    Unlocking the mutex after joining the thread is safe because the loop
    listeners will not be called anymore and the list of loop listeners will
    not be accessed otherwise.

http://git.fawkesrobotics.org/fawkes.git/commit/d8c6b2f
http://trac.fawkesrobotics.org/changeset/d8c6b2f

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 538921a69e8de75af25c8c1fe668f37a24584cd1
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Thu Jul 23 13:56:45 2015 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:36:59 2016 +0200

    syncpoint: improve syncpoint visualization
    
    Use different edge styles for different types of calls (emit,
    wait_for_one, wait_for_all), and highlight currently active wait calls.

http://git.fawkesrobotics.org/fawkes.git/commit/538921a
http://trac.fawkesrobotics.org/changeset/538921a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 079607de1b7e1984cfaf894e681dcc4d2ce186bf
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Thu Jul 23 14:33:23 2015 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:37:00 2016 +0200

    syncpoint: wake up all components in the same hierarchy simultaneously
    
    Until now, a component emitting a syncpoint '/some/sp' would
    1. wake up all components waiting for the syncpoint '/some/sp'
    2. unlock the syncpoint's mutex,
    3. go up the hierarchy (by waking up all components waiting for '/some')
    
    Since the syncpoint's mutex is unlocked in (2), all waiter threads will
    continue after (2), while the emitter is still waking up components
    further up in the hierarchy.
    
    This can cause deadlocks, especially if one of the waiters is very fast
    and immediately emits a syncpoint another component requires. To avoid
    this kind of deadlock, first wake up all components, and then release
    all mutexes at the same time.

http://git.fawkesrobotics.org/fawkes.git/commit/079607d
http://trac.fawkesrobotics.org/changeset/079607d

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 99bae6ef6ecf55d5a23d6e8cba5e7a398ddbd7a0
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Fri Jul 24 17:56:08 2015 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Wed Apr 13 16:37:00 2016 +0200

    syncpoint: add the possibility of time-limited waits
    
    Sometimes a component should only wait for a certain time for a given
    syncpoint. After the time limit has been exceeded, the component will
    print a warning and continue to execute.
    
    In particular, this is used in the main thread to accomplish timed waits
    for the hooks of the main loop.

http://git.fawkesrobotics.org/fawkes.git/commit/99bae6e
http://trac.fawkesrobotics.org/changeset/99bae6e

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 2ebd7b36ae3206417a572d4ebee89101e25e2398
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Aug 3 15:56:05 2015 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Thu Apr 14 16:02:35 2016 +0200

    syncpoint: allow waiter to lock all emitters
    
    Sometimes it is necessary to force all emitters to wait before the next
    emit() call until a waiter has called wait(). As an example, a thread
    watching all emitters of a given syncpoint (such as the MainThread)
    needs to call wait() before the emitters call emit. Thus, add a mutex as
    a stopby for all emitters.
    
    If a component needs to lock the emitters, it can simply call
    lock_until_next_wait(component_id). This way, any emitter will lock
    until the specified waiter calls wait().

http://git.fawkesrobotics.org/fawkes.git/commit/2ebd7b3
http://trac.fawkesrobotics.org/changeset/2ebd7b3

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit adbd3195c18ccfe7b226a2bdc46c87de56e63127
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Mon Apr 11 13:53:16 2016 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Thu Apr 14 16:02:36 2016 +0200

    baseapp: add a mainloop based on syncpoints to have min/max loop time
    
    Similar to the old mainloop, this allows to configure a minimum and a
    maximum for the duration of the mainloop. If the loop time is less than
    the minimum, the mainloop waits until the desired minimum is reached. If
    the maximum is reached, a warning is printed.
    
    Note that in contrast to the old mainloop, this does not remove any
    threads from the loop, but only prints warnings.

http://git.fawkesrobotics.org/fawkes.git/commit/adbd319
http://trac.fawkesrobotics.org/changeset/adbd319

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 75ef4c9845fb8c627a68e7c2cc1b08347031d480
Author:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
AuthorDate: Wed Apr 13 16:13:39 2016 +0200
Commit:     Till Hofmann <hofmann at kbsg.rwth-aachen.de>
CommitDate: Thu Apr 14 16:02:36 2016 +0200

    libs: add dependency of syncpoint on logging

http://git.fawkesrobotics.org/fawkes.git/commit/75ef4c9
http://trac.fawkesrobotics.org/changeset/75ef4c9

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


- *Summary* -----------------------------------------------------------
 cfg/conf.d/amcl.yaml                               |   18 +-
 cfg/conf.d/bumblebee2.yaml                         |    4 +-
 cfg/conf.d/colli.yaml                              |    6 +-
 cfg/conf.d/dynamixel.yaml                          |   14 +
 cfg/conf.d/firevision.yaml                         |    2 +-
 cfg/conf.d/frames.yaml                             |    6 +-
 cfg/conf.d/gazsim.yaml                             |    4 +-
 cfg/conf.d/imu.yaml                                |    2 +-
 cfg/conf.d/jaco.yaml                               |   87 +
 cfg/conf.d/joystick.yaml                           |   25 +
 cfg/conf.d/katana.yaml                             |   25 +-
 cfg/conf.d/laser-cluster.yaml                      |    2 +-
 cfg/conf.d/laser-filter.yaml                       |   37 +
 cfg/conf.d/laser-lines.yaml                        |    2 +-
 cfg/conf.d/laser.yaml                              |    4 +-
 cfg/conf.d/navgraph.yaml                           |    6 -
 cfg/conf.d/openni.yaml                             |    7 +
 cfg/conf.d/pantilt.yaml                            |    6 +-
 cfg/conf.d/pcl.yaml                                |   10 +
 cfg/conf.d/pcl_db.yaml                             |   12 +-
 cfg/conf.d/robotino.yaml                           |    6 +-
 cfg/conf.d/ros.yaml                                |   27 +
 cfg/conf.d/static_transforms.yaml                  |    4 +-
 cfg/conf.d/tabletop_objects.yaml                   |    2 +-
 cfg/examples/fake_localization.yaml                |    4 +-
 cfg/examples/tripod_kinect_static_transforms.yaml  |   20 +-
 etc/buildsys/btypes/config_sysinstall.mk           |    4 +-
 etc/buildsys/btypes/config_syswide.mk              |    4 +-
 etc/buildsys/cgal.mk                               |   14 +-
 etc/buildsys/clang.mk                              |    3 +
 etc/buildsys/clips.mk                              |    6 +
 etc/buildsys/config.mk                             |    9 +-
 etc/buildsys/eigen3.mk                             |    7 +-
 etc/buildsys/fvconf.mk                             |    5 +-
 etc/buildsys/gcc.mk                                |    4 +
 etc/buildsys/gui.mk                                |    9 +-
 etc/buildsys/interface.mk                          |    4 +-
 etc/buildsys/libxmlpp.mk                           |   35 +
 etc/buildsys/lua_check.mk                          |    2 +-
 etc/buildsys/protobuf_msgs.mk                      |    2 +-
 etc/buildsys/ros.mk                                |   46 +-
 etc/buildsys/rules.mk                              |   37 +-
 res/guis/skillgui/skillgui.ui                      |   21 +-
 res/guis/skillgui/skillgui_gtk2.ui                 |    4 +-
 res/guis/skillgui/skillgui_gtk2_nospinner.ui       |  618 +++++++
 res/openrave/ball_med.kinbody.xml                  |   13 +
 res/openrave/ball_small.kinbody.xml                |   13 +
 res/openrave/jaco.robot.xml                        |   20 +
 res/openrave/jaco_dual.robot.xml                   |   58 +
 res/openrave/separator.kinbody.xml                 |   14 +
 res/openrave/service_plate.kinbody.xml             |   60 +
 res/urdf/katana/gazebo.urdf.xacro                  |  108 ++
 res/urdf/katana/katana_300_6m180.urdf.xacro        |  305 ++++
 res/urdf/katana/transmissions.urdf.xacro           |   22 +
 res/webview/css/blackboard.css                     |    2 +-
 src/libs/Makefile                                  |    4 +-
 src/libs/aspect/inifins/pointcloud.cpp             |    8 +-
 src/libs/aspect/inifins/pointcloud.h               |    2 +-
 src/libs/aspect/inifins/tf.cpp                     |    4 +-
 src/libs/aspect/manager.cpp                        |    2 +-
 src/libs/aspect/tf.cpp                             |  131 ++-
 src/libs/aspect/tf.h                               |   15 +-
 src/libs/baseapp/run.cpp                           |   10 +-
 src/libs/baseapp/run.h                             |    6 +-
 src/libs/baseapp/timing_thread.cpp                 |  121 ++
 src/libs/baseapp/timing_thread.h                   |   70 +
 src/libs/blackboard/internal/instance_factory.cpp  |   15 +
 src/libs/blackboard/net/handler.cpp                |    4 +-
 src/libs/blackboard/net/handler.h                  |    2 +-
 src/libs/blackboard/net/messages.h                 |    2 +-
 src/libs/blackboard/remote.cpp                     |    2 +-
 src/libs/config/net_handler.cpp                    |    4 +-
 src/libs/config/netconf.cpp                        |   32 +-
 src/libs/config/netconf.h                          |    2 +-
 src/libs/config/sqlite.cpp                         |   23 +-
 src/libs/config/sqlite.h                           |    4 +-
 src/libs/config/yaml.cpp                           |   24 +-
 src/libs/config/yaml.h                             |    2 +-
 src/libs/config/yaml_node.h                        |    6 +-
 src/libs/core/threading/wait_condition.h           |    2 +
 src/libs/fvfilters/gauss.cpp                       |    5 +-
 src/libs/fvfilters/hipass.cpp                      |    5 +-
 src/libs/fvfilters/laplace.cpp                     |    5 +-
 src/libs/fvfilters/median.cpp                      |    5 +-
 src/libs/fvfilters/morphology/dilation.cpp         |    5 +-
 src/libs/fvfilters/morphology/erosion.cpp          |    5 +-
 src/libs/fvfilters/or.cpp                          |    5 +-
 src/libs/fvfilters/sharpen.cpp                     |    5 +-
 src/libs/fvfilters/sobel.cpp                       |    5 +-
 src/libs/fvfilters/threshold.cpp                   |    5 +-
 src/libs/gui_utils/throbber.cpp                    |  211 ---
 src/libs/gui_utils/throbber.h                      |   62 -
 src/libs/interfaces/.gitignore                     |    2 +
 src/libs/interfaces/EclipseDebuggerInterface.cpp   |  225 +++
 src/libs/interfaces/EclipseDebuggerInterface.h     |  100 ++
 src/libs/interfaces/EclipseDebuggerInterface.tolua |   61 +
 src/libs/interfaces/FacerInterface.cpp             |  291 ++++-
 src/libs/interfaces/FacerInterface.h               |   74 +-
 src/libs/interfaces/FacerInterface.tolua           |   30 +-
 src/libs/interfaces/FacerInterface.xml             |   22 +
 src/libs/interfaces/KeyValueInterface.cpp          |  388 +++++
 src/libs/interfaces/KeyValueInterface.h            |  114 ++
 src/libs/interfaces/KeyValueInterface.tolua        |   81 +
 src/libs/interfaces/KeyValueInterface.xml          |   26 +
 src/libs/interfaces/Laser1080Interface.cpp         |  250 +++
 src/libs/interfaces/Laser1080Interface.h           |   90 +
 src/libs/interfaces/Laser1080Interface.tolua       |   57 +
 src/libs/interfaces/Laser1080Interface.xml         |   20 +
 src/libs/interfaces/NavigatorInterface.cpp         |    4 +-
 src/libs/interfaces/NavigatorInterface.h           |    1 +
 src/libs/interfaces/NavigatorInterface.tolua       |    1 +
 src/libs/interfaces/NavigatorInterface.xml         |    3 +
 src/libs/interfaces/Position3DInterface.cpp        |   83 +-
 src/libs/interfaces/Position3DInterface.h          |   11 +
 src/libs/interfaces/Position3DInterface.tolua      |    3 +
 src/libs/interfaces/Position3DInterface.xml        |    6 +
 src/libs/interfaces/TransformInterface.cpp         |   40 +-
 src/libs/interfaces/TransformInterface.h           |    7 +
 src/libs/interfaces/TransformInterface.tolua       |    3 +
 src/libs/interfaces/TransformInterface.xml         |    4 +
 src/libs/interfaces/generator/cpp_generator.cpp    |   16 +-
 src/libs/interfaces/generator/type_checker.cpp     |    1 +
 src/libs/navgraph/Makefile                         |    1 +
 src/libs/navgraph/constraints/constraint_repo.cpp  |    2 +-
 .../navgraph/constraints/polygon_constraint.cpp    |    5 +
 src/libs/navgraph/generators/Makefile              |   16 +-
 src/libs/navgraph/generators/voronoi.cpp           |  246 ++-
 src/libs/navgraph/generators/voronoi.h             |   44 +-
 src/libs/navgraph/navgraph.cpp                     |   12 +-
 src/libs/navgraph/navgraph.mk                      |    5 +-
 src/libs/navgraph/navgraph_edge.cpp                |   15 +
 src/libs/navgraph/navgraph_path.cpp                |   25 +
 src/libs/navgraph/navgraph_path.h                  |    3 +
 src/libs/navgraph/search_state.h                   |    1 -
 src/libs/netcomm/fawkes/server_thread.cpp          |   81 +-
 src/libs/pcl_utils/utils.h                         |   29 +
 src/libs/protobuf_comm/message_register.cpp        |    6 +
 src/libs/tf/Makefile                               |   17 +-
 src/libs/tf/buffer_core.cpp                        | 1203 ++++++++++++++
 src/libs/tf/buffer_core.h                          |  228 +++
 src/libs/tf/static_cache.cpp                       |  154 ++
 src/libs/tf/tf.mk                                  |   13 +-
 src/libs/tf/tf.tolua                               |    2 +
 src/libs/tf/time_cache.cpp                         |  150 +-
 src/libs/tf/time_cache.h                           |  123 +-
 src/libs/tf/transform_listener.cpp                 |   54 +-
 src/libs/tf/transform_listener.h                   |   13 +-
 src/libs/tf/transform_publisher.cpp                |   41 +-
 src/libs/tf/transform_publisher.h                  |   13 +-
 src/libs/tf/transform_storage.h                    |  101 ++
 src/libs/tf/transformer.cpp                        | 1153 +++-----------
 src/libs/tf/transformer.h                          |  126 +--
 src/libs/tf/types.h                                |   25 +-
 src/libs/tf/utils.h                                |   25 +
 src/libs/utils/math/angle.h                        |    9 +-
 src/libs/utils/math/lines.h                        |    8 +
 src/libs/utils/math/polygon.h                      |  159 ++
 src/libs/utils/math/triangle.h                     |   74 +
 src/libs/webview/request_dispatcher.cpp            |   16 +-
 src/libs/webview/request_dispatcher.h              |    5 +-
 src/libs/webview/request_manager.cpp               |    4 +-
 src/libs/webview/request_manager.h                 |    2 +-
 src/libs/webview/server.cpp                        |    2 +-
 src/libs/webview/server.h                          |    2 +-
 src/lua/fawkes/fsm/jumpstate.lua                   |   14 +-
 src/lua/fawkes/fsm/skill_jumpstate.lua             |   42 +
 src/lua/fawkes/hsm.lua                             |    2 +-
 src/lua/fawkes/mathext.lua                         |   16 +
 src/lua/luaagent/agentenv.lua                      |   25 +-
 src/lua/luaagent/agenthsm.lua                      |    5 +
 src/lua/luaagent/jumpstates.lua                    |   16 +-
 src/lua/skiller/skill_jumpstate.lua                |  355 ----
 src/lua/skiller/skillhsm.lua                       |    7 +-
 src/lua/skiller/subskill_jumpstate.lua             |  389 +++++
 src/lua/skills/generic/align_at_table.lua          |    6 +-
 src/lua/skills/generic/back_off.lua                |   21 +-
 src/lua/skills/generic/goto.lua                    |   14 +-
 src/lua/skills/generic/jaco.lua                    |  320 ++++
 src/lua/skills/generic/jaco_bimanual.lua           |  204 +++
 src/lua/skills/generic/katana.lua                  |    8 +-
 src/lua/skills/generic/katana_rel.lua              |    8 +-
 src/lua/skills/generic/openrave/openrave.lua       |   83 +
 src/lua/skills/generic/openrave/or_object.lua      |  280 +++--
 src/plugins/Makefile                               |    8 +-
 src/plugins/amcl/Makefile                          |    4 +-
 src/plugins/amcl/amcl_plugin.cpp                   |   17 +
 src/plugins/amcl/amcl_thread.cpp                   |  205 +--
 src/plugins/amcl/amcl_thread.h                     |   37 +-
 src/plugins/amcl/map_lasergen_thread.cpp           |    6 +-
 src/plugins/amcl/ros_thread.cpp                    |  220 +++
 src/plugins/amcl/ros_thread.h                      |   92 +
 src/plugins/bumblebee2/calib/Makefile              |    4 +-
 src/plugins/clips-tf/clips_tf_thread.cpp           |    5 +-
 src/plugins/colli/act_thread.cpp                   |   67 -
 src/plugins/colli/act_thread.h                     |   11 -
 src/plugins/colli/colli_thread.cpp                 |   25 +-
 src/plugins/colli/search/og_laser.cpp              |    2 +-
 src/plugins/colli/visualization_thread.cpp         |    9 +-
 src/plugins/colli/visualization_thread.h           |    2 +
 src/plugins/dynamixel/Makefile                     |   14 +-
 src/plugins/dynamixel/driver_thread.cpp            |   48 +-
 src/plugins/dynamixel/driver_thread.h              |    4 +
 src/plugins/dynamixel/dynamixel_plugin.cpp         |    4 +
 .../interfaces/DynamixelServoInterface.cpp         |  202 +++-
 .../interfaces/DynamixelServoInterface.h_ext       |   57 +
 .../interfaces/DynamixelServoInterface.tolua       |   21 +
 .../interfaces/DynamixelServoInterface.xml         |    8 +
 src/plugins/dynamixel/servo_chain.cpp              |   48 +-
 src/plugins/dynamixel/servo_chain.h                |    3 +-
 src/plugins/eclipse-clp/eclipse_thread.cpp         |    1 +
 src/plugins/eclipse-clp/externals/blackboard.cpp   |   81 +-
 src/plugins/eclipse-clp/externals/blackboard.ecl   |    6 +-
 src/plugins/eclipse-clp/externals/blackboard.h     |    4 +-
 src/plugins/eclipse-clp/externals/config.ecl       |    8 -
 src/plugins/eclipse-clp/externals/quaternions.ecl  |    8 -
 .../eclipse-clp/externals/rcsoft_map_graph.ecl     |    7 -
 src/plugins/eclipse-clp/utils/skiller.ecl          |    4 +
 src/plugins/eclipse-clp/utils/timing.ecl           |   40 +
 .../examples/tf_example/tf_example_thread.cpp      |   21 +-
 .../examples/tf_example/tf_example_thread.h        |    2 +
 .../gazsim-robotino/gazsim_robotino_thread.cpp     |   10 +-
 .../gazsim-robotino/gazsim_robotino_thread.h       |    2 +
 .../gazsim_vis_localization_thread.cpp             |   18 +
 src/plugins/gazebo/msgs/LightSignalDetection.proto |   56 +
 src/plugins/imu/imu_plugin.cpp                     |    4 +
 src/plugins/jaco/Makefile                          |   56 +
 src/plugins/jaco/act_thread.cpp                    |  338 ++++
 src/plugins/jaco/act_thread.h                      |   67 +
 src/plugins/jaco/arm.h                             |  140 ++
 src/plugins/jaco/arm_dummy.cpp                     |  205 +++
 src/plugins/jaco/arm_dummy.h                       |   76 +
 src/plugins/jaco/arm_kindrv.cpp                    |  358 ++++
 src/plugins/jaco/arm_kindrv.h                      |   78 +
 src/plugins/jaco/bimanual_act_thread.cpp           |  143 ++
 src/plugins/jaco/bimanual_act_thread.h             |   60 +
 src/plugins/jaco/bimanual_goto_thread.cpp          |  482 ++++++
 src/plugins/jaco/bimanual_goto_thread.h            |   89 +
 src/plugins/jaco/bimanual_openrave_thread.cpp      |  705 ++++++++
 src/plugins/jaco/bimanual_openrave_thread.h        |   91 +
 src/plugins/jaco/goto_thread.cpp                   |  552 +++++++
 src/plugins/jaco/goto_thread.h                     |   86 +
 src/plugins/jaco/info_thread.cpp                   |   98 ++
 src/plugins/jaco/info_thread.h                     |   64 +
 .../jaco/interfaces/JacoBimanualInterface.cpp      | 1190 +++++++++++++
 .../jaco/interfaces/JacoBimanualInterface.h_ext    |  268 +++
 .../jaco/interfaces/JacoBimanualInterface.tolua    |  156 ++
 .../jaco/interfaces/JacoBimanualInterface.xml      |   63 +
 src/plugins/jaco/interfaces/JacoInterface.cpp      | 1740 ++++++++++++++++++++
 src/plugins/jaco/interfaces/JacoInterface.h_ext    |  411 +++++
 src/plugins/jaco/interfaces/JacoInterface.tolua    |  216 +++
 src/plugins/jaco/interfaces/JacoInterface.xml      |   94 ++
 src/plugins/jaco/interfaces/Makefile               |   23 +
 src/plugins/jaco/jaco.mk                           |   23 +
 src/plugins/jaco/jaco_plugin.cpp                   |  140 ++
 src/plugins/jaco/jaco_plugin.h                     |   34 +
 src/plugins/jaco/openrave_base_thread.cpp          |  162 ++
 src/plugins/jaco/openrave_base_thread.h            |  116 ++
 src/plugins/jaco/openrave_thread.cpp               |  766 +++++++++
 src/plugins/jaco/openrave_thread.h                 |   85 +
 src/plugins/jaco/types.h                           |  123 ++
 src/plugins/joystick/Makefile                      |    2 +-
 src/plugins/joystick/acquisition_thread.cpp        |   57 +-
 src/plugins/joystick/acquisition_thread.h          |    3 +
 src/plugins/joystick/joystick_teleop_thread.cpp    |  107 +-
 src/plugins/joystick/joystick_teleop_thread.h      |   10 +
 src/plugins/katana/Makefile                        |    5 +-
 src/plugins/katana/act_thread.cpp                  |  249 ++-
 src/plugins/katana/act_thread.h                    |   29 +-
 src/plugins/katana/calib_thread.cpp                |    3 +
 src/plugins/katana/controller_kni.h                |    5 +
 src/plugins/katana/controller_openrave.cpp         |    9 +-
 src/plugins/katana/controller_openrave.h           |   14 +-
 src/plugins/katana/goto_openrave_thread.cpp        |   37 +-
 src/plugins/katana/goto_openrave_thread.h          |   17 +-
 src/plugins/katana/goto_thread.cpp                 |    4 +
 src/plugins/katana/gripper_thread.cpp              |    4 +
 src/plugins/katana/motion_thread.h                 |    4 +-
 src/plugins/katana/motor_control_thread.cpp        |    5 +-
 src/plugins/laser-cluster/laser-cluster-thread.cpp |   53 +-
 src/plugins/laser-filter/Makefile                  |    4 +-
 src/plugins/laser-filter/filter_thread.cpp         |  112 +-
 src/plugins/laser-filter/filter_thread.h           |   10 +-
 src/plugins/laser-filter/filters/1080to360.cpp     |   73 +
 src/plugins/laser-filter/filters/1080to360.h       |   39 +
 src/plugins/laser-filter/filters/filter.cpp        |    7 +-
 src/plugins/laser-filter/filters/map_filter.cpp    |  165 ++
 src/plugins/laser-filter/filters/map_filter.h      |   61 +
 src/plugins/laser-filter/filters/min_circle.cpp    |    5 +-
 src/plugins/laser-lines/laser-lines-thread.cpp     |    9 +
 src/plugins/laser-pointclouds/Makefile             |    4 +-
 .../laser-pointclouds/laser_pointcloud_thread.cpp  |   87 +-
 .../laser-pointclouds/laser_pointcloud_thread.h    |    6 +-
 src/plugins/laser/Makefile                         |    3 +-
 src/plugins/laser/sensor_thread.cpp                |   14 +-
 src/plugins/laser/sensor_thread.h                  |    6 +-
 src/plugins/laser/sick_tim55x_common_aqt.cpp       |   50 +-
 src/plugins/laser/sick_tim55x_common_aqt.h         |    5 +
 src/plugins/laser/sick_tim55x_ethernet_aqt.cpp     |   41 +-
 src/plugins/laser/sick_tim55x_ethernet_aqt.h       |    2 +
 src/plugins/laser/sick_tim55x_usb_aqt.cpp          |    3 +-
 src/plugins/mongodb/mongodb.mk                     |   21 +-
 src/plugins/mongodb/mongodb_thread.cpp             |   20 +
 src/plugins/mongodb_log/mongodb_log_tf_thread.cpp  |   54 +-
 src/plugins/mongodb_log/mongodb_log_tf_thread.h    |    2 +-
 src/plugins/mongodb_log/tools/Makefile             |    2 +-
 .../mongodb_log/tools/ffmongodb_save_imgs.cpp      |    4 +
 src/plugins/nao/naogui/Makefile                    |    4 +-
 src/plugins/navgraph-clusters/Makefile             |   10 +-
 .../interfaces/NavGraphGeneratorInterface.cpp      |    2 +-
 .../interfaces/NavGraphGeneratorInterface.h_ext    |   88 +-
 .../interfaces/NavGraphGeneratorInterface.xml      |   88 +-
 .../navgraph_generator_thread.cpp                  |  101 +-
 src/plugins/navgraph/navgraph_thread.cpp           |  163 ++-
 src/plugins/navgraph/navgraph_thread.h             |    6 +-
 src/plugins/navgraph/visualization_thread.cpp      |   66 +-
 src/plugins/navgraph/visualization_thread.h        |    2 +
 src/plugins/openni/pcl_frombuf_thread.cpp          |    2 +-
 src/plugins/openni/pointcloud_thread.cpp           |   14 +-
 src/plugins/openni/pointcloud_thread.h             |    3 +
 src/plugins/openprs/mod_config.cpp                 |    4 +
 src/plugins/openrave/Makefile                      |    2 +-
 src/plugins/openrave/aspect/openrave_connector.h   |   86 +-
 src/plugins/openrave/environment.cpp               |  350 ++++-
 src/plugins/openrave/environment.h                 |   38 +-
 .../openrave/interfaces/OpenRaveInterface.cpp      |  165 ++-
 .../openrave/interfaces/OpenRaveInterface.h_ext    |   50 +-
 .../openrave/interfaces/OpenRaveInterface.tolua    |   19 +-
 .../openrave/interfaces/OpenRaveInterface.xml      |    8 +-
 src/plugins/openrave/manipulator.cpp               |   36 +-
 src/plugins/openrave/manipulator.h                 |   30 +-
 src/plugins/openrave/manipulators/jaco.kinbody.xml |  327 ++++
 src/plugins/openrave/manipulators/katana6M180.cpp  |   21 +-
 src/plugins/openrave/manipulators/katana6M180.h    |    3 +-
 src/plugins/openrave/manipulators/kinova_jaco.cpp  |  131 ++
 src/plugins/openrave/manipulators/kinova_jaco.h    |   48 +
 .../openrave/manipulators/neuronics_katana.cpp     |   21 +-
 .../openrave/manipulators/neuronics_katana.h       |    3 +-
 src/plugins/openrave/message_handler_thread.cpp    |   35 +-
 src/plugins/openrave/openrave.mk                   |    5 +-
 src/plugins/openrave/openrave_thread.cpp           |  139 ++-
 src/plugins/openrave/openrave_thread.h             |   55 +-
 src/plugins/openrave/qa/qa_manip.cpp               |    2 +-
 src/plugins/openrave/qa/qa_modules.cpp             |    6 +-
 src/plugins/openrave/qa/qa_robot.cpp               |    8 +-
 src/plugins/openrave/robot.cpp                     |  372 ++++-
 src/plugins/openrave/robot.h                       |   56 +-
 src/plugins/openrave/types.h                       |   29 +-
 src/plugins/pantilt/robotis/rx28_thread.cpp        |    2 +-
 .../perception/pcl-db/mongodb_tf_transformer.cpp   |    2 +-
 src/plugins/perception/tabletop-objects/Makefile   |    6 +
 .../tabletop-objects/tabletop_objects_thread.cpp   |   29 +-
 .../tabletop-objects/tabletop_objects_thread.h     |    1 +
 .../tabletop-objects/visualization_thread.cpp      |   12 +-
 .../tabletop-objects/visualization_thread.h        |    1 +
 src/plugins/refboxcomm/Makefile                    |    7 +-
 src/plugins/robot_state_publisher/Makefile         |    7 +-
 src/plugins/robotino/com_thread.cpp                |    1 +
 src/plugins/robotino/ir_pcl_thread.cpp             |    2 +-
 src/plugins/robotino/ir_pcl_thread.h               |    3 +-
 src/plugins/robotino/robotino.mk                   |   33 +-
 src/plugins/ros/Makefile                           |   36 +-
 src/plugins/ros/clock_plugin.cpp                   |   45 +
 src/plugins/ros/clock_thread.cpp                   |   91 +
 src/plugins/ros/clock_thread.h                     |   65 +
 src/plugins/ros/laserscan_thread.cpp               |  151 ++-
 src/plugins/ros/laserscan_thread.h                 |    6 +-
 src/plugins/ros/move_base_thread.cpp               |    9 +-
 src/plugins/ros/move_base_thread.h                 |    4 +-
 src/plugins/ros/navigator_thread.cpp               |    2 +-
 src/plugins/ros/odometry_thread.cpp                |    2 +-
 src/plugins/ros/tf_thread.cpp                      |  291 +++-
 src/plugins/ros/tf_thread.h                        |   31 +-
 src/plugins/skiller/exec_thread.cpp                |    5 +-
 .../static_transforms/static_transforms_thread.cpp |   50 +-
 .../static_transforms/static_transforms_thread.h   |    4 -
 .../webview-ptzcam/webview-ptzcam-processor.cpp    |    1 +
 .../webview-ptzcam/webview-ptzcam-thread.cpp       |    8 +-
 src/plugins/webview/blackboard_processor.cpp       |    9 +-
 src/plugins/webview/blackboard_processor.h         |    2 +
 src/tools/eclipse_debugger/Makefile                |    7 +-
 src/tools/eclipse_debugger/eclipse_debugger.cpp    |    1 -
 src/tools/eclipse_debugger/eclipse_debugger.h      |    1 -
 src/tools/eclipse_debugger/main.cpp                |   12 +
 src/tools/ffswitch/Makefile                        |   28 +
 src/tools/ffswitch/ffswitch.txt                    |   57 +
 src/tools/ffswitch/main.cpp                        |  103 ++
 src/tools/lasergui/Makefile                        |    3 +-
 src/tools/lasergui/laser_drawing_area.cpp          |    9 +
 src/tools/lasergui/laser_drawing_area.h            |    1 +
 src/tools/lasergui/lasergui.cpp                    |    9 +-
 src/tools/refboxrep/Makefile                       |    7 +-
 src/tools/set_pose/Makefile                        |    2 +-
 src/tools/set_pose/ffset_pose.cpp                  |   17 +-
 src/tools/skillgui/main.cpp                        |    6 +-
 src/tools/skillgui/skillgui.cpp                    |   33 +-
 src/tools/skillgui/skillgui.h                      |    9 +-
 src/tools/vision/Makefile                          |    5 +-
 397 files changed, 22649 insertions(+), 3949 deletions(-)
 create mode 100644 cfg/conf.d/jaco.yaml
 create mode 100644 cfg/conf.d/laser-filter.yaml
 create mode 100644 cfg/conf.d/pcl.yaml
 create mode 100644 etc/buildsys/libxmlpp.mk
 create mode 100644 res/guis/skillgui/skillgui_gtk2_nospinner.ui
 create mode 100644 res/openrave/ball_med.kinbody.xml
 create mode 100644 res/openrave/ball_small.kinbody.xml
 create mode 100644 res/openrave/jaco.robot.xml
 create mode 100644 res/openrave/jaco_dual.robot.xml
 create mode 100644 res/openrave/separator.kinbody.xml
 create mode 100644 res/openrave/service_plate.kinbody.xml
 create mode 100644 res/urdf/katana/gazebo.urdf.xacro
 create mode 100644 res/urdf/katana/katana_300_6m180.urdf.xacro
 create mode 100644 res/urdf/katana/transmissions.urdf.xacro
 create mode 100644 src/libs/baseapp/timing_thread.cpp
 create mode 100644 src/libs/baseapp/timing_thread.h
 delete mode 100644 src/libs/gui_utils/throbber.cpp
 delete mode 100644 src/libs/gui_utils/throbber.h
 create mode 100644 src/libs/interfaces/EclipseDebuggerInterface.cpp
 create mode 100644 src/libs/interfaces/EclipseDebuggerInterface.h
 create mode 100644 src/libs/interfaces/EclipseDebuggerInterface.tolua
 create mode 100644 src/libs/interfaces/KeyValueInterface.cpp
 create mode 100644 src/libs/interfaces/KeyValueInterface.h
 create mode 100644 src/libs/interfaces/KeyValueInterface.tolua
 create mode 100644 src/libs/interfaces/KeyValueInterface.xml
 create mode 100644 src/libs/interfaces/Laser1080Interface.cpp
 create mode 100644 src/libs/interfaces/Laser1080Interface.h
 create mode 100644 src/libs/interfaces/Laser1080Interface.tolua
 create mode 100644 src/libs/interfaces/Laser1080Interface.xml
 create mode 100644 src/libs/tf/buffer_core.cpp
 create mode 100644 src/libs/tf/buffer_core.h
 create mode 100644 src/libs/tf/static_cache.cpp
 create mode 100644 src/libs/tf/transform_storage.h
 create mode 100644 src/libs/utils/math/polygon.h
 create mode 100644 src/libs/utils/math/triangle.h
 create mode 100644 src/lua/fawkes/fsm/skill_jumpstate.lua
 delete mode 100644 src/lua/skiller/skill_jumpstate.lua
 create mode 100644 src/lua/skiller/subskill_jumpstate.lua
 create mode 100644 src/lua/skills/generic/jaco.lua
 create mode 100644 src/lua/skills/generic/jaco_bimanual.lua
 create mode 100644 src/lua/skills/generic/openrave/openrave.lua
 create mode 100644 src/plugins/amcl/ros_thread.cpp
 create mode 100644 src/plugins/amcl/ros_thread.h
 create mode 100644 src/plugins/eclipse-clp/utils/timing.ecl
 create mode 100644 src/plugins/gazebo/msgs/LightSignalDetection.proto
 create mode 100644 src/plugins/jaco/Makefile
 create mode 100644 src/plugins/jaco/act_thread.cpp
 create mode 100644 src/plugins/jaco/act_thread.h
 create mode 100644 src/plugins/jaco/arm.h
 create mode 100644 src/plugins/jaco/arm_dummy.cpp
 create mode 100644 src/plugins/jaco/arm_dummy.h
 create mode 100644 src/plugins/jaco/arm_kindrv.cpp
 create mode 100644 src/plugins/jaco/arm_kindrv.h
 create mode 100644 src/plugins/jaco/bimanual_act_thread.cpp
 create mode 100644 src/plugins/jaco/bimanual_act_thread.h
 create mode 100644 src/plugins/jaco/bimanual_goto_thread.cpp
 create mode 100644 src/plugins/jaco/bimanual_goto_thread.h
 create mode 100644 src/plugins/jaco/bimanual_openrave_thread.cpp
 create mode 100644 src/plugins/jaco/bimanual_openrave_thread.h
 create mode 100644 src/plugins/jaco/goto_thread.cpp
 create mode 100644 src/plugins/jaco/goto_thread.h
 create mode 100644 src/plugins/jaco/info_thread.cpp
 create mode 100644 src/plugins/jaco/info_thread.h
 create mode 100644 src/plugins/jaco/interfaces/JacoBimanualInterface.cpp
 create mode 100644 src/plugins/jaco/interfaces/JacoBimanualInterface.h_ext
 create mode 100644 src/plugins/jaco/interfaces/JacoBimanualInterface.tolua
 create mode 100644 src/plugins/jaco/interfaces/JacoBimanualInterface.xml
 create mode 100644 src/plugins/jaco/interfaces/JacoInterface.cpp
 create mode 100644 src/plugins/jaco/interfaces/JacoInterface.h_ext
 create mode 100644 src/plugins/jaco/interfaces/JacoInterface.tolua
 create mode 100644 src/plugins/jaco/interfaces/JacoInterface.xml
 create mode 100644 src/plugins/jaco/interfaces/Makefile
 create mode 100644 src/plugins/jaco/jaco.mk
 create mode 100644 src/plugins/jaco/jaco_plugin.cpp
 create mode 100644 src/plugins/jaco/jaco_plugin.h
 create mode 100644 src/plugins/jaco/openrave_base_thread.cpp
 create mode 100644 src/plugins/jaco/openrave_base_thread.h
 create mode 100644 src/plugins/jaco/openrave_thread.cpp
 create mode 100644 src/plugins/jaco/openrave_thread.h
 create mode 100644 src/plugins/jaco/types.h
 create mode 100644 src/plugins/laser-filter/filters/1080to360.cpp
 create mode 100644 src/plugins/laser-filter/filters/1080to360.h
 create mode 100644 src/plugins/laser-filter/filters/map_filter.cpp
 create mode 100644 src/plugins/laser-filter/filters/map_filter.h
 create mode 100644 src/plugins/openrave/manipulators/jaco.kinbody.xml
 create mode 100644 src/plugins/openrave/manipulators/kinova_jaco.cpp
 create mode 100644 src/plugins/openrave/manipulators/kinova_jaco.h
 create mode 100644 src/plugins/ros/clock_plugin.cpp
 create mode 100644 src/plugins/ros/clock_thread.cpp
 create mode 100644 src/plugins/ros/clock_thread.h
 create mode 100644 src/tools/ffswitch/Makefile
 create mode 100644 src/tools/ffswitch/ffswitch.txt
 create mode 100644 src/tools/ffswitch/main.cpp


- *Diffs* -------------------------------------------------------------

- *commit* a06118fee013af4465c122a4c77b57dc2b6f0269 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Feb 3 15:04:05 2014 +0100
Subject: syncpoint: add SyncPoint library

 src/libs/Makefile                                  |    3 +-
 src/libs/aspect/Makefile                           |    2 +-
 src/libs/aspect/inifins/syncpoint_manager.cpp      |   70 +++++++++
 .../inifins/syncpoint_manager.h}                   |   31 ++--
 src/libs/aspect/manager.cpp                        |    7 +-
 src/libs/aspect/manager.h                          |    4 +-
 src/libs/aspect/syncpoint_manager.cpp              |   62 ++++++++
 .../syncpoint_manager.h}                           |   30 ++--
 src/libs/baseapp/Makefile                          |    2 +-
 src/libs/baseapp/run.cpp                           |    7 +-
 .../rrd/aspect => libs/syncpoint}/Makefile         |   28 ++--
 src/libs/syncpoint/exceptions.h                    |  160 ++++++++++++++++++++
 src/libs/syncpoint/syncpoint.cpp                   |  118 ++++++++++++++
 src/libs/syncpoint/syncpoint.h                     |   68 +++++++++
 src/libs/syncpoint/syncpoint_manager.cpp           |  132 ++++++++++++++++
 .../fam_thread.h => syncpoint/syncpoint_manager.h} |   49 ++++---
 16 files changed, 707 insertions(+), 66 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/Makefile b/src/libs/Makefile
index 14d0b54..6a50896 100644
--- a/src/libs/Makefile
+++ b/src/libs/Makefile
@@ -20,7 +20,7 @@ include $(BUILDSYSDIR)/fvconf.mk
 SUBDIRS = core utils interface netcomm blackboard interfaces config logging tf \
 	  plugin lua aspect webview gui_utils baseapp navgraph \
 	  fvutils fvcams fvmodels fvfilters fvclassifiers fvstereo fvwidgets \
-	  kdl_parser protobuf_comm protobuf_clips pcl_utils
+	  kdl_parser protobuf_comm protobuf_clips pcl_utils syncpoint 
 
 ifeq ($(HAVE_SIFT),1)
   SUBDIRS += extlib/sift
@@ -65,6 +65,7 @@ endif
 protobuf_clips: core logging protobuf_comm
 pcl_utils: core tf
 kdl_parser: core
+syncpoint: core 
 
 include $(BUILDSYSDIR)/rules.mk
 include $(LIBSRCDIR)/extlibs.mk
diff --git a/src/libs/aspect/Makefile b/src/libs/aspect/Makefile
index 3bf9541..da5c69d 100644
--- a/src/libs/aspect/Makefile
+++ b/src/libs/aspect/Makefile
@@ -20,7 +20,7 @@ include $(BUILDCONFDIR)/tf/tf.mk
 include $(BUILDSYSDIR)/pcl.mk
 
 LIBS_libfawkesaspects = fawkescore fawkesutils fawkesblackboard fawkesnetcomm \
-			fawkesconfig fawkesplugin fawkeslogging
+			fawkesconfig fawkesplugin fawkeslogging fawkessyncpoint
 
 ifneq ($(HAVE_WEBVIEW),1)
   OBJS_FILTER_OUT += $(subst $(SRCDIR)/,,$(wildcard $(SRCDIR)/webview.cpp $(SRCDIR)/inifins/webview.cpp))
diff --git a/src/libs/aspect/manager.cpp b/src/libs/aspect/manager.cpp
index 86a4637..e5058f6 100644
--- a/src/libs/aspect/manager.cpp
+++ b/src/libs/aspect/manager.cpp
@@ -37,6 +37,7 @@
 #include <aspect/inifins/time_source.h>
 #include <aspect/inifins/vision_master.h>
 #include <aspect/inifins/vision.h>
+#include <aspect/inifins/syncpoint_manager.h>
 #ifdef HAVE_WEBVIEW
 #  include <aspect/inifins/webview.h>
 #endif
@@ -221,6 +222,7 @@ AspectManager::prepare_finalize(Thread *thread)
  * @param service_browser service browser for NetworkAspect
  * @param pmanager plugin manager for PluginDirectorAspect
  * @param tf_listener transformer for TransformAspect
+ * @param syncpoint_manager manager for SyncPointManagerAspect
  */
 void
 AspectManager::register_default_inifins(BlackBoard *blackboard,
@@ -236,7 +238,8 @@ AspectManager::register_default_inifins(BlackBoard *blackboard,
 					ServicePublisher *service_publisher,
 					ServiceBrowser *service_browser,
 					PluginManager *pmanager,
-					tf::Transformer *tf_listener)
+					tf::Transformer *tf_listener,
+					SyncPointManager *syncpoint_manager)
 {
   if (! __default_inifins.empty())  return;
 
@@ -258,6 +261,7 @@ AspectManager::register_default_inifins(BlackBoard *blackboard,
   TimeSourceAspectIniFin *ts_aif = new TimeSourceAspectIniFin(clock);
   VisionMasterAspectIniFin *vm_aif = new VisionMasterAspectIniFin();
   VisionAspectIniFin *vis_aif = new VisionAspectIniFin(vm_aif);
+  SyncPointManagerAspectIniFin *spm_aif = new SyncPointManagerAspectIniFin(syncpoint_manager);
 #ifdef HAVE_WEBVIEW
   WebviewAspectIniFin *web_aif = new WebviewAspectIniFin();
 #endif
@@ -284,6 +288,7 @@ AspectManager::register_default_inifins(BlackBoard *blackboard,
   __default_inifins[ts_aif->get_aspect_name()] = ts_aif;
   __default_inifins[vm_aif->get_aspect_name()] = vm_aif;
   __default_inifins[vis_aif->get_aspect_name()] = vis_aif;
+  __default_inifins[spm_aif->get_aspect_name()] = spm_aif;
 #ifdef HAVE_WEBVIEW
   __default_inifins[web_aif->get_aspect_name()] = web_aif;
 #endif
diff --git a/src/libs/aspect/manager.h b/src/libs/aspect/manager.h
index 561c5ba..39a57c4 100644
--- a/src/libs/aspect/manager.h
+++ b/src/libs/aspect/manager.h
@@ -51,6 +51,7 @@ class LoggerEmployer;
 class BlockedTimingExecutor;
 class MainLoopEmployer;
 class AspectIniFin;
+class SyncPointManager;
 
 namespace tf {
   class Transformer;
@@ -83,7 +84,8 @@ class AspectManager : public ThreadInitializer, public ThreadFinalizer
 				ServicePublisher *service_publisher,
 				ServiceBrowser *service_browser,
 				PluginManager *pmanager,
-				tf::Transformer *tf_listener);
+				tf::Transformer *tf_listener,
+				SyncPointManager *syncpoint_manager);
 
  private:
   std::map<std::string, AspectIniFin *> __inifins;
diff --git a/src/libs/baseapp/Makefile b/src/libs/baseapp/Makefile
index 3eeadf2..29b4554 100644
--- a/src/libs/baseapp/Makefile
+++ b/src/libs/baseapp/Makefile
@@ -24,7 +24,7 @@ LDFLAGS += $(LDFLAGS_LIBDAEMON) $(LDFLAGS_TF)
 
 LIBS_libfawkesbaseapp = stdc++ pthread fawkescore fawkesutils fawkesconfig \
 			fawkesblackboard fawkesplugin fawkesnetcomm \
-			fawkesaspects fawkeslogging
+			fawkesaspects fawkeslogging fawkessyncpoint
 
 REQ_BOOST_LIBS = system
 HAVE_BOOST_LIBS = $(call boost-have-libs,$(REQ_BOOST_LIBS))
diff --git a/src/libs/baseapp/run.cpp b/src/libs/baseapp/run.cpp
index 1a60d72..a715d1e 100644
--- a/src/libs/baseapp/run.cpp
+++ b/src/libs/baseapp/run.cpp
@@ -48,6 +48,7 @@
 #include <plugin/manager.h>
 #include <plugin/net/handler.h>
 #include <aspect/manager.h>
+#include <syncpoint/syncpoint_manager.h>
 #ifdef HAVE_TF
 #  include <tf/transform_listener.h>
 #  include <tf/transformer.h>
@@ -89,6 +90,7 @@ InitOptions               * init_options = NULL;
 tf::Transformer           * tf_transformer = NULL;
 tf::TransformListener     * tf_listener = NULL;
 Time                      * start_time = NULL;
+SyncPointManager          * syncpoint_manager = NULL;
 #ifdef HAVE_LOGGING_FD_REDIRECT
 LogFileDescriptorToLog    * log_fd_redirect_stderr_ = NULL;
 LogFileDescriptorToLog    * log_fd_redirect_stdout_ = NULL;
@@ -354,6 +356,8 @@ init(InitOptions options, int & retval)
   aspect_manager     = new AspectManager();
   thread_manager     = new ThreadManager(aspect_manager, aspect_manager);
 
+  syncpoint_manager  = new SyncPointManager();
+
   plugin_manager     = new PluginManager(thread_manager, config,
 					 "/fawkes/meta_plugins/",
 					 options.plugin_module_flags(),
@@ -394,7 +398,8 @@ init(InitOptions options, int & retval)
 					   network_manager->nnresolver(),
 					   network_manager->service_publisher(),
 					   network_manager->service_browser(),
-					   plugin_manager, tf_transformer);
+					   plugin_manager, tf_transformer,
+					   syncpoint_manager);
 
   retval = 0;
   return true;

- *commit* a3ed12bb4662f3eecc7f1ca044ef4d9c4c4dd801 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon May 5 15:42:19 2014 +0200
Subject: syncpoint: add unit tests

 .../{interfaces/qa => syncpoint/tests}/Makefile    |   18 +-
 src/libs/syncpoint/tests/test_syncpoint.cpp        |  179 ++++++++++++++++++++
 2 files changed, 188 insertions(+), 9 deletions(-)


- *commit* 5be9ca5fc46ebafc8c653e8845829a86a1542305 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon May 5 15:56:39 2014 +0200
Subject: syncpoint: add two simple test plugins

 src/plugins/Makefile                               |    3 +-
 .../syncpoint_test-emitter}/Makefile               |   18 +++--
 .../syncpoint_test_emitter_plugin.cpp}             |   22 +++---
 .../syncpoint_test_emitter_thread.cpp              |   68 ++++++++++++++++
 .../syncpoint_test_emitter_thread.h}               |   35 ++++----
 .../{procrrd => syncpoint_test-waiter}/Makefile    |   29 +++----
 .../syncpoint_test_waiter_plugin.cpp}              |   22 +++---
 .../syncpoint_test_waiter_thread.cpp               |   85 ++++++++++++++++++++
 .../syncpoint_test_waiter_thread.h}                |   34 ++++----
 9 files changed, 235 insertions(+), 81 deletions(-)

_Diff for modified files_:
diff --git a/src/plugins/Makefile b/src/plugins/Makefile
index caee20b..9844ea3 100644
--- a/src/plugins/Makefile
+++ b/src/plugins/Makefile
@@ -28,7 +28,8 @@ SUBDIRS	= bbsync bblogger webview ttmainloop rrd rrdweb \
 	  clips-tf openprs openprs-agent eclipse-clp \
 	  mongodb mongodb_log \
 	  openni refboxcomm ros player xmlrpc gossip \
-	  robot_state_publisher gazebo dynamixel navgraph-interactive
+	  robot_state_publisher gazebo dynamixel navgraph-interactive \
+	  syncpoint_test-emitter syncpoint_test-waiter
 
 include $(BUILDSYSDIR)/rules.mk
 

- *commit* 4892df65ea09d66ab57a17bb8d2e3712a2d62a12 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Tue May 20 11:25:07 2014 +0200
Subject: syncpoint: use mutexes in SyncPoint and SyncPointManager

 src/libs/syncpoint/syncpoint.cpp         |   27 +++++++++++++++++++++------
 src/libs/syncpoint/syncpoint.h           |    4 +++-
 src/libs/syncpoint/syncpoint_manager.cpp |   24 +++++++++++++++++++++---
 src/libs/syncpoint/syncpoint_manager.h   |    3 +++
 4 files changed, 48 insertions(+), 10 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 56242e6..d0b815d 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -49,17 +49,25 @@ namespace fawkes {
  */
 SyncPoint::SyncPoint(const char * identifier)
     : identifier_(identifier),
-      wait_condition(WaitCondition())
+      mutex(new Mutex()),
+      wait_condition(new WaitCondition(mutex))
 {
-  if (!strcmp(identifier, ""))
+  if (!strcmp(identifier, "")) {
+    delete wait_condition;
+    delete mutex;
     throw SyncPointInvalidIdentifierException(identifier);
-  if (strncmp(identifier, "/", 1))
+  }
+  if (strncmp(identifier, "/", 1)) {
+    delete wait_condition;
+    delete mutex;
     throw SyncPointInvalidIdentifierException(identifier);
+  }
 }
 
 SyncPoint::~SyncPoint()
 {
-
+  delete wait_condition;
+  delete mutex;
 }
 
 /**
@@ -98,10 +106,13 @@ SyncPoint::operator<(const SyncPoint &other) const
 void
 SyncPoint::emit(const char * component)
 {
+  mutex->lock();
   if (!watchers.count(component)) {
+    mutex->unlock();
     throw SyncPointNonWatcherCalledEmitException(component, get_identifier());
   }
-  wait_condition.wake_all();
+  wait_condition->wake_all();
+  mutex->unlock();
 }
 
 /** Wait until SyncPoint is emitted
@@ -109,10 +120,14 @@ SyncPoint::emit(const char * component)
  */
 void
 SyncPoint::wait(const char * component) {
+  mutex->lock();
+  // check if calling component is registered for this SyncPoint
   if (!watchers.count(component)) {
+    mutex->unlock();
     throw SyncPointNonWatcherCalledWaitException(component, get_identifier());
   }
-  wait_condition.wait();
+  wait_condition->wait();
+  mutex->unlock();
 }
 
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 231c325..efa7067 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -24,6 +24,7 @@
 
 #include <interface/interface.h>
 #include <syncpoint/syncpoint_manager.h>
+#include <core/threading/mutex.h>
 #include <core/threading/wait_condition.h>
 
 #include <set>
@@ -60,7 +61,8 @@ class SyncPoint
     const char * identifier_;
     std::set<const char *> watchers;
 
-    WaitCondition wait_condition;
+    Mutex *mutex;
+    WaitCondition *wait_condition;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 7c43ebf..6ba24a9 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -41,11 +41,13 @@ namespace fawkes {
  */
 
 SyncPointManager::SyncPointManager()
+: mutex(new Mutex())
 {
 }
 
 SyncPointManager::~SyncPointManager()
 {
+  delete mutex;
 }
 
 /**
@@ -61,20 +63,32 @@ SyncPointManager::~SyncPointManager()
 RefPtr<SyncPoint>
 SyncPointManager::get_syncpoint(const char * component, const char * identifier)
 {
-  if (!strcmp(component, ""))
+  mutex->lock();
+  if (!strcmp(component, "")) {
+    mutex->unlock();
     throw SyncPointInvalidComponentException(component, identifier);
+  }
   // insert a new SyncPoint if no SyncPoint with the same identifier exists,
   // otherwise, use that SyncPoint
-  std::pair<std::set<RefPtr<SyncPoint> >::iterator,bool> ret = syncpoints_.insert(
-      RefPtr<SyncPoint>(new SyncPoint(identifier)));
+  std::pair<std::set<RefPtr<SyncPoint> >::iterator,bool> ret;
+  try {
+  ret = syncpoints_.insert(RefPtr<SyncPoint>(new SyncPoint(identifier)));
+  } catch (const SyncPointInvalidIdentifierException &e) {
+    mutex->unlock();
+    throw;
+  }
+
   std::set<RefPtr<SyncPoint> >::iterator it = ret.first;
 
   // add component to the set of watchers
   // check if component is already a watcher
   // insert returns a pair whose second element is false if element already exists
   if (!(*it)->watchers.insert(component).second) {
+    mutex->unlock();
     throw SyncPointAlreadyOpenedException(component, identifier);
   }
+  mutex->unlock();
+
   return *it;
 }
 
@@ -91,15 +105,19 @@ SyncPointManager::get_syncpoint(const char * component, const char * identifier)
 void
 SyncPointManager::release_syncpoint(const char * component, RefPtr<SyncPoint> sync_point)
 {
+  mutex->lock();
   std::set<RefPtr<SyncPoint> >::iterator sp_it = syncpoints_.find(
       sync_point);
   if (sp_it == syncpoints_.end()) {
+    mutex->unlock();
     throw SyncPointReleasedDoesNotExistException(component, sync_point->get_identifier());
   }
   if (!(*sp_it)->watchers.erase(component)) {
+    mutex->unlock();
     throw SyncPointReleasedByNonWatcherException(component, sync_point->get_identifier());
   }
 
+  mutex->unlock();
 }
 
 
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index 61b5914..602d7a0 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -26,6 +26,7 @@
 
 #include <syncpoint/syncpoint.h>
 #include <core/utils/refptr.h>
+#include <core/threading/mutex.h>
 
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
@@ -55,6 +56,8 @@ class SyncPointManager
      * Set of all existing SyncPoints
      */
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints_;
+    /** Mutex used for all SyncPointManager calls */
+    Mutex *mutex;
 
 
 };

- *commit* fc80185a193952af7797c28b78e3bb81d4d5b7f1 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Tue May 20 11:27:41 2014 +0200
Subject: syncpoint: Minor changes in exception descriptions

 src/libs/syncpoint/exceptions.h |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/exceptions.h b/src/libs/syncpoint/exceptions.h
index 8c694f2..ef3e633 100644
--- a/src/libs/syncpoint/exceptions.h
+++ b/src/libs/syncpoint/exceptions.h
@@ -41,7 +41,7 @@ class SyncPointAlreadyOpenedException : public Exception
       const char *identifier)
     {
       append(
-          "Component %s called get_syncpoint() for identifier %s, but is already watching",
+          "Component '%s' called get_syncpoint() for identifier '%s', but is already watching",
           component, identifier);
     }
 };
@@ -59,7 +59,7 @@ class SyncPointNonWatcherCalledEmitException : public Exception
     SyncPointNonWatcherCalledEmitException(const char * component,
       const char *identifier)
     {
-      append("Component %s called emit for SyncPoint %s, but is not a watcher",
+      append("Component '%s' called emit for SyncPoint '%s', but is not a watcher",
           component, identifier);
     }
 };
@@ -77,7 +77,7 @@ class SyncPointNonWatcherCalledWaitException : public Exception
     SyncPointNonWatcherCalledWaitException(const char * component,
       const char *identifier)
     {
-      append("Component %s called wait for SyncPoint %s, but is not a watcher",
+      append("Component '%s' called wait for SyncPoint '%s', but is not a watcher",
           component, identifier);
     }
 };
@@ -95,7 +95,7 @@ class SyncPointReleasedDoesNotExistException : public Exception
     SyncPointReleasedDoesNotExistException(const char * component,
       const char * identifier)
     {
-      append("Component %s tried to release non-existing SyncPoint %s",
+      append("Component '%s' tried to release non-existing SyncPoint '%s'",
           component, identifier);
     }
 };
@@ -113,7 +113,7 @@ class SyncPointReleasedByNonWatcherException : public Exception
     SyncPointReleasedByNonWatcherException(const char * component,
       const char * identifier)
     {
-      append("Component %s tried to release SyncPoint %s but is not a watcher",
+      append("Component '%s' tried to release SyncPoint '%s' but is not a watcher",
           component, identifier);
     }
 };
@@ -129,7 +129,7 @@ class SyncPointInvalidIdentifierException : public Exception
      */
     SyncPointInvalidIdentifierException(const char * identifier)
     {
-      append("Tried to construct a SyncPoint with invalid identifier ('%s')"
+      append("Tried to construct a SyncPoint with invalid identifier ('%s'). "
           "Identifier must be a non-empty absolute path (e.g. '/path/to/syncpoint')",
           identifier);
     }

- *commit* a6dc56681f765eab2bc9bdde06d28348837f8054 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Tue May 20 11:31:45 2014 +0200
Subject: syncpoint: throw exception if a waiting component calls wait() again

 src/libs/syncpoint/exceptions.h  |   18 ++++++++++++++++++
 src/libs/syncpoint/syncpoint.cpp |    7 +++++++
 src/libs/syncpoint/syncpoint.h   |    1 +
 3 files changed, 26 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/exceptions.h b/src/libs/syncpoint/exceptions.h
index ef3e633..a1bf769 100644
--- a/src/libs/syncpoint/exceptions.h
+++ b/src/libs/syncpoint/exceptions.h
@@ -153,6 +153,24 @@ class SyncPointInvalidComponentException : public Exception
     }
 };
 
+/** A component called wait() but is already waiting
+ *
+ */
+class SyncPointMultipleWaitCallsException : public Exception
+{
+  public:
+    /** Constructor.
+     * @param component The calling component
+     * @param identifier The identifier of the SyncPoint
+     */
+    SyncPointMultipleWaitCallsException(const char * component,
+      const char * identifier)
+    {
+      append("Component '%s' called wait() on SyncPoint '%s', but is already waiting",
+          component, identifier);
+    }
+};
+
 
 } // namespace fawkes
 
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index d0b815d..927ec66 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -111,6 +111,7 @@ SyncPoint::emit(const char * component)
     mutex->unlock();
     throw SyncPointNonWatcherCalledEmitException(component, get_identifier());
   }
+  waiting_watchers.clear();
   wait_condition->wake_all();
   mutex->unlock();
 }
@@ -126,6 +127,12 @@ SyncPoint::wait(const char * component) {
     mutex->unlock();
     throw SyncPointNonWatcherCalledWaitException(component, get_identifier());
   }
+  // check if calling component is not already waiting
+  if (waiting_watchers.count(component)) {
+    mutex->unlock();
+    throw SyncPointMultipleWaitCallsException(component, get_identifier());
+  }
+  waiting_watchers.insert(component);
   wait_condition->wait();
   mutex->unlock();
 }
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index efa7067..8fe3707 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -60,6 +60,7 @@ class SyncPoint
   private:
     const char * identifier_;
     std::set<const char *> watchers;
+    std::set<const char *> waiting_watchers;
 
     Mutex *mutex;
     WaitCondition *wait_condition;

- *commit* d30b3026298b0bc6295b0dae105ae07fda32276c - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Tue May 20 11:42:47 2014 +0200
Subject: syncpoint: add unit tests for multiple wait calls, multi-threading

 src/libs/syncpoint/tests/test_syncpoint.cpp |   59 +++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index bafcd8c..33cbafb 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -30,6 +30,8 @@
 #include <pthread.h>
 #include <baseapp/run.h>
 
+#include <unistd.h>
+
 #include <set>
 
 using namespace fawkes;
@@ -177,3 +179,60 @@ TEST_F(SyncPointManagerTest, SyncPointManagerExceptions) {
 
 
 }
+
+// helper function used for testing wait()
+void * call_wait(void *data)
+{
+  SyncPoint * sp = (SyncPoint *)(data);
+  sp->wait("component");
+  return NULL;
+}
+
+TEST_F(SyncPointManagerTest, MultipleWaits)
+{
+  RefPtr<SyncPoint> sp_ref = manager->get_syncpoint("component", "/test/sp1");
+  SyncPoint * sp = *sp_ref;
+  pthread_t thread1;
+  pthread_create(&thread1, NULL, call_wait, (void *)sp);
+  // make sure the other thread is first
+  usleep(100);
+  ASSERT_THROW(sp_ref->wait("component"), SyncPointMultipleWaitCallsException);
+  pthread_cancel(thread1);
+}
+
+/** struct used for multithreading tests */
+struct waiter_thread_params {
+    /** SyncPointManager passed to the thread */
+    RefPtr<SyncPointManager> manager;
+    /** Thread number */
+    uint thread_nr;
+};
+
+/** get a SyncPoint and wait for it */
+void * start_waiter_thread(void * data) {
+  waiter_thread_params *params = (waiter_thread_params *)data;
+  char component[40];
+  sprintf(component, "component %u", params->thread_nr);
+  RefPtr<SyncPoint> sp = params->manager->get_syncpoint(component, "/test/sp1");
+  sp->wait(component);
+  return NULL;
+}
+
+TEST_F(SyncPointManagerTest, ParallelWaitCalls)
+{
+  uint num_threads = 100;
+  pthread_t threads[num_threads];
+  waiter_thread_params *params[num_threads];
+  for (uint i = 0; i < num_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    pthread_create(&threads[i], NULL, start_waiter_thread, params[i]);
+  }
+
+  usleep(100);
+  for (uint i = 0; i < num_threads; i++) {
+    pthread_cancel(threads[i]);
+    delete params[i];
+  }
+}

- *commit* 6a1b95656137369e110ba7a02e8095efc4a68ed7 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Tue May 20 14:40:22 2014 +0200
Subject: syncpoint: add unit tests to test wait/emit calls with multi-threading

 src/libs/syncpoint/tests/test_syncpoint.cpp |   53 +++++++++++++++++++++++++++
 1 files changed, 53 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 33cbafb..8a3ddb6 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -31,6 +31,7 @@
 #include <baseapp/run.h>
 
 #include <unistd.h>
+#include <time.h>
 
 #include <set>
 
@@ -200,6 +201,7 @@ TEST_F(SyncPointManagerTest, MultipleWaits)
   pthread_cancel(thread1);
 }
 
+
 /** struct used for multithreading tests */
 struct waiter_thread_params {
     /** SyncPointManager passed to the thread */
@@ -236,3 +238,54 @@ TEST_F(SyncPointManagerTest, ParallelWaitCalls)
     delete params[i];
   }
 }
+
+/** start multiple threads, let them wait for a SyncPoint,
+ * emit the SyncPoint and verify that they all returned
+ */
+TEST_F(SyncPointManagerTest, ParallelWaitsReturn)
+{
+  uint num_threads = 100;
+  pthread_t threads[num_threads];
+  waiter_thread_params *params[num_threads];
+  for (uint i = 0; i < num_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    pthread_create(&threads[i], NULL, start_waiter_thread, params[i]);
+  }
+
+  usleep(50);
+  RefPtr<SyncPoint> sp =manager->get_syncpoint("main_thread", "/test/sp1");
+
+  sp->emit("main_thread");
+  usleep(500);
+  for (uint i = 0; i < num_threads; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(threads[i], NULL));
+    delete params[i];
+  }
+}
+
+/** start multiple threads, let them wait for a SyncPoint,
+ * but don't emit the SyncPoint. Verify that they have not returned
+ */
+TEST_F(SyncPointManagerTest, WaitDoesNotReturnImmediately)
+{
+  uint num_threads = 100;
+  pthread_t threads[num_threads];
+  waiter_thread_params *params[num_threads];
+  for (uint i = 0; i < num_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    pthread_create(&threads[i], NULL, start_waiter_thread, params[i]);
+  }
+
+  usleep(50);
+  RefPtr<SyncPoint> sp =manager->get_syncpoint("main_thread", "/test/sp1");
+  usleep(500);
+
+  for (uint i = 0; i < num_threads; i++) {
+    ASSERT_EQ(16, pthread_tryjoin_np(threads[i], NULL));
+    delete params[i];
+  }
+}

- *commit* 3580b24d60a083758234e44b2609bd477ecdc88c - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Aug 15 19:49:05 2014 +0200
Subject: syncpoint: add support for visualization

 src/libs/syncpoint/Makefile                        |    2 +-
 src/libs/syncpoint/syncpoint.cpp                   |   44 ++++++++
 src/libs/syncpoint/syncpoint.h                     |   18 +++-
 src/libs/syncpoint/syncpoint_call.cpp              |   74 +++++++++++++
 .../syncpoint_call.h}                              |   31 +++---
 src/libs/syncpoint/syncpoint_call_stats.cpp        |  110 ++++++++++++++++++++
 .../syncpoint_call_stats.h}                        |   35 ++++---
 src/libs/syncpoint/syncpoint_manager.cpp           |   71 +++++++++++++
 src/libs/syncpoint/syncpoint_manager.h             |    3 +
 9 files changed, 357 insertions(+), 31 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/Makefile b/src/libs/syncpoint/Makefile
index 494a926..154a448 100644
--- a/src/libs/syncpoint/Makefile
+++ b/src/libs/syncpoint/Makefile
@@ -17,7 +17,7 @@ BASEDIR = ../../..
 include $(BASEDIR)/etc/buildsys/config.mk
 
 
-LIBS_libfawkessyncpoint = fawkescore 
+LIBS_libfawkessyncpoint = fawkescore fawkesutils
 OBJS_libfawkessyncpoint = $(patsubst %.cpp,%.o,$(patsubst qa/%,,$(subst $(SRCDIR)/,,$(realpath $(wildcard $(SRCDIR)/*.cpp)))))
 HDRS_libfawkessyncpoint = $(subst $(SRCDIR)/,,$(wildcard $(SRCDIR)/*.h))
 
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 927ec66..ba7b35f 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -22,6 +22,8 @@
 #include <syncpoint/syncpoint.h>
 #include <syncpoint/exceptions.h>
 
+#include <utils/time/time.h>
+
 #include <string.h>
 
 namespace fawkes {
@@ -29,6 +31,7 @@ namespace fawkes {
 }
 #endif
 
+
 /** @class SyncPoint <syncpoint/syncpoint.h>
  * The SyncPoint class.
  * This class is used for dynamic synchronization of threads which depend
@@ -49,6 +52,9 @@ namespace fawkes {
  */
 SyncPoint::SyncPoint(const char * identifier)
     : identifier_(identifier),
+      emit_calls_(CircularBuffer<SyncPointCall>(1000)),
+      wait_calls_(CircularBuffer<SyncPointCall>(1000)),
+      creation_time_(Time()),
       mutex(new Mutex()),
       wait_condition(new WaitCondition(mutex))
 {
@@ -112,6 +118,7 @@ SyncPoint::emit(const char * component)
     throw SyncPointNonWatcherCalledEmitException(component, get_identifier());
   }
   waiting_watchers.clear();
+  emit_calls_.push_back(SyncPointCall(component));
   wait_condition->wake_all();
   mutex->unlock();
 }
@@ -133,8 +140,45 @@ SyncPoint::wait(const char * component) {
     throw SyncPointMultipleWaitCallsException(component, get_identifier());
   }
   waiting_watchers.insert(component);
+  Time start;
   wait_condition->wait();
+  Time wait_time = Time() - start;
+  wait_calls_.push_back(SyncPointCall(component, start, wait_time));
+  mutex->unlock();
+}
+
+/**
+ * @return all watchers of the SyncPoint
+ */
+std::set<const char *>
+SyncPoint::get_watchers() const {
+  mutex->lock();
+  std::set<const char *> ret = watchers;
+  mutex->unlock();
+  return ret;
+}
+
+/**
+ * @return a copy of the wait call buffer
+ */
+CircularBuffer<SyncPointCall>
+SyncPoint::get_wait_calls() const {
+  mutex->lock();
+  CircularBuffer<SyncPointCall> ret(wait_calls_);
+  mutex->unlock();
+  return ret;
+}
+
+
+/**
+ * @return a copy of the emit call buffer
+ */
+CircularBuffer<SyncPointCall>
+SyncPoint::get_emit_calls() const {
+  mutex->lock();
+  CircularBuffer<SyncPointCall> ret(emit_calls_);
   mutex->unlock();
+  return ret;
 }
 
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 8fe3707..4222435 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -24,10 +24,15 @@
 
 #include <interface/interface.h>
 #include <syncpoint/syncpoint_manager.h>
+#include <syncpoint/syncpoint_call.h>
 #include <core/threading/mutex.h>
 #include <core/threading/wait_condition.h>
+#include <utils/time/time.h>
+
+#include <core/utils/circular_buffer.h>
 
 #include <set>
+#include <map>
 
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
@@ -35,6 +40,8 @@ namespace fawkes {
 #endif
 
 class SyncPointManager;
+class SyncPointCall;
+
 
 class SyncPoint
 {
@@ -52,16 +59,25 @@ class SyncPoint
     bool operator==(const SyncPoint & other) const;
     bool operator<(const SyncPoint & other) const;
 
+    std::set<const char *> get_watchers() const;
+    CircularBuffer<SyncPointCall> get_wait_calls() const;
+    CircularBuffer<SyncPointCall> get_emit_calls() const;
+
+
     /**
      * allow Syncpoint Manager to edit
      */
     friend SyncPointManager;
 
   private:
-    const char * identifier_;
+    const char * const identifier_;
     std::set<const char *> watchers;
     std::set<const char *> waiting_watchers;
 
+    CircularBuffer<SyncPointCall> emit_calls_;
+    CircularBuffer<SyncPointCall> wait_calls_;
+    const Time creation_time_;
+
     Mutex *mutex;
     WaitCondition *wait_condition;
 };
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 6ba24a9..e9e4861 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -22,7 +22,10 @@
 #include <syncpoint/syncpoint_manager.h>
 #include <syncpoint/exceptions.h>
 
+#include "syncpoint_call_stats.h"
+
 #include <string.h>
+#include <sstream>
 
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
@@ -147,4 +150,72 @@ SyncPointManager::get_syncpoints() {
   return syncpoints_;
 }
 
+/**
+ * Get DOT graph for all SyncPoints
+ * @param max_age Show only SyncPoint calls which are younger than max_age
+ * @return string representation of DOT graph
+ */
+std::string
+SyncPointManager::all_syncpoints_as_dot(float max_age)
+{
+  std::stringstream graph;
+  graph << std::fixed; //fixed point notation
+  graph.precision(3); //3 decimal places
+  graph << "digraph { graph [fontsize=14]; "
+      << "node [fontsize=12]; edge [fontsize=12]; ";
+  graph.setf(std::ios::fixed, std::ios::floatfield);
+
+  for (std::set<RefPtr<SyncPoint>, SyncPointSetLessThan>::const_iterator sp_it = syncpoints_.begin();
+      sp_it != syncpoints_.end(); sp_it++) {
+    Time lifetime = Time() - (*sp_it)->creation_time_;
+    graph << "\"" << (*sp_it)->get_identifier() << "\";";
+
+    // EMIT CALLS
+    CircularBuffer<SyncPointCall> emit_calls = (*sp_it)->get_emit_calls();
+    // generate call stats
+    std::map<const char *, SyncPointCallStats> emit_call_stats;
+    for (CircularBuffer<SyncPointCall>::iterator emitcalls_it = emit_calls.begin();
+        emitcalls_it != emit_calls.end(); emitcalls_it++) {
+      emit_call_stats[emitcalls_it->get_caller()].update_calls(emitcalls_it->get_call_time());
+    }
+
+    for (std::map<const char *, SyncPointCallStats>::iterator emit_call_stats_it = emit_call_stats.begin();
+        emit_call_stats_it != emit_call_stats.end(); emit_call_stats_it++) {
+      float age = (Time() - emit_call_stats_it->second.get_last_call()).in_sec();
+      if (age < max_age) {
+      graph << "\"" << emit_call_stats_it->first << "\" -> \""
+          <<  (*sp_it)->get_identifier()
+          << "\"" << " [label=\""
+          << " freq=" << emit_call_stats_it->second.get_call_frequency() << "Hz"
+          << " age=" << age << "s"
+          << "\"" << "];";
+      }
+    }
+
+    // WAIT CALLS
+    CircularBuffer<SyncPointCall> wait_calls = (*sp_it)->get_wait_calls();
+    // generate call stats
+    std::map<const char *, SyncPointCallStats> wait_call_stats;
+    for (CircularBuffer<SyncPointCall>::iterator waitcalls_it = wait_calls.begin();
+        waitcalls_it != wait_calls.end(); waitcalls_it++) {
+      wait_call_stats[waitcalls_it->get_caller()].update_calls(*waitcalls_it);
+    }
+
+    for (std::map<const char *, SyncPointCallStats>::iterator wait_call_stats_it = wait_call_stats.begin();
+        wait_call_stats_it != wait_call_stats.end(); wait_call_stats_it++) {
+      float age = (Time() - wait_call_stats_it->second.get_last_call()).in_sec();
+      if (age < max_age) {
+      graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> "
+          << "\"" << wait_call_stats_it->first << "\"" << " [label=" << "\""
+          << " avg=" << wait_call_stats_it->second.get_waittime_average() <<  "s"
+          << " age=" << age << "s"
+          //<< " max=" << max_wait_time << "s"
+          << "\"" << "];";
+      }
+    }
+  }
+  graph << "}";
+  return graph.str();
+}
+
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index 602d7a0..23f61ea 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -23,6 +23,7 @@
 #define __SYNCPOINT_SYNCPOINT_MANAGER_H_
 
 #include <set>
+#include <string>
 
 #include <syncpoint/syncpoint.h>
 #include <core/utils/refptr.h>
@@ -51,6 +52,8 @@ class SyncPointManager
 
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > get_syncpoints();
 
+    std::string all_syncpoints_as_dot(float max_age);
+
   protected:
     /**
      * Set of all existing SyncPoints

- *commit* afdd6ec79e109c2fc9c711a2e209f13b8bc43362 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Aug 15 20:01:14 2014 +0200
Subject: webview: add SyncPoint visualization

 cfg/conf.d/webview.yaml                            |    5 ++-
 src/plugins/webview/Makefile                       |   12 ++++-
 .../{tf_processor.cpp => syncpoint_processor.cpp}  |   57 ++++++++++---------
 .../{tf_processor.h => syncpoint_processor.h}      |   26 ++++-----
 src/plugins/webview/webview_thread.cpp             |   14 +++++
 src/plugins/webview/webview_thread.h               |    6 ++
 6 files changed, 77 insertions(+), 43 deletions(-)

_Diff for modified files_:
diff --git a/cfg/conf.d/webview.yaml b/cfg/conf.d/webview.yaml
index b237ee2..9e96e65 100644
--- a/cfg/conf.d/webview.yaml
+++ b/cfg/conf.d/webview.yaml
@@ -64,4 +64,7 @@ webview:
       jpeg-vflip: false
 
   # directories with static files
-  static-dirs: ["@BASEDIR@/res/webview"]
\ No newline at end of file
+  static-dirs: ["@BASEDIR@/res/webview"]
+
+  syncpoints:
+    max_age: 3.0
diff --git a/src/plugins/webview/Makefile b/src/plugins/webview/Makefile
index cf5b1ac..cda8fd5 100644
--- a/src/plugins/webview/Makefile
+++ b/src/plugins/webview/Makefile
@@ -94,6 +94,16 @@ ifeq ($(HAVE_LIBMICROHTTPD),1)
     LIBS_webview += crypt
     WARN_TARGETS += warning_apr_util
   endif
+
+  ifeq ($(HAVE_GRAPHVIZ),1)
+    OBJS_webview += syncpoint_processor.o
+    LIBS_webview += fawkessyncpoint
+    CFLAGS += $(CFLAGS_GRAPHVIZ)
+    LDFLAGS += $(LDFLAGS_GRAPHVIZ)
+  else
+    WARN_TARGETS += warning_graphviz
+  endif
+
 else
   WARN_TARGETS += warning_libmicrohttpd
 endif
@@ -110,7 +120,7 @@ warning_libmicrohttpd:
 warning_tf:
 	$(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting transforms support$(TNORMAL) (TF not available)"
 warning_graphviz:
-	$(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting transforms support$(TNORMAL) (graphviz not found)"
+	$(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting transforms and syncpoint support$(TNORMAL) (graphviz not found)"
 warning_jpeg:
 	$(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting image viewing support$(TNORMAL) (JPEG not available)"
 warning_cpp11:
diff --git a/src/plugins/webview/webview_thread.cpp b/src/plugins/webview/webview_thread.cpp
index 6c174e5..74ff835 100644
--- a/src/plugins/webview/webview_thread.cpp
+++ b/src/plugins/webview/webview_thread.cpp
@@ -24,6 +24,7 @@
 #include "blackboard_processor.h"
 #include "startpage_processor.h"
 #include "plugins_processor.h"
+#include "syncpoint_processor.h"
 #ifdef HAVE_TF
 #  include "tf_processor.h"
 #endif
@@ -61,6 +62,8 @@ const char *WebviewThread::PLUGINS_URL_PREFIX = "/plugins";
 const char *WebviewThread::TF_URL_PREFIX = "/tf";
 /** Prefix for the WebMJPEGRequestProcessor. */
 const char *WebviewThread::IMAGE_URL_PREFIX = "/images";
+/** Prefix for the SyncPointRequestProcessor. */
+const char *WebviewThread::SYNCPOINT_URL_PREFIX = "/syncpoints";
 
 /** @class WebviewThread "webview_thread.h"
  * Webview Thread.
@@ -153,6 +156,11 @@ WebviewThread::init()
     __cfg_access_log = config->get_string("/webview/access_log");
   } catch (Exception &e) {}
 
+  __cfg_syncpoint_max_age = 20.f;
+  try {
+    __cfg_syncpoint_max_age = config->get_float("/webview/syncpoints/max_age");
+  } catch (Exception &e) {}
+
 
   __cache_logger.clear();
 
@@ -213,6 +221,7 @@ WebviewThread::init()
   __static_processor     = new WebviewStaticRequestProcessor(STATIC_URL_PREFIX, static_dirs_cstr, logger);
   __blackboard_processor = new WebviewBlackBoardRequestProcessor(BLACKBOARD_URL_PREFIX, blackboard);
   __plugins_processor    = new WebviewPluginsRequestProcessor(PLUGINS_URL_PREFIX, plugin_manager);
+  __syncpoint_processor  = new WebviewSyncPointRequestProcessor(SYNCPOINT_URL_PREFIX, syncpoint_manager, __cfg_syncpoint_max_age);
 #ifdef HAVE_TF
   __tf_processor         = new WebviewTfRequestProcessor(TF_URL_PREFIX, tf_listener);
 #endif
@@ -224,6 +233,7 @@ WebviewThread::init()
   webview_url_manager->register_baseurl(STATIC_URL_PREFIX, __static_processor);
   webview_url_manager->register_baseurl(BLACKBOARD_URL_PREFIX, __blackboard_processor);
   webview_url_manager->register_baseurl(PLUGINS_URL_PREFIX, __plugins_processor);
+  webview_url_manager->register_baseurl(SYNCPOINT_URL_PREFIX, __syncpoint_processor);
 #ifdef HAVE_TF
   webview_url_manager->register_baseurl(TF_URL_PREFIX, __tf_processor);
 #endif
@@ -236,6 +246,7 @@ WebviewThread::init()
   webview_nav_manager->add_nav_entry(TF_URL_PREFIX, "TF");
 #endif
   webview_nav_manager->add_nav_entry(PLUGINS_URL_PREFIX, "Plugins");
+  webview_nav_manager->add_nav_entry(SYNCPOINT_URL_PREFIX, "SyncPoints");
 #ifdef HAVE_JPEG
   webview_nav_manager->add_nav_entry(IMAGE_URL_PREFIX, "Images");
 #endif
@@ -263,6 +274,7 @@ WebviewThread::finalize()
   webview_url_manager->unregister_baseurl(BLACKBOARD_URL_PREFIX);
   webview_url_manager->unregister_baseurl(PLUGINS_URL_PREFIX);
   webview_url_manager->unregister_baseurl(IMAGE_URL_PREFIX);
+  webview_url_manager->unregister_baseurl(SYNCPOINT_URL_PREFIX);
 
 #ifdef HAVE_TF
   webview_url_manager->unregister_baseurl(TF_URL_PREFIX);
@@ -270,6 +282,7 @@ WebviewThread::finalize()
 
   webview_nav_manager->remove_nav_entry(BLACKBOARD_URL_PREFIX);
   webview_nav_manager->remove_nav_entry(PLUGINS_URL_PREFIX);
+  webview_nav_manager->remove_nav_entry(SYNCPOINT_URL_PREFIX);
 #ifdef HAVE_TF
   webview_nav_manager->remove_nav_entry(TF_URL_PREFIX);
 #endif
@@ -287,6 +300,7 @@ WebviewThread::finalize()
   delete __blackboard_processor;
   delete __startpage_processor;
   delete __plugins_processor;
+  delete __syncpoint_processor;
 #ifdef HAVE_TF
   delete __tf_processor;
 #endif
diff --git a/src/plugins/webview/webview_thread.h b/src/plugins/webview/webview_thread.h
index b4da1f2..c3cb458 100644
--- a/src/plugins/webview/webview_thread.h
+++ b/src/plugins/webview/webview_thread.h
@@ -36,6 +36,7 @@
 #ifdef HAVE_TF
 #  include <aspect/tf.h>
 #endif
+#include <aspect/syncpoint_manager.h>
 
 #include <logging/cache.h>
 
@@ -59,6 +60,7 @@ class WebviewTfRequestProcessor;
 #ifdef HAVE_JPEG
 class WebviewImageRequestProcessor;
 #endif
+class WebviewSyncPointRequestProcessor;
 
 class WebviewThread
 : public fawkes::Thread,
@@ -74,6 +76,7 @@ class WebviewThread
 #ifdef HAVE_TF
   public fawkes::TransformAspect,
 #endif
+  public fawkes::SyncPointManagerAspect,
   public fawkes::WebviewAspect
 {
  public:
@@ -89,6 +92,7 @@ class WebviewThread
   static const char *PLUGINS_URL_PREFIX;
   static const char *TF_URL_PREFIX;
   static const char *IMAGE_URL_PREFIX;
+  static const char *SYNCPOINT_URL_PREFIX;
 
  private:
   void ssl_create(const char *ssl_key_file, const char *ssl_cert_file);
@@ -115,6 +119,7 @@ class WebviewThread
   WebviewHeaderGenerator             *__header_gen;
   WebviewFooterGenerator             *__footer_gen;
   WebviewUserVerifier                *__user_verifier;
+  WebviewSyncPointRequestProcessor   *__syncpoint_processor;
 
   unsigned int __cfg_port;
   bool         __cfg_use_ssl;
@@ -125,6 +130,7 @@ class WebviewThread
   bool         __cfg_use_basic_auth;
   std::string  __cfg_basic_auth_realm;
   std::string  __cfg_access_log;
+  float        __cfg_syncpoint_max_age;
 
   fawkes::CacheLogger     __cache_logger;
   fawkes::NetworkService *__webview_service;

- *commit* 35a9b1dc7bcceb2aafecf44f1cdba8cc690d0693 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Jan 16 13:57:37 2015 +0100
Subject: syncpoint: consistent variable naming

 src/libs/syncpoint/syncpoint.cpp         |   58 +++++++++++++++---------------
 src/libs/syncpoint/syncpoint.h           |    8 ++--
 src/libs/syncpoint/syncpoint_manager.cpp |    4 +-
 3 files changed, 35 insertions(+), 35 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index ba7b35f..760ec0f 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -55,25 +55,25 @@ SyncPoint::SyncPoint(const char * identifier)
       emit_calls_(CircularBuffer<SyncPointCall>(1000)),
       wait_calls_(CircularBuffer<SyncPointCall>(1000)),
       creation_time_(Time()),
-      mutex(new Mutex()),
-      wait_condition(new WaitCondition(mutex))
+      mutex_(new Mutex()),
+      wait_condition_(new WaitCondition(mutex_))
 {
   if (!strcmp(identifier, "")) {
-    delete wait_condition;
-    delete mutex;
+    delete wait_condition_;
+    delete mutex_;
     throw SyncPointInvalidIdentifierException(identifier);
   }
   if (strncmp(identifier, "/", 1)) {
-    delete wait_condition;
-    delete mutex;
+    delete wait_condition_;
+    delete mutex_;
     throw SyncPointInvalidIdentifierException(identifier);
   }
 }
 
 SyncPoint::~SyncPoint()
 {
-  delete wait_condition;
-  delete mutex;
+  delete wait_condition_;
+  delete mutex_;
 }
 
 /**
@@ -112,15 +112,15 @@ SyncPoint::operator<(const SyncPoint &other) const
 void
 SyncPoint::emit(const char * component)
 {
-  mutex->lock();
-  if (!watchers.count(component)) {
-    mutex->unlock();
+  mutex_->lock();
+  if (!watchers_.count(component)) {
+    mutex_->unlock();
     throw SyncPointNonWatcherCalledEmitException(component, get_identifier());
   }
-  waiting_watchers.clear();
+  waiting_watchers_.clear();
   emit_calls_.push_back(SyncPointCall(component));
-  wait_condition->wake_all();
-  mutex->unlock();
+  wait_condition_->wake_all();
+  mutex_->unlock();
 }
 
 /** Wait until SyncPoint is emitted
@@ -128,23 +128,23 @@ SyncPoint::emit(const char * component)
  */
 void
 SyncPoint::wait(const char * component) {
-  mutex->lock();
+  mutex_->lock();
   // check if calling component is registered for this SyncPoint
-  if (!watchers.count(component)) {
-    mutex->unlock();
+  if (!watchers_.count(component)) {
+    mutex_->unlock();
     throw SyncPointNonWatcherCalledWaitException(component, get_identifier());
   }
   // check if calling component is not already waiting
-  if (waiting_watchers.count(component)) {
-    mutex->unlock();
+  if (waiting_watchers_.count(component)) {
+    mutex_->unlock();
     throw SyncPointMultipleWaitCallsException(component, get_identifier());
   }
-  waiting_watchers.insert(component);
+  waiting_watchers_.insert(component);
   Time start;
-  wait_condition->wait();
+  wait_condition_->wait();
   Time wait_time = Time() - start;
   wait_calls_.push_back(SyncPointCall(component, start, wait_time));
-  mutex->unlock();
+  mutex_->unlock();
 }
 
 /**
@@ -152,9 +152,9 @@ SyncPoint::wait(const char * component) {
  */
 std::set<const char *>
 SyncPoint::get_watchers() const {
-  mutex->lock();
-  std::set<const char *> ret = watchers;
-  mutex->unlock();
+  mutex_->lock();
+  std::set<const char *> ret = watchers_;
+  mutex_->unlock();
   return ret;
 }
 
@@ -163,9 +163,9 @@ SyncPoint::get_watchers() const {
  */
 CircularBuffer<SyncPointCall>
 SyncPoint::get_wait_calls() const {
-  mutex->lock();
+  mutex_->lock();
   CircularBuffer<SyncPointCall> ret(wait_calls_);
-  mutex->unlock();
+  mutex_->unlock();
   return ret;
 }
 
@@ -175,9 +175,9 @@ SyncPoint::get_wait_calls() const {
  */
 CircularBuffer<SyncPointCall>
 SyncPoint::get_emit_calls() const {
-  mutex->lock();
+  mutex_->lock();
   CircularBuffer<SyncPointCall> ret(emit_calls_);
-  mutex->unlock();
+  mutex_->unlock();
   return ret;
 }
 
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 4222435..0b078c2 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -71,15 +71,15 @@ class SyncPoint
 
   private:
     const char * const identifier_;
-    std::set<const char *> watchers;
-    std::set<const char *> waiting_watchers;
+    std::set<const char *> watchers_;
+    std::set<const char *> waiting_watchers_;
 
     CircularBuffer<SyncPointCall> emit_calls_;
     CircularBuffer<SyncPointCall> wait_calls_;
     const Time creation_time_;
 
-    Mutex *mutex;
-    WaitCondition *wait_condition;
+    Mutex *mutex_;
+    WaitCondition *wait_condition_;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index e9e4861..6b24f35 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -86,7 +86,7 @@ SyncPointManager::get_syncpoint(const char * component, const char * identifier)
   // add component to the set of watchers
   // check if component is already a watcher
   // insert returns a pair whose second element is false if element already exists
-  if (!(*it)->watchers.insert(component).second) {
+  if (!(*it)->watchers_.insert(component).second) {
     mutex->unlock();
     throw SyncPointAlreadyOpenedException(component, identifier);
   }
@@ -115,7 +115,7 @@ SyncPointManager::release_syncpoint(const char * component, RefPtr<SyncPoint> sy
     mutex->unlock();
     throw SyncPointReleasedDoesNotExistException(component, sync_point->get_identifier());
   }
-  if (!(*sp_it)->watchers.erase(component)) {
+  if (!(*sp_it)->watchers_.erase(component)) {
     mutex->unlock();
     throw SyncPointReleasedByNonWatcherException(component, sync_point->get_identifier());
   }

- *commit* b9090fd43ee68b23d6398932f4d6a2eea1cef4e2 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Jan 23 15:22:07 2015 +0100
Subject: syncpoint: use std::string for identifiers, API change!

 src/libs/syncpoint/syncpoint.cpp         |   32 +++++++++++++++--------------
 src/libs/syncpoint/syncpoint.h           |   16 +++++++-------
 src/libs/syncpoint/syncpoint_call.cpp    |    4 +-
 src/libs/syncpoint/syncpoint_call.h      |    8 ++++--
 src/libs/syncpoint/syncpoint_manager.cpp |   24 +++++++++++-----------
 src/libs/syncpoint/syncpoint_manager.h   |    4 +-
 6 files changed, 46 insertions(+), 42 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 760ec0f..c4c1c38 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -26,6 +26,8 @@
 
 #include <string.h>
 
+using namespace std;
+
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
 }
@@ -50,7 +52,7 @@ namespace fawkes {
  * @param identifier The identifier of the SyncPoint. This must be in absolute
  * path style, e.g. '/some/syncpoint'.
  */
-SyncPoint::SyncPoint(const char * identifier)
+SyncPoint::SyncPoint(string identifier)
     : identifier_(identifier),
       emit_calls_(CircularBuffer<SyncPointCall>(1000)),
       wait_calls_(CircularBuffer<SyncPointCall>(1000)),
@@ -58,15 +60,15 @@ SyncPoint::SyncPoint(const char * identifier)
       mutex_(new Mutex()),
       wait_condition_(new WaitCondition(mutex_))
 {
-  if (!strcmp(identifier, "")) {
+  if (identifier.empty()) {
     delete wait_condition_;
     delete mutex_;
-    throw SyncPointInvalidIdentifierException(identifier);
+    throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
-  if (strncmp(identifier, "/", 1)) {
+  if (identifier.compare(0,1,"/")) {
     delete wait_condition_;
     delete mutex_;
-    throw SyncPointInvalidIdentifierException(identifier);
+    throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
 }
 
@@ -79,7 +81,7 @@ SyncPoint::~SyncPoint()
 /**
  * @return the identifier of the SyncPoint
  */
-const char *
+string
 SyncPoint::get_identifier() const {
   return identifier_;
 }
@@ -92,7 +94,7 @@ SyncPoint::get_identifier() const {
 bool
 SyncPoint::operator==(const SyncPoint &other) const
 {
-  return strcmp(identifier_, other.get_identifier()) == 0;
+  return identifier_ == other.get_identifier();
 }
 
 /** LessThan Operator.
@@ -103,19 +105,19 @@ SyncPoint::operator==(const SyncPoint &other) const
 bool
 SyncPoint::operator<(const SyncPoint &other) const
 {
-  return strcmp(identifier_, other.get_identifier()) < 0;
+  return identifier_ < other.get_identifier();
 }
 
 /** Wake up all components which are waiting for this SyncPoint
  * @param component The identifier of the component emitting the SyncPoint
  */
 void
-SyncPoint::emit(const char * component)
+SyncPoint::emit(const std::string & component)
 {
   mutex_->lock();
   if (!watchers_.count(component)) {
     mutex_->unlock();
-    throw SyncPointNonWatcherCalledEmitException(component, get_identifier());
+    throw SyncPointNonWatcherCalledEmitException(component.c_str(), get_identifier().c_str());
   }
   waiting_watchers_.clear();
   emit_calls_.push_back(SyncPointCall(component));
@@ -127,17 +129,17 @@ SyncPoint::emit(const char * component)
  * @param component The identifier of the component waiting for the SyncPoint
  */
 void
-SyncPoint::wait(const char * component) {
   mutex_->lock();
+SyncPoint::wait(const std::string & component) {
   // check if calling component is registered for this SyncPoint
   if (!watchers_.count(component)) {
     mutex_->unlock();
-    throw SyncPointNonWatcherCalledWaitException(component, get_identifier());
+    throw SyncPointNonWatcherCalledWaitException(component.c_str(), get_identifier().c_str());
   }
   // check if calling component is not already waiting
   if (waiting_watchers_.count(component)) {
     mutex_->unlock();
-    throw SyncPointMultipleWaitCallsException(component, get_identifier());
+    throw SyncPointMultipleWaitCallsException(component.c_str(), get_identifier().c_str());
   }
   waiting_watchers_.insert(component);
   Time start;
@@ -150,10 +152,10 @@ SyncPoint::wait(const char * component) {
 /**
  * @return all watchers of the SyncPoint
  */
-std::set<const char *>
+std::set<std::string>
 SyncPoint::get_watchers() const {
   mutex_->lock();
-  std::set<const char *> ret = watchers_;
+  std::set<std::string> ret = watchers_;
   mutex_->unlock();
   return ret;
 }
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 0b078c2..7b3d529 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -46,20 +46,20 @@ class SyncPointCall;
 class SyncPoint
 {
   public:
-    SyncPoint(const char * identifier);
+    SyncPoint(std::string identifier);
     virtual ~SyncPoint();
 
     /** send a signal to all waiting threads */
-    virtual void emit(const char * component);
+    virtual void emit(const std::string & component);
 
     /** wait for the sync point to be emitted */
-    virtual void wait(const char * component);
+    virtual void wait(const std::string & component);
 
-    const char * get_identifier() const;
+    std::string get_identifier() const;
     bool operator==(const SyncPoint & other) const;
     bool operator<(const SyncPoint & other) const;
 
-    std::set<const char *> get_watchers() const;
+    std::set<std::string> get_watchers() const;
     CircularBuffer<SyncPointCall> get_wait_calls() const;
     CircularBuffer<SyncPointCall> get_emit_calls() const;
 
@@ -70,9 +70,9 @@ class SyncPoint
     friend SyncPointManager;
 
   private:
-    const char * const identifier_;
-    std::set<const char *> watchers_;
-    std::set<const char *> waiting_watchers_;
+    const std::string identifier_;
+    std::set<std::string> watchers_;
+    std::set<std::string> waiting_watchers_;
 
     CircularBuffer<SyncPointCall> emit_calls_;
     CircularBuffer<SyncPointCall> wait_calls_;
diff --git a/src/libs/syncpoint/syncpoint_call.cpp b/src/libs/syncpoint/syncpoint_call.cpp
index 067b36b..4bb0ea8 100644
--- a/src/libs/syncpoint/syncpoint_call.cpp
+++ b/src/libs/syncpoint/syncpoint_call.cpp
@@ -37,7 +37,7 @@ namespace fawkes {
  * @param caller The calling component
  * @param wait_time The time the caller had to wait for the SyncPoint (wait calls)
  */
-SyncPointCall::SyncPointCall(const char * caller, Time call_time, Time wait_time)
+SyncPointCall::SyncPointCall(const std::string & caller, Time call_time, Time wait_time)
   : caller_(caller),
     call_time_(call_time),
     wait_time_(wait_time)
@@ -64,7 +64,7 @@ SyncPointCall::get_wait_time() const
 /** Get the name of the component which made the call
  * @return the component name
  */
-const char *
+std::string
 SyncPointCall::get_caller() const
 {
   return caller_;
diff --git a/src/libs/syncpoint/syncpoint_call.h b/src/libs/syncpoint/syncpoint_call.h
index f2139ed..e809d21 100644
--- a/src/libs/syncpoint/syncpoint_call.h
+++ b/src/libs/syncpoint/syncpoint_call.h
@@ -24,6 +24,8 @@
 
 #include <utils/time/time.h>
 
+#include <string>
+
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
 }
@@ -32,16 +34,16 @@ namespace fawkes {
 class SyncPointCall
 {
   public:
-    SyncPointCall(const char * caller, Time call_time = Time(), Time wait_time =
+    SyncPointCall(const std::string & caller, Time call_time = Time(), Time wait_time =
       Time(0.d));
 
   public:
     Time get_call_time() const;
     Time get_wait_time() const;
-    const char * get_caller() const;
+    std::string get_caller() const;
 
   private:
-    const char * const caller_;
+    const std::string caller_;
     const Time call_time_;
     const Time wait_time_;
 };
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 6b24f35..7a20324 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -24,7 +24,7 @@
 
 #include "syncpoint_call_stats.h"
 
-#include <string.h>
+#include <string>
 #include <sstream>
 
 namespace fawkes {
@@ -64,12 +64,12 @@ SyncPointManager::~SyncPointManager()
  * by the component
  */
 RefPtr<SyncPoint>
-SyncPointManager::get_syncpoint(const char * component, const char * identifier)
+SyncPointManager::get_syncpoint(const std::string & component, const std::string & identifier)
 {
   mutex->lock();
-  if (!strcmp(component, "")) {
+  if (component == "") {
     mutex->unlock();
-    throw SyncPointInvalidComponentException(component, identifier);
+    throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
   }
   // insert a new SyncPoint if no SyncPoint with the same identifier exists,
   // otherwise, use that SyncPoint
@@ -88,7 +88,7 @@ SyncPointManager::get_syncpoint(const char * component, const char * identifier)
   // insert returns a pair whose second element is false if element already exists
   if (!(*it)->watchers_.insert(component).second) {
     mutex->unlock();
-    throw SyncPointAlreadyOpenedException(component, identifier);
+    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
   }
   mutex->unlock();
 
@@ -106,18 +106,18 @@ SyncPointManager::get_syncpoint(const char * component, const char * identifier)
  * a watcher of the SyncPoint
  */
 void
-SyncPointManager::release_syncpoint(const char * component, RefPtr<SyncPoint> sync_point)
+SyncPointManager::release_syncpoint(const std::string & component, RefPtr<SyncPoint> sync_point)
 {
   mutex->lock();
   std::set<RefPtr<SyncPoint> >::iterator sp_it = syncpoints_.find(
       sync_point);
   if (sp_it == syncpoints_.end()) {
     mutex->unlock();
-    throw SyncPointReleasedDoesNotExistException(component, sync_point->get_identifier());
+    throw SyncPointReleasedDoesNotExistException(component.c_str(), sync_point->get_identifier().c_str());
   }
   if (!(*sp_it)->watchers_.erase(component)) {
     mutex->unlock();
-    throw SyncPointReleasedByNonWatcherException(component, sync_point->get_identifier());
+    throw SyncPointReleasedByNonWatcherException(component.c_str(), sync_point->get_identifier().c_str());
   }
 
   mutex->unlock();
@@ -173,13 +173,13 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
     // EMIT CALLS
     CircularBuffer<SyncPointCall> emit_calls = (*sp_it)->get_emit_calls();
     // generate call stats
-    std::map<const char *, SyncPointCallStats> emit_call_stats;
+    std::map<std::string, SyncPointCallStats> emit_call_stats;
     for (CircularBuffer<SyncPointCall>::iterator emitcalls_it = emit_calls.begin();
         emitcalls_it != emit_calls.end(); emitcalls_it++) {
       emit_call_stats[emitcalls_it->get_caller()].update_calls(emitcalls_it->get_call_time());
     }
 
-    for (std::map<const char *, SyncPointCallStats>::iterator emit_call_stats_it = emit_call_stats.begin();
+    for (std::map<std::string, SyncPointCallStats>::iterator emit_call_stats_it = emit_call_stats.begin();
         emit_call_stats_it != emit_call_stats.end(); emit_call_stats_it++) {
       float age = (Time() - emit_call_stats_it->second.get_last_call()).in_sec();
       if (age < max_age) {
@@ -195,13 +195,13 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
     // WAIT CALLS
     CircularBuffer<SyncPointCall> wait_calls = (*sp_it)->get_wait_calls();
     // generate call stats
-    std::map<const char *, SyncPointCallStats> wait_call_stats;
+    std::map<std::string, SyncPointCallStats> wait_call_stats;
     for (CircularBuffer<SyncPointCall>::iterator waitcalls_it = wait_calls.begin();
         waitcalls_it != wait_calls.end(); waitcalls_it++) {
       wait_call_stats[waitcalls_it->get_caller()].update_calls(*waitcalls_it);
     }
 
-    for (std::map<const char *, SyncPointCallStats>::iterator wait_call_stats_it = wait_call_stats.begin();
+    for (std::map<std::string, SyncPointCallStats>::iterator wait_call_stats_it = wait_call_stats.begin();
         wait_call_stats_it != wait_call_stats.end(); wait_call_stats_it++) {
       float age = (Time() - wait_call_stats_it->second.get_last_call()).in_sec();
       if (age < max_age) {
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index 23f61ea..c1486dc 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -47,8 +47,8 @@ class SyncPointManager
     SyncPointManager();
     virtual ~SyncPointManager();
 
-    RefPtr<SyncPoint> get_syncpoint(const char * component, const char * identifier);
-    void release_syncpoint(const char * component, RefPtr<SyncPoint> syncpoint);
+    RefPtr<SyncPoint> get_syncpoint(const std::string & component, const std::string & identifier);
+    void release_syncpoint(const std::string & component, RefPtr<SyncPoint> syncpoint);
 
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > get_syncpoints();
 

- *commit* ca3bec072cdafefcb9093667906fece4446f74fe - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Jan 23 20:17:22 2015 +0100
Subject: syncpoint: add method add_watcher

 src/libs/syncpoint/syncpoint.cpp         |   11 +++++++++++
 src/libs/syncpoint/syncpoint.h           |    3 +++
 src/libs/syncpoint/syncpoint_manager.cpp |    2 +-
 3 files changed, 15 insertions(+), 1 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index c4c1c38..23a3110 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -22,6 +22,7 @@
 #include <syncpoint/syncpoint.h>
 #include <syncpoint/exceptions.h>
 
+#include <core/threading/mutex_locker.h>
 #include <utils/time/time.h>
 
 #include <string.h>
@@ -149,6 +150,16 @@ SyncPoint::wait(const std::string & component) {
   mutex_->unlock();
 }
 
+/** Add a watcher to the watch list
+ *  @param watcher the new watcher
+ */
+pair<set<string>::iterator,bool>
+SyncPoint::add_watcher(string watcher)
+{
+  MutexLocker ml(mutex_);
+  return watchers_.insert(watcher);
+}
+
 /**
  * @return all watchers of the SyncPoint
  */
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 7b3d529..6c7676a 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -70,6 +70,9 @@ class SyncPoint
     friend SyncPointManager;
 
   private:
+    std::pair<std::set<std::string>::iterator,bool> add_watcher(std::string watcher);
+
+  private:
     const std::string identifier_;
     std::set<std::string> watchers_;
     std::set<std::string> waiting_watchers_;
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 7a20324..9be0283 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -86,7 +86,7 @@ SyncPointManager::get_syncpoint(const std::string & component, const std::string
   // add component to the set of watchers
   // check if component is already a watcher
   // insert returns a pair whose second element is false if element already exists
-  if (!(*it)->watchers_.insert(component).second) {
+  if (!(*it)->add_watcher(component).second) {
     mutex->unlock();
     throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
   }

- *commit* 1b4992fc956b4ba02f91ba1a01c83289954a1be3 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Jan 23 20:26:31 2015 +0100
Subject: syncpoint: initialize WaitCondition correctly, use MutexLocker

 src/libs/syncpoint/syncpoint.cpp         |   26 +++++++++++---------------
 src/libs/syncpoint/syncpoint_manager.cpp |   20 ++++++++------------
 src/libs/syncpoint/syncpoint_manager.h   |    2 +-
 3 files changed, 20 insertions(+), 28 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 23a3110..a25d3ac 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -59,7 +59,7 @@ SyncPoint::SyncPoint(string identifier)
       wait_calls_(CircularBuffer<SyncPointCall>(1000)),
       creation_time_(Time()),
       mutex_(new Mutex()),
-      wait_condition_(new WaitCondition(mutex_))
+      wait_condition_(new WaitCondition())
 {
   if (identifier.empty()) {
     delete wait_condition_;
@@ -122,16 +122,16 @@ SyncPoint::emit(const std::string & component)
   }
   waiting_watchers_.clear();
   emit_calls_.push_back(SyncPointCall(component));
-  wait_condition_->wake_all();
   mutex_->unlock();
+  wait_condition_->wake_all();
 }
 
 /** Wait until SyncPoint is emitted
  * @param component The identifier of the component waiting for the SyncPoint
  */
 void
-  mutex_->lock();
 SyncPoint::wait(const std::string & component) {
+  mutex_->lock();
   // check if calling component is registered for this SyncPoint
   if (!watchers_.count(component)) {
     mutex_->unlock();
@@ -143,9 +143,11 @@ SyncPoint::wait(const std::string & component) {
     throw SyncPointMultipleWaitCallsException(component.c_str(), get_identifier().c_str());
   }
   waiting_watchers_.insert(component);
+  mutex_->unlock();
   Time start;
   wait_condition_->wait();
   Time wait_time = Time() - start;
+  mutex_->lock();
   wait_calls_.push_back(SyncPointCall(component, start, wait_time));
   mutex_->unlock();
 }
@@ -165,10 +167,8 @@ SyncPoint::add_watcher(string watcher)
  */
 std::set<std::string>
 SyncPoint::get_watchers() const {
-  mutex_->lock();
-  std::set<std::string> ret = watchers_;
-  mutex_->unlock();
-  return ret;
+  MutexLocker ml(mutex_);
+  return watchers_;
 }
 
 /**
@@ -176,10 +176,8 @@ SyncPoint::get_watchers() const {
  */
 CircularBuffer<SyncPointCall>
 SyncPoint::get_wait_calls() const {
-  mutex_->lock();
-  CircularBuffer<SyncPointCall> ret(wait_calls_);
-  mutex_->unlock();
-  return ret;
+  MutexLocker ml(mutex_);
+  return wait_calls_;
 }
 
 
@@ -188,10 +186,8 @@ SyncPoint::get_wait_calls() const {
  */
 CircularBuffer<SyncPointCall>
 SyncPoint::get_emit_calls() const {
-  mutex_->lock();
-  CircularBuffer<SyncPointCall> ret(emit_calls_);
-  mutex_->unlock();
-  return ret;
+  MutexLocker ml(mutex_);
+  return emit_calls_;
 }
 
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 9be0283..a06ef48 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -19,6 +19,8 @@
  *  Read the full text in the LICENSE.GPL file in the doc directory.
  */
 
+#include <core/threading/mutex_locker.h>
+
 #include <syncpoint/syncpoint_manager.h>
 #include <syncpoint/exceptions.h>
 
@@ -44,13 +46,13 @@ namespace fawkes {
  */
 
 SyncPointManager::SyncPointManager()
-: mutex(new Mutex())
+: mutex_(new Mutex())
 {
 }
 
 SyncPointManager::~SyncPointManager()
 {
-  delete mutex;
+  delete mutex_;
 }
 
 /**
@@ -66,9 +68,8 @@ SyncPointManager::~SyncPointManager()
 RefPtr<SyncPoint>
 SyncPointManager::get_syncpoint(const std::string & component, const std::string & identifier)
 {
-  mutex->lock();
+  MutexLocker ml(mutex_);
   if (component == "") {
-    mutex->unlock();
     throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
   }
   // insert a new SyncPoint if no SyncPoint with the same identifier exists,
@@ -77,7 +78,6 @@ SyncPointManager::get_syncpoint(const std::string & component, const std::string
   try {
   ret = syncpoints_.insert(RefPtr<SyncPoint>(new SyncPoint(identifier)));
   } catch (const SyncPointInvalidIdentifierException &e) {
-    mutex->unlock();
     throw;
   }
 
@@ -87,10 +87,8 @@ SyncPointManager::get_syncpoint(const std::string & component, const std::string
   // check if component is already a watcher
   // insert returns a pair whose second element is false if element already exists
   if (!(*it)->add_watcher(component).second) {
-    mutex->unlock();
     throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
   }
-  mutex->unlock();
 
   return *it;
 }
@@ -108,19 +106,15 @@ SyncPointManager::get_syncpoint(const std::string & component, const std::string
 void
 SyncPointManager::release_syncpoint(const std::string & component, RefPtr<SyncPoint> sync_point)
 {
-  mutex->lock();
+  MutexLocker ml(mutex_);
   std::set<RefPtr<SyncPoint> >::iterator sp_it = syncpoints_.find(
       sync_point);
   if (sp_it == syncpoints_.end()) {
-    mutex->unlock();
     throw SyncPointReleasedDoesNotExistException(component.c_str(), sync_point->get_identifier().c_str());
   }
   if (!(*sp_it)->watchers_.erase(component)) {
-    mutex->unlock();
     throw SyncPointReleasedByNonWatcherException(component.c_str(), sync_point->get_identifier().c_str());
   }
-
-  mutex->unlock();
 }
 
 
@@ -147,6 +141,7 @@ SyncPointSetLessThan::operator()(const RefPtr<SyncPoint> sp1, const RefPtr<SyncP
  */
 std::set<RefPtr<SyncPoint>, SyncPointSetLessThan >
 SyncPointManager::get_syncpoints() {
+  MutexLocker ml(mutex_);
   return syncpoints_;
 }
 
@@ -165,6 +160,7 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
       << "node [fontsize=12]; edge [fontsize=12]; ";
   graph.setf(std::ios::fixed, std::ios::floatfield);
 
+  MutexLocker ml(mutex_);
   for (std::set<RefPtr<SyncPoint>, SyncPointSetLessThan>::const_iterator sp_it = syncpoints_.begin();
       sp_it != syncpoints_.end(); sp_it++) {
     Time lifetime = Time() - (*sp_it)->creation_time_;
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index c1486dc..d670237 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -60,7 +60,7 @@ class SyncPointManager
      */
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints_;
     /** Mutex used for all SyncPointManager calls */
-    Mutex *mutex;
+    Mutex *mutex_;
 
 
 };

- *commit* aed0e80779cf0d53ba5c78874c71b286f99ace3e - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Jan 23 20:41:01 2015 +0100
Subject: syncpoint: remove errors reported by clang

 src/libs/syncpoint/syncpoint.h              |    2 +-
 src/libs/syncpoint/syncpoint_call.h         |    2 +-
 src/libs/syncpoint/syncpoint_call_stats.cpp |    2 +-
 src/libs/syncpoint/syncpoint_call_stats.h   |    2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 6c7676a..fb54f05 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -67,7 +67,7 @@ class SyncPoint
     /**
      * allow Syncpoint Manager to edit
      */
-    friend SyncPointManager;
+    friend class SyncPointManager;
 
   private:
     std::pair<std::set<std::string>::iterator,bool> add_watcher(std::string watcher);
diff --git a/src/libs/syncpoint/syncpoint_call.h b/src/libs/syncpoint/syncpoint_call.h
index e809d21..7989e60 100644
--- a/src/libs/syncpoint/syncpoint_call.h
+++ b/src/libs/syncpoint/syncpoint_call.h
@@ -35,7 +35,7 @@ class SyncPointCall
 {
   public:
     SyncPointCall(const std::string & caller, Time call_time = Time(), Time wait_time =
-      Time(0.d));
+      Time(0.f));
 
   public:
     Time get_call_time() const;
diff --git a/src/libs/syncpoint/syncpoint_call_stats.cpp b/src/libs/syncpoint/syncpoint_call_stats.cpp
index c29d6ea..33d76b7 100644
--- a/src/libs/syncpoint/syncpoint_call_stats.cpp
+++ b/src/libs/syncpoint/syncpoint_call_stats.cpp
@@ -39,7 +39,7 @@ namespace fawkes {
 SyncPointCallStats::SyncPointCallStats()
 : first_call_(TIME_MAX),
   last_call_(TIME_MIN),
-  total_wait_time_(Time(0.d)),
+  total_wait_time_(Time(0.f)),
   num_calls_(0)
 {}
 
diff --git a/src/libs/syncpoint/syncpoint_call_stats.h b/src/libs/syncpoint/syncpoint_call_stats.h
index fa8481f..7bad11b 100644
--- a/src/libs/syncpoint/syncpoint_call_stats.h
+++ b/src/libs/syncpoint/syncpoint_call_stats.h
@@ -35,7 +35,7 @@ class SyncPointCallStats {
   public:
     SyncPointCallStats();
 
-    void update_calls(Time new_call, Time wait_time = Time(0.d));
+    void update_calls(Time new_call, Time wait_time = Time(0.f));
     void update_calls(SyncPointCall call);
     Time get_first_call() const;
     Time get_last_call() const;

- *commit* c56c39c8e09d40b24184240c7b96fa964e882fb3 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Sun Jan 25 00:10:42 2015 +0100
Subject: syncpoint: update unit test

 src/libs/syncpoint/tests/Makefile           |   16 ++-
 src/libs/syncpoint/tests/test_syncpoint.cpp |  174 +++++++++++++++++++--------
 2 files changed, 136 insertions(+), 54 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/Makefile b/src/libs/syncpoint/tests/Makefile
index 6e349b5..e9b314e 100644
--- a/src/libs/syncpoint/tests/Makefile
+++ b/src/libs/syncpoint/tests/Makefile
@@ -15,15 +15,19 @@
 
 BASEDIR = ../../../..
 include $(BASEDIR)/etc/buildsys/config.mk
+include $(BASEDIR)/etc/buildsys/gtest.mk
 
-LIBS_gtest_syncpoint += stdc++ fawkescore fawkesutils fawkessyncpoint gtest gtest_main pthread
+CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable
+LIBS_gtest_syncpoint += stdc++ fawkescore fawkesutils fawkessyncpoint pthread
 
 OBJS_gtest_syncpoint += test_syncpoint.o
-OBJS_all    = $(OBJS_gtest_syncpoint)
-
-LIBS_test = $(LIBDIR)/test/syncpoint.so
-
-BINS_test		= $(BINDIR)/gtest_syncpoint
+OBJS_all = $(OBJS_gtest_syncpoint)
 
+ifeq ($(HAVE_GTEST),1)
+  CFLAGS += $(CFLAGS_GTEST)
+  LDFLAGS += $(LDFLAGS_GTEST)
+  LIBS_test = $(LIBDIR)/test/syncpoint.so
+  BINS_test = $(BINDIR)/gtest_syncpoint
+endif
 
 include $(BUILDSYSDIR)/base.mk
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 8a3ddb6..44a6106 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -1,8 +1,8 @@
 /***************************************************************************
- *  syncpoint-test.cpp - SyncPoint Unit Test
+ *  test_syncpoint.cpp - SyncPoint Unit Test
  *
  *  Created: Wed Jan 22 11:17:43 2014
- *  Copyright  2014  Till Hofmann
+ *  Copyright  2014-2015  Till Hofmann
  *
  ****************************************************************************/
 
@@ -21,21 +21,21 @@
 
 #include <gtest/gtest.h>
 
-#include <libs/syncpoint/syncpoint.h>
-#include <libs/syncpoint/exceptions.h>
-#include <libs/syncpoint/syncpoint_manager.h>
-
-#include <core/utils/refptr.h>
-
 #include <pthread.h>
-#include <baseapp/run.h>
-
+#include <errno.h>
 #include <unistd.h>
 #include <time.h>
 
-#include <set>
+#include <string>
+
+#include <libs/syncpoint/syncpoint.h>
+#include <libs/syncpoint/syncpoint_manager.h>
+#include <libs/syncpoint/exceptions.h>
+
+#include <core/utils/refptr.h>
 
 using namespace fawkes;
+using namespace std;
 
 /** @class SyncPointTest
  * Test class for SyncPoint
@@ -50,9 +50,8 @@ class SyncPointTest : public ::testing::Test
      */
     virtual void SetUp()
     {
-      const char * id1 = "/id1";
-      const char * id2 = "/id2";
-      //const char * id3 = "/id3";
+      string id1 = "/id1";
+      string id2 = "/id2";
       sp1 = new SyncPoint(id1);
       sp2 = new SyncPoint(id1);
       sp3 = new SyncPoint(id2);
@@ -79,15 +78,29 @@ class SyncPointManagerTest : public ::testing::Test
     /**
      * Initialize the test class
      */
-    virtual void SetUp()
+    SyncPointManagerTest()
     {
       manager = new SyncPointManager();
+
+      pthread_attr_init(&attrs);
+
+    }
+
+    /**
+     * Deinitialize the test class
+     */
+    virtual ~SyncPointManagerTest()
+    {
+      pthread_attr_destroy(&attrs);
     }
 
     /**
      * A Pointer to a SyncPointManager
      */
     RefPtr<SyncPointManager> manager;
+
+    /** Thread attributes */
+    pthread_attr_t attrs;
 };
 
 TEST_F(SyncPointTest, CreateSyncPoint)
@@ -113,7 +126,7 @@ TEST_F(SyncPointTest, LessThan)
   ASSERT_FALSE(**sp2 < **sp1);
 }
 
-TEST_F(SyncPointTest, Sets)
+TEST_F(SyncPointTest, SyncPointSets)
 {
   using namespace std;
   set<RefPtr<SyncPoint>, SyncPointSetLessThan > sp_set;
@@ -142,18 +155,27 @@ TEST_F(SyncPointTest, Sets)
 
 TEST_F(SyncPointManagerTest, SyncPointManager)
 {
-  ASSERT_EQ(manager->get_syncpoints().size(), 0);
+  ASSERT_EQ(manager->get_syncpoints().size(), 0u);
   manager->get_syncpoint("test", "/test/1");
-  ASSERT_EQ(manager->get_syncpoints().size(), 1);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1);
+  ASSERT_EQ(manager->get_syncpoints().size(), 1u);
+  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1u);
   manager->get_syncpoint("test", "/test/2");
-  ASSERT_EQ(manager->get_syncpoints().size(), 2);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))), 1);
+  ASSERT_EQ(manager->get_syncpoints().size(), 2u);
+  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1u);
+  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))), 1u);
   manager->get_syncpoint("test2", "/test/1");
-  ASSERT_EQ(manager->get_syncpoints().size(), 2);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))), 1);
+  ASSERT_EQ(manager->get_syncpoints().size(), 2u);
+  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1u);
+  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))), 1u);
+}
+
+TEST_F(SyncPointManagerTest, WatcherSet)
+{
+  ASSERT_NO_THROW(manager->get_syncpoint("component 1", "/test"));
+  ASSERT_NO_THROW(manager->get_syncpoint("component 2", "/test"));
+  ASSERT_NO_THROW(manager->get_syncpoint("component 3", "/test"));
+  ASSERT_THROW(manager->get_syncpoint("component 1", "/test"), SyncPointAlreadyOpenedException);
+
 }
 
 TEST_F(SyncPointTest, EmptyIdentifier)
@@ -194,11 +216,12 @@ TEST_F(SyncPointManagerTest, MultipleWaits)
   RefPtr<SyncPoint> sp_ref = manager->get_syncpoint("component", "/test/sp1");
   SyncPoint * sp = *sp_ref;
   pthread_t thread1;
-  pthread_create(&thread1, NULL, call_wait, (void *)sp);
+  pthread_create(&thread1, &attrs, call_wait, (void *)sp);
   // make sure the other thread is first
-  usleep(100);
+  usleep(10000);
   ASSERT_THROW(sp_ref->wait("component"), SyncPointMultipleWaitCallsException);
   pthread_cancel(thread1);
+  pthread_join(thread1, NULL);
 }
 
 
@@ -208,33 +231,78 @@ struct waiter_thread_params {
     RefPtr<SyncPointManager> manager;
     /** Thread number */
     uint thread_nr;
+    /** Number of wait calls the thread should make */
+    uint num_wait_calls;
+    /** Name of the SyncPoint */
+    string sp_identifier;
 };
 
+
 /** get a SyncPoint and wait for it */
 void * start_waiter_thread(void * data) {
   waiter_thread_params *params = (waiter_thread_params *)data;
-  char component[40];
-  sprintf(component, "component %u", params->thread_nr);
-  RefPtr<SyncPoint> sp = params->manager->get_syncpoint(component, "/test/sp1");
-  sp->wait(component);
-  return NULL;
+  char *comp;
+  asprintf(&comp, "component %u", params->thread_nr);
+  string component = comp;
+  free(comp);
+  RefPtr<SyncPoint> sp = params->manager->get_syncpoint(component, params->sp_identifier);
+  for (uint i = 0; i < params->num_wait_calls; i++) {
+    sp->wait(component);
+  }
+  pthread_exit(NULL);
+}
+/** Create multiple threads which will all call get_syncpoint
+ *  for the same SyncPoint. Do not wait for the SyncPoint but return
+ *  immediately.
+ */
+TEST_F(SyncPointManagerTest, MultipleManagerRequests)
+{
+  uint num_threads = 50;
+  pthread_t threads[num_threads];
+  waiter_thread_params *params[num_threads];
+  string sp_identifier = "/test/sp1";
+  for (uint i = 0; i < num_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    params[i]->num_wait_calls = 0;
+    params[i]->sp_identifier = sp_identifier;
+    pthread_create(&threads[i], &attrs, start_waiter_thread, params[i]);
+    pthread_yield();
+  }
+
+  for (uint i = 0; i < num_threads; i++) {
+    pthread_join(threads[i], NULL);
+    delete params[i];
+  }
 }
 
+
+/** start multiple threads and let them wait.
+ *  This just tests whether there are any segfaults.
+ *  No assertions are made.
+ */
 TEST_F(SyncPointManagerTest, ParallelWaitCalls)
 {
-  uint num_threads = 100;
+  uint num_threads = 50;
+  uint num_wait_calls = 10;
   pthread_t threads[num_threads];
   waiter_thread_params *params[num_threads];
+  string sp_identifier = "/test/sp1";
   for (uint i = 0; i < num_threads; i++) {
     params[i] = new waiter_thread_params();
     params[i]->manager = manager;
     params[i]->thread_nr = i;
-    pthread_create(&threads[i], NULL, start_waiter_thread, params[i]);
+    params[i]->num_wait_calls = num_wait_calls;
+    params[i]->sp_identifier = sp_identifier;
+    pthread_create(&threads[i], &attrs, start_waiter_thread, params[i]);
+    pthread_yield();
   }
 
-  usleep(100);
+  usleep(10000);
   for (uint i = 0; i < num_threads; i++) {
     pthread_cancel(threads[i]);
+    ASSERT_EQ(0,pthread_join(threads[i], NULL));
     delete params[i];
   }
 }
@@ -244,21 +312,30 @@ TEST_F(SyncPointManagerTest, ParallelWaitCalls)
  */
 TEST_F(SyncPointManagerTest, ParallelWaitsReturn)
 {
-  uint num_threads = 100;
+
+  uint num_threads = 50;
+  uint num_wait_calls = 10;
   pthread_t threads[num_threads];
   waiter_thread_params *params[num_threads];
+  string sp_identifier = "/test/sp1";
   for (uint i = 0; i < num_threads; i++) {
     params[i] = new waiter_thread_params();
     params[i]->manager = manager;
     params[i]->thread_nr = i;
-    pthread_create(&threads[i], NULL, start_waiter_thread, params[i]);
+    params[i]->num_wait_calls = num_wait_calls;
+    params[i]->sp_identifier = sp_identifier;
+    pthread_create(&threads[i], &attrs, start_waiter_thread, params[i]);
+    usleep(10000);
   }
 
-  usleep(50);
-  RefPtr<SyncPoint> sp =manager->get_syncpoint("main_thread", "/test/sp1");
+  string component = "emitter";
+  RefPtr<SyncPoint> sp = manager->get_syncpoint(component, sp_identifier);
+  for (uint i = 0; i < num_wait_calls; i++) {
+    sp->emit(component);
+    usleep(10000);
+  }
 
-  sp->emit("main_thread");
-  usleep(500);
+  sleep(1);
   for (uint i = 0; i < num_threads; i++) {
     ASSERT_EQ(0, pthread_tryjoin_np(threads[i], NULL));
     delete params[i];
@@ -270,22 +347,23 @@ TEST_F(SyncPointManagerTest, ParallelWaitsReturn)
  */
 TEST_F(SyncPointManagerTest, WaitDoesNotReturnImmediately)
 {
-  uint num_threads = 100;
+  uint num_threads = 50;
   pthread_t threads[num_threads];
   waiter_thread_params *params[num_threads];
   for (uint i = 0; i < num_threads; i++) {
     params[i] = new waiter_thread_params();
     params[i]->manager = manager;
     params[i]->thread_nr = i;
-    pthread_create(&threads[i], NULL, start_waiter_thread, params[i]);
+    params[i]->num_wait_calls = 1;
+    params[i]->sp_identifier = "/test/sp1";
+    pthread_create(&threads[i], &attrs, start_waiter_thread, params[i]);
   }
 
-  usleep(50);
-  RefPtr<SyncPoint> sp =manager->get_syncpoint("main_thread", "/test/sp1");
-  usleep(500);
-
+  sleep(1);
   for (uint i = 0; i < num_threads; i++) {
-    ASSERT_EQ(16, pthread_tryjoin_np(threads[i], NULL));
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(threads[i], NULL));
+    pthread_cancel(threads[i]);
+    ASSERT_EQ(0, pthread_join(threads[i], NULL));
     delete params[i];
   }
 }

- *commit* 45a094a2b22ac3fb3e2d2d81e88c31e6d6d84bc6 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Sun Jan 25 02:27:48 2015 +0100
Subject: syncpoint: add SyncBarriers

 src/libs/syncpoint/exceptions.h          |   37 +++++++
 src/libs/syncpoint/syncbarrier.cpp       |  160 ++++++++++++++++++++++++++++++
 src/libs/syncpoint/syncbarrier.h         |   65 ++++++++++++
 src/libs/syncpoint/syncpoint.cpp         |    3 +
 src/libs/syncpoint/syncpoint.h           |   14 ++-
 src/libs/syncpoint/syncpoint_manager.cpp |   83 +++++++++++++++
 src/libs/syncpoint/syncpoint_manager.h   |   14 ++-
 7 files changed, 369 insertions(+), 7 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/exceptions.h b/src/libs/syncpoint/exceptions.h
index a1bf769..6d69606 100644
--- a/src/libs/syncpoint/exceptions.h
+++ b/src/libs/syncpoint/exceptions.h
@@ -171,6 +171,43 @@ class SyncPointMultipleWaitCallsException : public Exception
     }
 };
 
+/** A component tried to register as emitter but is already registered
+ *
+ */
+class SyncBarrierMultipleRegisterCallsException : public Exception
+{
+public:
+  /** Constructor.
+   * @param component The calling component
+   * @param identifier The identifier of the SyncBarrier
+   */
+	SyncBarrierMultipleRegisterCallsException(const char * component,
+    const char * identifier)
+  {
+    append("Component '%s' called register_emitter() on SyncBarrier '%s', but is already registered",
+        component, identifier);
+  }
+};
+
+/** Emit was called on a SyncBarrier but the calling component is not registered
+ *  as emitter
+ */
+class SyncBarrierNonEmitterCalledEmitException : public Exception
+{
+  public:
+    /** Constructor.
+     * @param component The calling component
+     * @param identifier The identifier of the SyncPoint
+     */
+	SyncBarrierNonEmitterCalledEmitException(const char * component,
+      const char *identifier)
+    {
+      append("Component '%s' called emit for SyncBarrier '%s', "
+	  "but is not a registered emitter",
+          component, identifier);
+    }
+};
+
 
 } // namespace fawkes
 
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index a25d3ac..e945de7 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -154,6 +154,9 @@ SyncPoint::wait(const std::string & component) {
 
 /** Add a watcher to the watch list
  *  @param watcher the new watcher
+ *  @return A pair, of which the first element is an iterator that points
+ *           to the possibly inserted element, and the second is a bool
+ *           that is true if the element was actually inserted.
  */
 pair<set<string>::iterator,bool>
 SyncPoint::add_watcher(string watcher)
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index fb54f05..813377c 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -23,7 +23,6 @@
 #define __SYNCPOINT_SYNCPOINT_H_
 
 #include <interface/interface.h>
-#include <syncpoint/syncpoint_manager.h>
 #include <syncpoint/syncpoint_call.h>
 #include <core/threading/mutex.h>
 #include <core/threading/wait_condition.h>
@@ -40,7 +39,6 @@ namespace fawkes {
 #endif
 
 class SyncPointManager;
-class SyncPointCall;
 
 
 class SyncPoint
@@ -69,19 +67,27 @@ class SyncPoint
      */
     friend class SyncPointManager;
 
-  private:
+  protected:
     std::pair<std::set<std::string>::iterator,bool> add_watcher(std::string watcher);
 
-  private:
+  protected:
+    /** The unique identifier of the SyncPoint */
     const std::string identifier_;
+    /** Set of all components which use this SyncPoint */
     std::set<std::string> watchers_;
+    /** Set of all components which are currently waiting for the SyncPoint */
     std::set<std::string> waiting_watchers_;
 
+    /** A buffer of the most recent emit calls. */
     CircularBuffer<SyncPointCall> emit_calls_;
+    /** A buffer of the most recent wait calls. */
     CircularBuffer<SyncPointCall> wait_calls_;
+    /** Time when this SyncPoint was created */
     const Time creation_time_;
 
+    /** Mutex used to protect all member variables */
     Mutex *mutex_;
+    /** WaitCondition which is used for wait() and emit() */
     WaitCondition *wait_condition_;
 };
 
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index a06ef48..8ae57a8 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -75,6 +75,7 @@ SyncPointManager::get_syncpoint(const std::string & component, const std::string
   // insert a new SyncPoint if no SyncPoint with the same identifier exists,
   // otherwise, use that SyncPoint
   std::pair<std::set<RefPtr<SyncPoint> >::iterator,bool> ret;
+  // TODO clean this up we don't need to catch the exception
   try {
   ret = syncpoints_.insert(RefPtr<SyncPoint>(new SyncPoint(identifier)));
   } catch (const SyncPointInvalidIdentifierException &e) {
@@ -94,6 +95,40 @@ SyncPointManager::get_syncpoint(const std::string & component, const std::string
 }
 
 /**
+ * Get a SyncBarrier. This allows accessing the SyncBarrier's wait() and emit() methods
+ * @param component The name of the component calling the method
+ * @param identifier The identifier of the requested SyncBarrier
+ * @return A RefPtr to a SyncBarrier which is shared by all threads with this
+ * SyncBarrier.
+ * @throw SyncPointInvalidComponentException thrown if component name is invalid
+ * @throw SyncPointAlreadyOpenedException thrown if SyncPoint is already opened
+ * by the component
+ */
+RefPtr<SyncBarrier>
+SyncPointManager::get_syncbarrier(const std::string & component, const std::string & identifier)
+{
+  MutexLocker ml(mutex_);
+  if (component == "") {
+    throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
+  }
+  // insert a new SyncBarrier if no SyncBarrier with the same identifier exists,
+  // otherwise, use that SyncBarrier
+  std::pair<std::set<RefPtr<SyncBarrier> >::iterator, bool> ret =
+      syncbarriers_.insert(RefPtr<SyncBarrier>(new SyncBarrier(identifier)));
+
+  std::set<RefPtr<SyncBarrier> >::iterator it = ret.first;
+
+  // add component to the set of watchers
+  // check if component is already a watcher
+  // insert returns a pair whose second element is false if element already exists
+  if (!(*it)->add_watcher(component).second) {
+    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
+  }
+
+  return *it;
+}
+
+/**
  * Release a SyncPoint. After releasing the SyncPoint, its wait() and emit()
  * methods cannot be called anymore by the releasing component
  * @param component The releasing component
@@ -117,6 +152,29 @@ SyncPointManager::release_syncpoint(const std::string & component, RefPtr<SyncPo
   }
 }
 
+/**
+ * Release a SyncBarrier. After releasing the SyncBarrier, its wait() and emit()
+ * methods cannot be called anymore by the releasing component
+ * @param component The releasing component
+ * @param sync_barrier A RefPtr to the released SyncBarrier
+ * @throw SyncPointReleasedDoesNotExistException thrown if the SyncBarrier doesn't
+ * exist, i.e. is not in the list of the manager's SyncBarriers.
+ * @throw SyncPointReleasedByNonWatcherException The releasing component is not
+ * a watcher of the SyncBarrier
+ */
+void
+SyncPointManager::release_syncbarrier(const std::string & component, RefPtr<SyncBarrier> sync_barrier)
+{
+  MutexLocker ml(mutex_);
+  std::set<RefPtr<SyncBarrier> >::iterator sp_it = syncbarriers_.find(
+      sync_barrier);
+  if (sp_it == syncbarriers_.end()) {
+    throw SyncPointReleasedDoesNotExistException(component.c_str(), sync_barrier->get_identifier().c_str());
+  }
+  if (!(*sp_it)->watchers_.erase(component)) {
+    throw SyncPointReleasedByNonWatcherException(component.c_str(), sync_barrier->get_identifier().c_str());
+  }
+}
 
 /** @class SyncPointSetLessThan "syncpoint_manager.h"
  * Compare sets of syncpoints
@@ -146,6 +204,31 @@ SyncPointManager::get_syncpoints() {
 }
 
 /**
+ * Get the current list of all SyncBarriers managed by this SyncPointManager
+ * @return a set of SyncBarriers
+ */
+std::set<RefPtr<SyncBarrier>, SyncPointSetLessThan >
+SyncPointManager::get_syncbarriers() {
+  MutexLocker ml(mutex_);
+  return syncbarriers_;
+}
+
+/**
+ * Reset all SyncBarriers. Resetting the barrier causes all registered emitters
+ * to be pending again, every registered emitter has to emit the barrier before
+ * a waiter unblocks.
+ */
+void
+SyncPointManager::reset_syncbarriers()
+{
+  MutexLocker ml(mutex_);
+  for (std::set<RefPtr<SyncBarrier> >::iterator it = syncbarriers_.begin();
+      it != syncbarriers_.end(); it++) {
+    (*it)->reset_emitters();
+  }
+}
+
+/**
  * Get DOT graph for all SyncPoints
  * @param max_age Show only SyncPoint calls which are younger than max_age
  * @return string representation of DOT graph
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index d670237..acf2fdb 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -26,6 +26,7 @@
 #include <string>
 
 #include <syncpoint/syncpoint.h>
+#include <syncpoint/syncbarrier.h>
 #include <core/utils/refptr.h>
 #include <core/threading/mutex.h>
 
@@ -50,15 +51,22 @@ class SyncPointManager
     RefPtr<SyncPoint> get_syncpoint(const std::string & component, const std::string & identifier);
     void release_syncpoint(const std::string & component, RefPtr<SyncPoint> syncpoint);
 
+    RefPtr<SyncBarrier> get_syncbarrier(const std::string & component, const std::string & identifier);
+    void release_syncbarrier(const std::string & component, RefPtr<SyncBarrier> syncpoint);
+
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > get_syncpoints();
+    std::set<RefPtr<SyncBarrier>, SyncPointSetLessThan > get_syncbarriers();
+
+    void reset_syncbarriers();
+
 
     std::string all_syncpoints_as_dot(float max_age);
 
   protected:
-    /**
-     * Set of all existing SyncPoints
-     */
+    /** Set of all existing SyncPoints */
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints_;
+    /** Set of all existing SyncBarriers */
+    std::set<RefPtr<SyncBarrier>, SyncPointSetLessThan > syncbarriers_;
     /** Mutex used for all SyncPointManager calls */
     Mutex *mutex_;
 

- *commit* dfd84a96c252c1572236371f5430617646b2cb4c - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Jan 26 16:50:14 2015 +0100
Subject: syncpoint: add SyncBarrier tests

 src/libs/syncpoint/tests/test_syncpoint.cpp |  260 +++++++++++++++++++++++++++
 1 files changed, 260 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 44a6106..0b7a740 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -103,6 +103,18 @@ class SyncPointManagerTest : public ::testing::Test
     pthread_attr_t attrs;
 };
 
+/** @class SyncBarrierTest
+ *  Test SyncBarriers
+ */
+class SyncBarrierTest : public SyncPointManagerTest
+{
+protected:
+  /** Constructor. */
+  SyncBarrierTest()
+  {
+  }
+};
+
 TEST_F(SyncPointTest, CreateSyncPoint)
 {
   ASSERT_TRUE(*sp1 != NULL);
@@ -367,3 +379,251 @@ TEST_F(SyncPointManagerTest, WaitDoesNotReturnImmediately)
     delete params[i];
   }
 }
+
+/** get a SyncBarrier and wait for it */
+void * start_barrier_waiter_thread(void * data) {
+  waiter_thread_params *params = (waiter_thread_params *)data;
+  char *comp;
+  asprintf(&comp, "component %u", params->thread_nr);
+  string component = comp;
+  free(comp);
+  RefPtr<SyncBarrier> sp;
+  EXPECT_NO_THROW(sp = params->manager->get_syncbarrier(component, params->sp_identifier));
+  for (uint i = 0; i < params->num_wait_calls; i++) {
+    sp->wait(component);
+  }
+  pthread_exit(NULL);
+}
+
+/** get a SyncBarrier, register as emitter and emit */
+void * start_barrier_emitter_thread(void * data) {
+  waiter_thread_params *params = (waiter_thread_params *)data;
+  char *comp;
+  asprintf(&comp, "emitter %u", params->thread_nr);
+  string component = comp;
+  free(comp);
+  RefPtr<SyncBarrier> sp;
+  EXPECT_NO_THROW(sp = params->manager->get_syncbarrier(component, params->sp_identifier));
+  sp->register_emitter(component);
+  for (uint i = 0; i < params->num_wait_calls; i++) {
+    sp->emit(component);
+  }
+  pthread_exit(NULL);
+}
+
+/** Helper class which registers and emits a given SyncBarrier */
+class Emitter {
+public:
+  /** Constructor.
+   *  @param identifier The identifier of this emitter.
+   *  @param syncbarrier The identifier of the SyncBarrier to register for.
+   *  @param manager Pointer to the SyncPointManager to use.
+   */
+  Emitter(string identifier, string syncbarrier, RefPtr<SyncPointManager> manager)
+  : identifier_(identifier),
+    manager_(manager)
+  {
+    barrier_ = manager->get_syncbarrier(identifier_, syncbarrier);
+    barrier_->register_emitter(identifier_);
+  }
+
+  /** Destructor. */
+  virtual ~Emitter()
+  {
+    barrier_->unregister_emitter(identifier_);
+    manager_->release_syncbarrier(identifier_, barrier_);
+  }
+
+  /** emit the SyncBarrier */
+  void emit()
+  {
+    barrier_->emit(identifier_);
+  }
+
+private:
+  string identifier_;
+  RefPtr<SyncBarrier> barrier_;
+  RefPtr<SyncPointManager> manager_;
+};
+
+
+/** Barrier: wait() returns immediately if no emitter is registered */
+TEST_F(SyncBarrierTest,WaitWithNoRegisteredEmitter)
+{
+  string barrier_id = "/test/barrier";
+  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier("main loop", barrier_id);
+  barrier->reset_emitters();
+  const uint num_waiter_threads = 1;
+  const uint num_wait_calls = 1;
+  pthread_t waiter_threads[num_waiter_threads];
+  waiter_thread_params *params[num_waiter_threads];
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    params[i]->num_wait_calls = num_wait_calls;
+    params[i]->sp_identifier = barrier_id;
+    pthread_create(&waiter_threads[i], &attrs, start_barrier_waiter_thread, params[i]);
+    usleep(10000);
+  }
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(waiter_threads[i], NULL));
+    delete params[i];
+  }
+}
+
+/** Start multiple threads, let them wait for a SyncBarrier,
+ *  also have two threads registered as emitter.
+ *  Let the first thread emit the barrier, assert the waiters did not unblock,
+ *  then let the second thread emit.
+ *  This tests the fundamental difference to a SyncPoint: With a SyncPoint,
+ *  wait() returns if the SyncPoint is emitted by one component.
+ *  With a SyncBarrier, all registered emitters need to emit the SyncBarrier
+ *  before wait() returns.
+ */
+TEST_F(SyncBarrierTest, WaitForAllEmitters)
+{
+
+  string barrier_id = "/test/barrier";
+  Emitter em1("emitter 1", barrier_id, manager);
+  Emitter em2("emitter 2", barrier_id, manager);
+
+  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier("main loop", barrier_id);
+  barrier->reset_emitters();
+
+  const uint num_waiter_threads = 50;
+  const uint num_wait_calls = 1;
+  pthread_t waiter_threads[num_waiter_threads];
+  waiter_thread_params *params[num_waiter_threads];
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    params[i]->num_wait_calls = num_wait_calls;
+    params[i]->sp_identifier = barrier_id;
+    pthread_create(&waiter_threads[i], &attrs, start_barrier_waiter_thread, params[i]);
+    usleep(10000);
+  }
+
+  sleep(1);
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(waiter_threads[i], NULL));
+  }
+
+  em1.emit();
+
+  sleep(1);
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(waiter_threads[i], NULL));
+  }
+
+  em1.emit();
+
+  sleep(1);
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(waiter_threads[i], NULL));
+  }
+
+  em2.emit();
+
+  sleep(1);
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(waiter_threads[i], NULL));
+    delete params[i];
+  }
+}
+
+
+/** two barriers, emit the first one. Only the threads waiting on the first
+ *  barrier should unblock
+ */
+TEST_F(SyncBarrierTest, BarriersAreIndependent)
+{
+  string barrier1_id = "/test/barrier1";
+  string barrier2_id = "/test/barrier2";
+  Emitter em1("em1", barrier1_id, manager);
+  Emitter em2("em2", barrier2_id, manager);
+
+  RefPtr<SyncBarrier> barrier1 = manager->get_syncbarrier("main loop",
+    barrier1_id);
+  barrier1->reset_emitters();
+
+  RefPtr<SyncBarrier> barrier2 = manager->get_syncbarrier("main loop",
+    barrier2_id);
+  barrier2->reset_emitters();
+
+  const uint num_waiter_threads = 50;
+  const uint num_wait_calls = 1;
+  pthread_t waiter_threads1[num_waiter_threads];
+  waiter_thread_params *params1[num_waiter_threads];
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    params1[i] = new waiter_thread_params();
+    params1[i]->manager = manager;
+    params1[i]->thread_nr = i;
+    params1[i]->num_wait_calls = num_wait_calls;
+    params1[i]->sp_identifier = barrier1_id;
+    pthread_create(&waiter_threads1[i], &attrs, start_barrier_waiter_thread,
+      params1[i]);
+    usleep(10000);
+  }
+
+  pthread_t waiter_threads2[num_waiter_threads];
+  waiter_thread_params *params2[num_waiter_threads];
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    params2[i] = new waiter_thread_params();
+    params2[i]->manager = manager;
+    params2[i]->thread_nr = i;
+    params2[i]->num_wait_calls = num_wait_calls;
+    params2[i]->sp_identifier = barrier2_id;
+    pthread_create(&waiter_threads2[i], &attrs, start_barrier_waiter_thread,
+      params2[i]);
+    usleep(10000);
+  }
+
+  sleep(1);
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(waiter_threads1[i], NULL));
+  }
+
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(waiter_threads2[i], NULL));
+  }
+
+  em1.emit();
+
+  sleep(1);
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(waiter_threads1[i], NULL));
+    delete params1[i];
+  }
+
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(waiter_threads2[i], NULL));
+  }
+
+  em2.emit();
+
+  sleep(1);
+  for (uint i = 0; i < num_waiter_threads; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(waiter_threads2[i], NULL));
+    delete params2[i];
+  }
+}
+
+/** Emit a barrier without registering */
+TEST_F(SyncBarrierTest, EmitWithoutRegister)
+{
+  string component = "emitter";
+  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
+  ASSERT_THROW(barrier->emit(component), SyncBarrierNonEmitterCalledEmitException);
+}
+
+/** Register multiple times */
+TEST_F(SyncBarrierTest, MultipleRegisterCalls)
+{
+  string component = "emitter";
+  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
+  EXPECT_NO_THROW(barrier->register_emitter(component));
+  ASSERT_THROW(barrier->register_emitter(component), SyncBarrierMultipleRegisterCallsException);
+}
+

- *commit* 67b8437a605e6f8d39920a550b89b2756f52382d - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Jan 26 18:08:55 2015 +0100
Subject: syncpoint: always reset pending emitters after SyncBarrier was released

 src/libs/syncpoint/syncbarrier.cpp       |   24 ++++++++++--------------
 src/libs/syncpoint/syncbarrier.h         |    7 ++++---
 src/libs/syncpoint/syncpoint_manager.cpp |   14 --------------
 src/libs/syncpoint/syncpoint_manager.h   |    2 --
 4 files changed, 14 insertions(+), 33 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncbarrier.cpp b/src/libs/syncpoint/syncbarrier.cpp
index 73c3da2..f5f33cd 100644
--- a/src/libs/syncpoint/syncbarrier.cpp
+++ b/src/libs/syncpoint/syncbarrier.cpp
@@ -93,22 +93,10 @@ SyncBarrier::emit(const string & component)
   if (pending_emitters_.empty()) {
     waiting_watchers_.clear();
     wait_condition_->wake_all();
+    reset_emitters_();
   }
 }
 
-/** Wait until SyncPoint is emitted
- * @param component The identifier of the component waiting for the SyncPoint
- */
-void
-SyncBarrier::wait(const string & component)
-{
-  if (!is_emitted()) {
-    // TODO
-    // this might actually break if the last emitter emits
-    // right here, between the is_emitter() call and the wait() call
-    SyncPoint::wait(component);
-  }
-}
 
 /** Register an emitter. A thread can only emit the barrier if it has been
  *  registered.
@@ -154,7 +142,15 @@ SyncBarrier::is_emitted() const {
 void
 SyncBarrier::reset_emitters() {
 	MutexLocker ml(mutex_);
-	pending_emitters_ = emitters_;
+	reset_emitters_();
+}
+
+/** Helper function. This allows to reset emitters both with mutex_ locked
+ *  and unlocked.
+ */
+void
+SyncBarrier::reset_emitters_() {
+  pending_emitters_ = emitters_;
 }
 
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncbarrier.h b/src/libs/syncpoint/syncbarrier.h
index 3f1255e..12e7087 100644
--- a/src/libs/syncpoint/syncbarrier.h
+++ b/src/libs/syncpoint/syncbarrier.h
@@ -47,14 +47,15 @@ class SyncBarrier : public SyncPoint
     /** send a signal to all waiting threads */
     virtual void emit(const std::string & component);
 
-    /** wait for the sync point to be emitted */
-    virtual void wait(const std::string & component);
-
     /** check whether the barrier is already emitted */
     virtual bool is_emitted() const;
 
     /** set all registered emitter as pending */
     void reset_emitters();
+
+  private:
+    void reset_emitters_();
+
   private:
     std::set<std::string> emitters_;
     std::set<std::string> pending_emitters_;
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 8ae57a8..63f9d47 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -213,20 +213,6 @@ SyncPointManager::get_syncbarriers() {
   return syncbarriers_;
 }
 
-/**
- * Reset all SyncBarriers. Resetting the barrier causes all registered emitters
- * to be pending again, every registered emitter has to emit the barrier before
- * a waiter unblocks.
- */
-void
-SyncPointManager::reset_syncbarriers()
-{
-  MutexLocker ml(mutex_);
-  for (std::set<RefPtr<SyncBarrier> >::iterator it = syncbarriers_.begin();
-      it != syncbarriers_.end(); it++) {
-    (*it)->reset_emitters();
-  }
-}
 
 /**
  * Get DOT graph for all SyncPoints
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index acf2fdb..169e91a 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -57,8 +57,6 @@ class SyncPointManager
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > get_syncpoints();
     std::set<RefPtr<SyncBarrier>, SyncPointSetLessThan > get_syncbarriers();
 
-    void reset_syncbarriers();
-
 
     std::string all_syncpoints_as_dot(float max_age);
 

- *commit* 6defe69477d0677fff7865fcb89b4fe9c4e27dde - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Feb 2 13:19:21 2015 +0100
Subject: syncpoint: only wait for a SyncBarrier if emitter exists

 src/libs/syncpoint/syncbarrier.cpp |   16 ++++++++++++++++
 src/libs/syncpoint/syncbarrier.h   |    3 +++
 2 files changed, 19 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncbarrier.cpp b/src/libs/syncpoint/syncbarrier.cpp
index f5f33cd..3e984be 100644
--- a/src/libs/syncpoint/syncbarrier.cpp
+++ b/src/libs/syncpoint/syncbarrier.cpp
@@ -97,6 +97,22 @@ SyncBarrier::emit(const string & component)
   }
 }
 
+/** Wait for the SyncBarrier.
+ *  If no emitters have registered for the barrier, return immediately.
+ *  Otherwise, wait until all registered emitters have emitted the SyncBarrier.
+ *  @param component The identifier of the component waiting for the SyncBarrier
+ */
+void
+SyncBarrier::wait(const string & component)
+{
+  mutex_->lock();
+  bool need_to_wait = !emitters_.empty();
+  mutex_->unlock();
+  if (need_to_wait) {
+    SyncPoint::wait(component);
+  }
+}
+
 
 /** Register an emitter. A thread can only emit the barrier if it has been
  *  registered.
diff --git a/src/libs/syncpoint/syncbarrier.h b/src/libs/syncpoint/syncbarrier.h
index 12e7087..3e53279 100644
--- a/src/libs/syncpoint/syncbarrier.h
+++ b/src/libs/syncpoint/syncbarrier.h
@@ -47,6 +47,9 @@ class SyncBarrier : public SyncPoint
     /** send a signal to all waiting threads */
     virtual void emit(const std::string & component);
 
+    /** wait for the barrier */
+    virtual void wait(const std::string & component);
+
     /** check whether the barrier is already emitted */
     virtual bool is_emitted() const;
 

- *commit* 982cfe1407c64a6893c04d9ab74ece270197e45f - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Feb 2 14:27:52 2015 +0100
Subject: syncpoint: add additional identifier constraints

 src/libs/syncpoint/exceptions.h  |    3 ++-
 src/libs/syncpoint/syncpoint.cpp |    8 ++++++++
 2 files changed, 10 insertions(+), 1 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/exceptions.h b/src/libs/syncpoint/exceptions.h
index 6d69606..988adf9 100644
--- a/src/libs/syncpoint/exceptions.h
+++ b/src/libs/syncpoint/exceptions.h
@@ -130,7 +130,8 @@ class SyncPointInvalidIdentifierException : public Exception
     SyncPointInvalidIdentifierException(const char * identifier)
     {
       append("Tried to construct a SyncPoint with invalid identifier ('%s'). "
-          "Identifier must be a non-empty absolute path (e.g. '/path/to/syncpoint')",
+          "Identifier must be a non-empty absolute path (e.g. '/path/to/syncpoint')"
+          " and may not end with '/'",
           identifier);
     }
 };
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index e945de7..6347804 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -71,6 +71,14 @@ SyncPoint::SyncPoint(string identifier)
     delete mutex_;
     throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
+  // check if last charater is '/'
+  // The identifier may only end in '/' if '/' is the complete identifier.
+  // '/' is allowed, '/some/' is not allowed
+  if (identifier != "/" && !identifier.compare(identifier.size() - 1, 1, "/")) {
+    delete wait_condition_;
+    delete mutex_;
+    throw SyncPointInvalidIdentifierException(identifier.c_str());
+  }
 }
 
 SyncPoint::~SyncPoint()

- *commit* 73a334157ab0993a6260dec806b3ca1d57f94d86 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Feb 2 14:30:14 2015 +0100
Subject: syncpoint: test additional identifier constraints

 src/libs/syncpoint/tests/test_syncpoint.cpp |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 0b7a740..116a6b8 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -197,8 +197,9 @@ TEST_F(SyncPointTest, EmptyIdentifier)
 
 TEST_F(SyncPointTest, InvalidIdentifier)
 {
-  ASSERT_THROW(sp1 = new SyncPoint("invalid"), SyncPointInvalidIdentifierException);
-
+  EXPECT_THROW(sp1 = new SyncPoint("invalid"), SyncPointInvalidIdentifierException);
+  EXPECT_NO_THROW(sp1 = new SyncPoint("/"));
+  EXPECT_THROW(sp1 = new SyncPoint("/test/"), SyncPointInvalidIdentifierException);
 }
 
 TEST_F(SyncPointManagerTest, SyncPointManagerExceptions) {

- *commit* a541425382acf929c0741c19097dc875de7a17b7 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 13 14:29:08 2015 +0100
Subject: syncpoint: add SyncPoint hierarchy

 src/libs/syncpoint/syncpoint.cpp         |    3 +
 src/libs/syncpoint/syncpoint.h           |    6 ++
 src/libs/syncpoint/syncpoint_manager.cpp |  104 ++++++++++++++++++++----------
 src/libs/syncpoint/syncpoint_manager.h   |    6 ++
 4 files changed, 86 insertions(+), 33 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 6347804..aa1c7c0 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -132,6 +132,9 @@ SyncPoint::emit(const std::string & component)
   emit_calls_.push_back(SyncPointCall(component));
   mutex_->unlock();
   wait_condition_->wake_all();
+  if (predecessor_) {
+    predecessor_->emit(component);
+  }
 }
 
 /** Wait until SyncPoint is emitted
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 813377c..65743be 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -28,6 +28,7 @@
 #include <core/threading/wait_condition.h>
 #include <utils/time/time.h>
 
+#include <core/utils/refptr.h>
 #include <core/utils/circular_buffer.h>
 
 #include <set>
@@ -78,6 +79,11 @@ class SyncPoint
     /** Set of all components which are currently waiting for the SyncPoint */
     std::set<std::string> waiting_watchers_;
 
+    /** The predecessor SyncPoint, which is the SyncPoint one level up
+     *  e.g. "/test/sp" -> "/test"
+     */
+    RefPtr<SyncPoint> predecessor_;
+
     /** A buffer of the most recent emit calls. */
     CircularBuffer<SyncPointCall> emit_calls_;
     /** A buffer of the most recent wait calls. */
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 63f9d47..2693014 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -56,7 +56,9 @@ SyncPointManager::~SyncPointManager()
 }
 
 /**
- * Get a SyncPoint. This allows accessing the SyncPoint's wait() and emit() methods
+ * Get a SyncPoint. This allows accessing the SyncPoint's wait() and emit() methods.
+ * This function creates a SyncPoint with the given identifier if it does not
+ * exist yet and constructs its predecessor.
  * @param component The name of the component calling the method
  * @param identifier The identifier of the requested SyncPoint
  * @return A RefPtr to a SyncPoint which is shared by all threads with this
@@ -69,29 +71,7 @@ RefPtr<SyncPoint>
 SyncPointManager::get_syncpoint(const std::string & component, const std::string & identifier)
 {
   MutexLocker ml(mutex_);
-  if (component == "") {
-    throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
-  }
-  // insert a new SyncPoint if no SyncPoint with the same identifier exists,
-  // otherwise, use that SyncPoint
-  std::pair<std::set<RefPtr<SyncPoint> >::iterator,bool> ret;
-  // TODO clean this up we don't need to catch the exception
-  try {
-  ret = syncpoints_.insert(RefPtr<SyncPoint>(new SyncPoint(identifier)));
-  } catch (const SyncPointInvalidIdentifierException &e) {
-    throw;
-  }
-
-  std::set<RefPtr<SyncPoint> >::iterator it = ret.first;
-
-  // add component to the set of watchers
-  // check if component is already a watcher
-  // insert returns a pair whose second element is false if element already exists
-  if (!(*it)->add_watcher(component).second) {
-    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
-  }
-
-  return *it;
+  return get_syncpoint_no_lock(component, identifier);
 }
 
 /**
@@ -130,7 +110,8 @@ SyncPointManager::get_syncbarrier(const std::string & component, const std::stri
 
 /**
  * Release a SyncPoint. After releasing the SyncPoint, its wait() and emit()
- * methods cannot be called anymore by the releasing component
+ * methods cannot be called anymore by the releasing component.
+ * This also releases the SyncPoint's predecessor if existent.
  * @param component The releasing component
  * @param sync_point A RefPtr to the released SyncPoint
  * @throw SyncPointReleasedDoesNotExistException thrown if the SyncPoint doesn't
@@ -142,14 +123,7 @@ void
 SyncPointManager::release_syncpoint(const std::string & component, RefPtr<SyncPoint> sync_point)
 {
   MutexLocker ml(mutex_);
-  std::set<RefPtr<SyncPoint> >::iterator sp_it = syncpoints_.find(
-      sync_point);
-  if (sp_it == syncpoints_.end()) {
-    throw SyncPointReleasedDoesNotExistException(component.c_str(), sync_point->get_identifier().c_str());
-  }
-  if (!(*sp_it)->watchers_.erase(component)) {
-    throw SyncPointReleasedByNonWatcherException(component.c_str(), sync_point->get_identifier().c_str());
-  }
+  release_syncpoint_no_lock(component, sync_point);
 }
 
 /**
@@ -283,4 +257,68 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
   return graph.str();
 }
 
+/** Find the prefix of the SyncPoint's identifier which is the identifier of
+ *  the direct predecessor SyncPoint.
+ *  The predecessor of a SyncPoint "/some/path" is "/some"
+ *  @param identifier The identifier of the SyncPoint
+ *  @return The identifier of the predecessor SyncPoint
+ */
+std::string
+SyncPointManager::find_prefix(const std::string & identifier) const
+{
+  size_t last_pos = identifier.rfind("/");
+  if (last_pos != 0) {
+    return identifier.substr(0, last_pos);
+  } else {
+    return "/";
+  }
+}
+
+RefPtr<SyncPoint>
+SyncPointManager::get_syncpoint_no_lock(const std::string & component, const std::string & identifier)
+{
+  if (component == "") {
+    throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
+  }
+  // insert a new SyncPoint if no SyncPoint with the same identifier exists,
+  // otherwise, use that SyncPoint
+  std::pair<std::set<RefPtr<SyncPoint> >::iterator,bool> insert_ret;
+  insert_ret = syncpoints_.insert(RefPtr<SyncPoint>(new SyncPoint(identifier)));
+  std::set<RefPtr<SyncPoint> >::iterator sp_it = insert_ret.first;
+
+  // add component to the set of watchers
+  // check if component is already a watcher
+  // insert returns a pair whose second element is false if element already exists
+  if (!(*sp_it)->add_watcher(component).second) {
+    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
+  }
+
+  if (identifier != "/") {
+    // create prefix SyncPoints.
+    // If this is the root SyncPoint ("/"), there will be no prefix
+    std::string prefix = find_prefix(identifier);
+    RefPtr<SyncPoint> predecessor = get_syncpoint_no_lock(component, prefix);
+    (*sp_it)->predecessor_ = predecessor;
+  }
+
+  return *sp_it;
+}
+
+void
+SyncPointManager::release_syncpoint_no_lock(const std::string & component, RefPtr<SyncPoint> sync_point)
+{
+  std::set<RefPtr<SyncPoint> >::iterator sp_it = syncpoints_.find(
+      sync_point);
+  if (sp_it == syncpoints_.end()) {
+    throw SyncPointReleasedDoesNotExistException(component.c_str(), sync_point->get_identifier().c_str());
+  }
+  if (!(*sp_it)->watchers_.erase(component)) {
+    throw SyncPointReleasedByNonWatcherException(component.c_str(), sync_point->get_identifier().c_str());
+  }
+
+  if (sync_point->predecessor_) {
+    release_syncpoint_no_lock(component, sync_point->predecessor_);
+  }
+}
+
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index 169e91a..c8d31ba 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -68,6 +68,12 @@ class SyncPointManager
     /** Mutex used for all SyncPointManager calls */
     Mutex *mutex_;
 
+  private:
+    std::string find_prefix(const std::string & identifier) const;
+    RefPtr<SyncPoint> get_syncpoint_no_lock(const std::string & component, const std::string & identifier);
+    void release_syncpoint_no_lock(const std::string & component, RefPtr<SyncPoint> syncpoint);
+
+
 
 };
 

- *commit* 8aa12b32e483992704904082cbc90127ad7e7edc - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 13 14:36:12 2015 +0100
Subject: syncpoint: add test for SyncPoint hierarchy

 src/libs/syncpoint/tests/Makefile           |    4 +-
 src/libs/syncpoint/tests/test_syncpoint.cpp |  123 +++++++++++++++++++++------
 2 files changed, 97 insertions(+), 30 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/Makefile b/src/libs/syncpoint/tests/Makefile
index e9b314e..a8112e6 100644
--- a/src/libs/syncpoint/tests/Makefile
+++ b/src/libs/syncpoint/tests/Makefile
@@ -23,8 +23,8 @@ LIBS_gtest_syncpoint += stdc++ fawkescore fawkesutils fawkessyncpoint pthread
 OBJS_gtest_syncpoint += test_syncpoint.o
 OBJS_all = $(OBJS_gtest_syncpoint)
 
-ifeq ($(HAVE_GTEST),1)
-  CFLAGS += $(CFLAGS_GTEST)
+ifeq ($(HAVE_GTEST)$(HAVE_CPP11),11)
+  CFLAGS += $(CFLAGS_GTEST) $(CFLAGS_CPP11)
   LDFLAGS += $(LDFLAGS_GTEST)
   LIBS_test = $(LIBDIR)/test/syncpoint.so
   BINS_test = $(BINDIR)/gtest_syncpoint
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 116a6b8..2ed7ccf 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -167,18 +167,20 @@ TEST_F(SyncPointTest, SyncPointSets)
 
 TEST_F(SyncPointManagerTest, SyncPointManager)
 {
-  ASSERT_EQ(manager->get_syncpoints().size(), 0u);
+  ASSERT_EQ(0u, manager->get_syncpoints().size());
   manager->get_syncpoint("test", "/test/1");
-  ASSERT_EQ(manager->get_syncpoints().size(), 1u);
+  ASSERT_EQ(3u, manager->get_syncpoints().size());
   ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1u);
-  manager->get_syncpoint("test", "/test/2");
-  ASSERT_EQ(manager->get_syncpoints().size(), 2u);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1u);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))), 1u);
-  manager->get_syncpoint("test2", "/test/1");
-  ASSERT_EQ(manager->get_syncpoints().size(), 2u);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1u);
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))), 1u);
+  manager->get_syncpoint("test2", "/test/2");
+  ASSERT_EQ(4u, manager->get_syncpoints().size());
+  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))));
+  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))));
+  manager->get_syncpoint("test3", "/test/1");
+  ASSERT_EQ(4u, manager->get_syncpoints().size());
+  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))));
+  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))));
+  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/"))));
+  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test"))));
 }
 
 TEST_F(SyncPointManagerTest, WatcherSet)
@@ -190,6 +192,30 @@ TEST_F(SyncPointManagerTest, WatcherSet)
 
 }
 
+/** Test what happens if we acquire a SyncPoint, release it, and then acquire it
+ * again. If release_syncpoint works properly, this should not throw. Otherwise,
+ * we would expect a SyncPointAlreadyOpenedException
+ */
+TEST_F(SyncPointManagerTest, ReleaseAndReacquire)
+{
+  string comp = "component";
+  string id = "/test/sp1";
+  RefPtr<SyncPoint> sp = manager->get_syncpoint(comp, id);
+  set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints = manager->get_syncpoints();
+  ASSERT_EQ(1, syncpoints.count(RefPtr<SyncPoint>(new SyncPoint("/test"))));
+  for (set<RefPtr<SyncPoint> >::const_iterator sp_it = syncpoints.begin();
+      sp_it != syncpoints.end(); sp_it++) {
+    EXPECT_EQ(1, (*sp_it)->get_watchers().count(comp)) << "for component " << comp;
+  }
+  manager->release_syncpoint(comp, sp);
+  for (set<RefPtr<SyncPoint> >::const_iterator sp_it = syncpoints.begin();
+      sp_it != syncpoints.end(); sp_it++) {
+    EXPECT_EQ(0, (*sp_it)->get_watchers().count(comp)) << "for component '"
+        << comp << "' and SyncPoint '" << (*sp_it)->get_identifier() << "'";
+  }
+  ASSERT_NO_THROW(manager->get_syncpoint(comp, id));
+}
+
 TEST_F(SyncPointTest, EmptyIdentifier)
 {
   ASSERT_THROW(sp1 = new SyncPoint(""), SyncPointInvalidIdentifierException);
@@ -212,8 +238,6 @@ TEST_F(SyncPointManagerTest, SyncPointManagerExceptions) {
       SyncPointInvalidIdentifierException);
   ASSERT_THROW(invalid_sp = manager->get_syncpoint("waiter", "invalid"),
         SyncPointInvalidIdentifierException);
-
-
 }
 
 // helper function used for testing wait()
@@ -264,6 +288,7 @@ void * start_waiter_thread(void * data) {
   }
   pthread_exit(NULL);
 }
+
 /** Create multiple threads which will all call get_syncpoint
  *  for the same SyncPoint. Do not wait for the SyncPoint but return
  *  immediately.
@@ -282,6 +307,7 @@ TEST_F(SyncPointManagerTest, MultipleManagerRequests)
     params[i]->sp_identifier = sp_identifier;
     pthread_create(&threads[i], &attrs, start_waiter_thread, params[i]);
     pthread_yield();
+    ASSERT_LE(manager->get_syncpoints().size(), 3u);
   }
 
   for (uint i = 0; i < num_threads; i++) {
@@ -310,6 +336,7 @@ TEST_F(SyncPointManagerTest, ParallelWaitCalls)
     params[i]->sp_identifier = sp_identifier;
     pthread_create(&threads[i], &attrs, start_waiter_thread, params[i]);
     pthread_yield();
+    ASSERT_LE(manager->get_syncpoints().size(), 3u);
   }
 
   usleep(10000);
@@ -381,6 +408,62 @@ TEST_F(SyncPointManagerTest, WaitDoesNotReturnImmediately)
   }
 }
 
+/**
+ * Test the SyncPoint hierarchy.
+ * This creates a SyncPoint, an emitter and waiters which wait for the
+ * SyncPoint's predecessor, the predecessor's predecessor (grandparent),
+ * and the root SyncPoint ("/").
+ */
+TEST_F(SyncPointManagerTest, SyncPointHierarchy)
+{
+  vector<string> identifiers = { "/test/topic", "/test", "/", "/other/topic" };
+  uint num_threads = identifiers.size();
+  pthread_t threads[num_threads];
+  waiter_thread_params *params[num_threads];
+  for (uint i = 0; i < num_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    params[i]->num_wait_calls = 1;
+    params[i]->sp_identifier = identifiers.at(i);
+    pthread_create(&threads[i], &attrs, start_waiter_thread, params[i]);
+  }
+
+  usleep(10000);
+  RefPtr<SyncPoint> sp = manager->get_syncpoint("emitter", "/test/topic/sp");
+  sp->emit("emitter");
+  usleep(10000);
+
+  /* The first waiters should be unblocked */
+  for (uint i = 0; i < num_threads - 1 ; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(threads[i], NULL));
+    delete params[i];
+  }
+
+  /* The last waiter should still wait */
+  pthread_t last_thread = threads[num_threads-1];
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(last_thread, NULL));
+  pthread_cancel(last_thread);
+  ASSERT_EQ(0, pthread_join(last_thread, NULL));
+}
+
+/** Emit a barrier without registering */
+TEST_F(SyncBarrierTest, EmitWithoutRegister)
+{
+  string component = "emitter";
+  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
+  ASSERT_THROW(barrier->emit(component), SyncBarrierNonEmitterCalledEmitException);
+}
+
+/** Register multiple times */
+TEST_F(SyncBarrierTest, MultipleRegisterCalls)
+{
+  string component = "emitter";
+  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
+  EXPECT_NO_THROW(barrier->register_emitter(component));
+  ASSERT_THROW(barrier->register_emitter(component), SyncBarrierMultipleRegisterCallsException);
+}
+
 /** get a SyncBarrier and wait for it */
 void * start_barrier_waiter_thread(void * data) {
   waiter_thread_params *params = (waiter_thread_params *)data;
@@ -611,20 +694,4 @@ TEST_F(SyncBarrierTest, BarriersAreIndependent)
   }
 }
 
-/** Emit a barrier without registering */
-TEST_F(SyncBarrierTest, EmitWithoutRegister)
-{
-  string component = "emitter";
-  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
-  ASSERT_THROW(barrier->emit(component), SyncBarrierNonEmitterCalledEmitException);
-}
-
-/** Register multiple times */
-TEST_F(SyncBarrierTest, MultipleRegisterCalls)
-{
-  string component = "emitter";
-  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
-  EXPECT_NO_THROW(barrier->register_emitter(component));
-  ASSERT_THROW(barrier->register_emitter(component), SyncBarrierMultipleRegisterCallsException);
-}
 

- *commit* d4dc9370bc1b5b0f4ec9e52b887ab3a643b1a4f3 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 13 15:15:09 2015 +0100
Subject: syncpoint: add SyncBarrier hierarchy

 src/libs/syncpoint/syncbarrier.cpp       |   10 ++++
 src/libs/syncpoint/syncbarrier.h         |    7 +++
 src/libs/syncpoint/syncpoint.h           |   11 +++--
 src/libs/syncpoint/syncpoint_manager.cpp |   70 ++++++++++++++++++++++--------
 src/libs/syncpoint/syncpoint_manager.h   |   12 ++++-
 5 files changed, 85 insertions(+), 25 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncbarrier.cpp b/src/libs/syncpoint/syncbarrier.cpp
index 3e984be..8abb97d 100644
--- a/src/libs/syncpoint/syncbarrier.cpp
+++ b/src/libs/syncpoint/syncbarrier.cpp
@@ -95,6 +95,10 @@ SyncBarrier::emit(const string & component)
     wait_condition_->wake_all();
     reset_emitters_();
   }
+
+  if (predecessor_) {
+    predecessor_->emit(component);
+  }
 }
 
 /** Wait for the SyncBarrier.
@@ -128,6 +132,9 @@ SyncBarrier::register_emitter(const string & component)
   }
   // TODO if a new emitter registers, should it already be part of the barrier
   // in this iteration? If so, we need to insert it in pending_emitters, too
+  if (predecessor_) {
+    predecessor_->register_emitter(component);
+  }
 }
 
 /** Unregister an emitter. This removes the component from the barrier, thus
@@ -140,6 +147,9 @@ SyncBarrier::unregister_emitter(const string & component) {
   MutexLocker ml(mutex_);
   pending_emitters_.erase(component);
   emitters_.erase(component);
+  if (predecessor_) {
+    predecessor_->unregister_emitter(component);
+  }
 }
 
 /** Check if the barrier is already open,
diff --git a/src/libs/syncpoint/syncbarrier.h b/src/libs/syncpoint/syncbarrier.h
index 3e53279..b5d3663 100644
--- a/src/libs/syncpoint/syncbarrier.h
+++ b/src/libs/syncpoint/syncbarrier.h
@@ -56,12 +56,19 @@ class SyncBarrier : public SyncPoint
     /** set all registered emitter as pending */
     void reset_emitters();
 
+    /**
+     * allow Syncpoint Manager to edit
+     */
+    friend class SyncPointManager;
+
   private:
     void reset_emitters_();
 
   private:
     std::set<std::string> emitters_;
     std::set<std::string> pending_emitters_;
+
+    RefPtr<SyncBarrier> predecessor_;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 65743be..c5adafb 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -79,11 +79,6 @@ class SyncPoint
     /** Set of all components which are currently waiting for the SyncPoint */
     std::set<std::string> waiting_watchers_;
 
-    /** The predecessor SyncPoint, which is the SyncPoint one level up
-     *  e.g. "/test/sp" -> "/test"
-     */
-    RefPtr<SyncPoint> predecessor_;
-
     /** A buffer of the most recent emit calls. */
     CircularBuffer<SyncPointCall> emit_calls_;
     /** A buffer of the most recent wait calls. */
@@ -95,6 +90,12 @@ class SyncPoint
     Mutex *mutex_;
     /** WaitCondition which is used for wait() and emit() */
     WaitCondition *wait_condition_;
+
+  private:
+    /** The predecessor SyncPoint, which is the SyncPoint one level up
+     *  e.g. "/test/sp" -> "/test"
+     */
+    RefPtr<SyncPoint> predecessor_;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 2693014..1703dfd 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -88,24 +88,7 @@ RefPtr<SyncBarrier>
 SyncPointManager::get_syncbarrier(const std::string & component, const std::string & identifier)
 {
   MutexLocker ml(mutex_);
-  if (component == "") {
-    throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
-  }
-  // insert a new SyncBarrier if no SyncBarrier with the same identifier exists,
-  // otherwise, use that SyncBarrier
-  std::pair<std::set<RefPtr<SyncBarrier> >::iterator, bool> ret =
-      syncbarriers_.insert(RefPtr<SyncBarrier>(new SyncBarrier(identifier)));
-
-  std::set<RefPtr<SyncBarrier> >::iterator it = ret.first;
-
-  // add component to the set of watchers
-  // check if component is already a watcher
-  // insert returns a pair whose second element is false if element already exists
-  if (!(*it)->add_watcher(component).second) {
-    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
-  }
-
-  return *it;
+  return get_syncbarrier_no_lock(component, identifier);
 }
 
 /**
@@ -304,6 +287,37 @@ SyncPointManager::get_syncpoint_no_lock(const std::string & component, const std
   return *sp_it;
 }
 
+RefPtr<SyncBarrier>
+SyncPointManager::get_syncbarrier_no_lock(const std::string & component, const std::string & identifier)
+{
+  if (component == "") {
+    throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
+  }
+  // insert a new SyncBarrier if no SyncBarrier with the same identifier exists,
+  // otherwise, use that SyncBarrier
+  std::pair<std::set<RefPtr<SyncBarrier> >::iterator, bool> ret =
+      syncbarriers_.insert(RefPtr<SyncBarrier>(new SyncBarrier(identifier)));
+
+  std::set<RefPtr<SyncBarrier> >::iterator it = ret.first;
+
+  // add component to the set of watchers
+  // check if component is already a watcher
+  // insert returns a pair whose second element is false if element already exists
+  if (!(*it)->add_watcher(component).second) {
+    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
+  }
+
+  if (identifier != "/") {
+    // create prefix SyncBarriers.
+    // If this is the root SyncBarrier ("/"), there will be no prefix
+    std::string prefix = find_prefix(identifier);
+    RefPtr<SyncBarrier> predecessor = get_syncbarrier_no_lock(component, prefix);
+    (*it)->predecessor_ = predecessor;
+  }
+
+  return *it;
+}
+
 void
 SyncPointManager::release_syncpoint_no_lock(const std::string & component, RefPtr<SyncPoint> sync_point)
 {
@@ -321,4 +335,24 @@ SyncPointManager::release_syncpoint_no_lock(const std::string & component, RefPt
   }
 }
 
+void
+SyncPointManager::release_syncbarrier_no_lock(
+  const std::string & component, RefPtr<SyncBarrier> sync_barrier)
+{
+  MutexLocker ml(mutex_);
+  std::set<RefPtr<SyncBarrier> >::iterator sp_it = syncbarriers_.find(
+      sync_barrier);
+  if (sp_it == syncbarriers_.end()) {
+    throw SyncPointReleasedDoesNotExistException(component.c_str(),
+        sync_barrier->get_identifier().c_str());
+  }
+  if (!(*sp_it)->watchers_.erase(component)) {
+    throw SyncPointReleasedByNonWatcherException(component.c_str(),
+        sync_barrier->get_identifier().c_str());
+  }
+
+  if (sync_barrier->predecessor_) {
+    release_syncbarrier_no_lock(component, sync_barrier->predecessor_);
+  }
+}
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index c8d31ba..701013a 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -70,8 +70,16 @@ class SyncPointManager
 
   private:
     std::string find_prefix(const std::string & identifier) const;
-    RefPtr<SyncPoint> get_syncpoint_no_lock(const std::string & component, const std::string & identifier);
-    void release_syncpoint_no_lock(const std::string & component, RefPtr<SyncPoint> syncpoint);
+    RefPtr<SyncPoint> get_syncpoint_no_lock(const std::string & component,
+      const std::string & identifier);
+    void release_syncpoint_no_lock(const std::string & component,
+      RefPtr<SyncPoint> syncpoint);
+    RefPtr<SyncBarrier> get_syncbarrier_no_lock(const std::string & component,
+      const std::string & identifier);
+    void release_syncbarrier_no_lock(const std::string & component,
+      RefPtr<SyncBarrier> sync_barrier);
+
+
 
 
 

- *commit* ea1c1e9213fd28f2bf202e4df35fbba3a41f3244 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 13 15:57:20 2015 +0100
Subject: syncpoint: add test for SyncBarrier hierarchy

 src/libs/syncpoint/tests/test_syncpoint.cpp |   58 +++++++++++++++++++++++++--
 1 files changed, 54 insertions(+), 4 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 2ed7ccf..7a8e6a0 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -472,7 +472,7 @@ void * start_barrier_waiter_thread(void * data) {
   string component = comp;
   free(comp);
   RefPtr<SyncBarrier> sp;
-  EXPECT_NO_THROW(sp = params->manager->get_syncbarrier(component, params->sp_identifier));
+  sp = params->manager->get_syncbarrier(component, params->sp_identifier);
   for (uint i = 0; i < params->num_wait_calls; i++) {
     sp->wait(component);
   }
@@ -628,11 +628,11 @@ TEST_F(SyncBarrierTest, BarriersAreIndependent)
   Emitter em1("em1", barrier1_id, manager);
   Emitter em2("em2", barrier2_id, manager);
 
-  RefPtr<SyncBarrier> barrier1 = manager->get_syncbarrier("main loop",
+  RefPtr<SyncBarrier> barrier1 = manager->get_syncbarrier("m1",
     barrier1_id);
   barrier1->reset_emitters();
 
-  RefPtr<SyncBarrier> barrier2 = manager->get_syncbarrier("main loop",
+  RefPtr<SyncBarrier> barrier2 = manager->get_syncbarrier("m2",
     barrier2_id);
   barrier2->reset_emitters();
 
@@ -656,7 +656,7 @@ TEST_F(SyncBarrierTest, BarriersAreIndependent)
   for (uint i = 0; i < num_waiter_threads; i++) {
     params2[i] = new waiter_thread_params();
     params2[i]->manager = manager;
-    params2[i]->thread_nr = i;
+    params2[i]->thread_nr = num_waiter_threads + i;
     params2[i]->num_wait_calls = num_wait_calls;
     params2[i]->sp_identifier = barrier2_id;
     pthread_create(&waiter_threads2[i], &attrs, start_barrier_waiter_thread,
@@ -694,4 +694,54 @@ TEST_F(SyncBarrierTest, BarriersAreIndependent)
   }
 }
 
+/**
+ * Test the SyncBarrier hierarchy, similar to the SyncPoint hierarchy test.
+ * This creates a SyncBarrier, an emitter and waiters which wait for the
+ * SyncBarrier's predecessor, the predecessor's predecessor (grandparent),
+ * and the root SyncBarrier ("/").
+ */
+TEST_F(SyncBarrierTest, SyncBarrierHierarchy)
+{
+  Emitter em1("emitter 1", "/test/topic/b1", manager);
+  Emitter em2("emitter 2", "/test/topic/b2", manager);
+  Emitter em3("emitter 3", "/other/topic", manager);
+
+  vector<string> identifiers = { "/test/topic", "/test", "/", "/other/topic" };
+  uint num_threads = identifiers.size();
+  pthread_t threads[num_threads];
+  waiter_thread_params *params[num_threads];
+  for (uint i = 0; i < num_threads; i++) {
+    params[i] = new waiter_thread_params();
+    params[i]->manager = manager;
+    params[i]->thread_nr = i;
+    params[i]->num_wait_calls = 1;
+    params[i]->sp_identifier = identifiers.at(i);
+    pthread_create(&threads[i], &attrs, start_barrier_waiter_thread, params[i]);
+  }
+
+  usleep(10000);
+
+  for (uint i = 0; i < num_threads; i++) {
+    ASSERT_EQ(EBUSY, pthread_tryjoin_np(threads[i], NULL));
+  }
+  em1.emit();
+  usleep(10000);
+  for (uint i = 0; i < num_threads; i++) {
+    ASSERT_EQ(EBUSY, pthread_tryjoin_np(threads[i], NULL));
+  }
+  em2.emit();
+  usleep(10000);
+  /* The first waiters should be unblocked */
+  for (uint i = 0; i < num_threads - 2 ; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(threads[i], NULL));
+    delete params[i];
+  }
+  /* The last two waiters should still be waiting */
+  for (uint i = num_threads - 2; i < num_threads; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(threads[i], NULL));
+    pthread_cancel(threads[i]);
+    ASSERT_EQ(0, pthread_join(threads[i], NULL));
+    delete params[i];
+  }
+}
 

- *commit* 6ac0e185729038a9a31a65977b24eb6f0d734603 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 13 15:58:00 2015 +0100
Subject: syncpoint: directly make a newly registered emitter pending

 src/libs/syncpoint/syncbarrier.cpp |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncbarrier.cpp b/src/libs/syncpoint/syncbarrier.cpp
index 8abb97d..43dcf9e 100644
--- a/src/libs/syncpoint/syncbarrier.cpp
+++ b/src/libs/syncpoint/syncbarrier.cpp
@@ -130,8 +130,7 @@ SyncBarrier::register_emitter(const string & component)
     throw SyncBarrierMultipleRegisterCallsException(component.c_str(),
       get_identifier().c_str());
   }
-  // TODO if a new emitter registers, should it already be part of the barrier
-  // in this iteration? If so, we need to insert it in pending_emitters, too
+  pending_emitters_.insert(component);
   if (predecessor_) {
     predecessor_->register_emitter(component);
   }

- *commit* 4955dbe8617900c485755cc033717da41d012c27 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Thu Feb 19 11:10:08 2015 +0100
Subject: Revert "syncpoint: add two simple test plugins"

 src/plugins/Makefile                               |    3 +-
 src/plugins/syncpoint_test-emitter/Makefile        |   30 -------
 .../syncpoint_test_emitter_plugin.cpp              |   46 -----------
 .../syncpoint_test_emitter_thread.cpp              |   68 ----------------
 .../syncpoint_test_emitter_thread.h                |   55 -------------
 src/plugins/syncpoint_test-waiter/Makefile         |   37 ---------
 .../syncpoint_test_waiter_plugin.cpp               |   46 -----------
 .../syncpoint_test_waiter_thread.cpp               |   85 --------------------
 .../syncpoint_test_waiter_thread.h                 |   54 ------------
 9 files changed, 1 insertions(+), 423 deletions(-)

_Diff for modified files_:
diff --git a/src/plugins/Makefile b/src/plugins/Makefile
index 9844ea3..caee20b 100644
--- a/src/plugins/Makefile
+++ b/src/plugins/Makefile
@@ -28,8 +28,7 @@ SUBDIRS	= bbsync bblogger webview ttmainloop rrd rrdweb \
 	  clips-tf openprs openprs-agent eclipse-clp \
 	  mongodb mongodb_log \
 	  openni refboxcomm ros player xmlrpc gossip \
-	  robot_state_publisher gazebo dynamixel navgraph-interactive \
-	  syncpoint_test-emitter syncpoint_test-waiter
+	  robot_state_publisher gazebo dynamixel navgraph-interactive
 
 include $(BUILDSYSDIR)/rules.mk
 

- *commit* 0deb47a02429b9b89c7f9a822f0f836d41574fa3 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Thu Feb 19 16:12:10 2015 +0100
Subject: core: add ThreadLoopListener

 src/libs/core/threading/thread.cpp                 |   38 ++++++++++++++++++++
 src/libs/core/threading/thread.h                   |    6 +++
 .../threading/thread_loop_listener.cpp}            |   31 +++++++++-------
 .../{spinlock.h => thread_loop_listener.h}         |   25 +++++--------
 4 files changed, 72 insertions(+), 28 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/core/threading/thread.cpp b/src/libs/core/threading/thread.cpp
index b8f829f..36ca109 100644
--- a/src/libs/core/threading/thread.cpp
+++ b/src/libs/core/threading/thread.cpp
@@ -29,6 +29,8 @@
 #include <core/threading/read_write_lock.h>
 #include <core/threading/thread_finalizer.h>
 #include <core/threading/thread_notification_listener.h>
+#include <core/threading/thread_loop_listener.h>
+
 #include <core/exceptions/software.h>
 #include <core/exceptions/system.h>
 #include <core/utils/lock_list.h>
@@ -250,6 +252,7 @@ Thread::__constructor(const char *name, OpMode op_mode)
   __op_mode = op_mode;
   __name   = strdup(name);
   __notification_listeners = new LockList<ThreadNotificationListener *>();
+  __loop_listeners         = new LockList<ThreadLoopListener *>();
 
   if ( __op_mode == OPMODE_WAITFORWAKEUP ) {
     __sleep_mutex        = new Mutex();
@@ -295,6 +298,7 @@ Thread::~Thread()
   delete loop_mutex;
   free(__name);
   delete __notification_listeners;
+  delete __loop_listeners;
   delete loopinterrupt_antistarve_mutex;
   delete __startup_barrier;
   delete __prepfin_hold_mutex;
@@ -954,7 +958,20 @@ Thread::run()
     loop_mutex->lock();
     if ( ! finalize_prepared ) {
       __loop_done = false;
+
+      for (LockList<ThreadLoopListener *>::iterator it = __loop_listeners->begin();
+          it != __loop_listeners->end();
+          it++) {
+        (*it)->pre_loop(this);
+      }
+
       loop();
+
+      for (LockList<ThreadLoopListener *>::reverse_iterator it = __loop_listeners->rbegin();
+          it != __loop_listeners->rend();
+          it++) {
+        (*it)->post_loop(this);
+      }
     }
     loop_mutex->unlock();
 
@@ -1181,6 +1198,27 @@ Thread::remove_notification_listener(ThreadNotificationListener *notification_li
 }
 
 
+/** Add loop listener.
+ * Add a loop listener for this thread.
+ * @param loop_listener loop listener to add
+ */
+void
+Thread::add_loop_listener(ThreadLoopListener *loop_listener)
+{
+  __loop_listeners->push_back_locked(loop_listener);
+}
+
+
+/** Remove loop listener.
+ * @param loop_listener loop listener to remove
+ */
+void
+Thread::remove_loop_listener(ThreadLoopListener *loop_listener)
+{
+  __loop_listeners->remove_locked(loop_listener);
+}
+
+
 /** Notify of successful startup.
  * This method is called internally in entry().
  */
diff --git a/src/libs/core/threading/thread.h b/src/libs/core/threading/thread.h
index 87e37b6..a8a91a3 100644
--- a/src/libs/core/threading/thread.h
+++ b/src/libs/core/threading/thread.h
@@ -36,6 +36,7 @@ class WaitCondition;
 class Mutex;
 class Barrier;
 class ThreadNotificationListener;
+class ThreadLoopListener;
 class ThreadList;
 template <typename Type> class LockList;
 
@@ -116,6 +117,9 @@ class Thread {
 
   void notify_of_failed_init();
 
+  void add_loop_listener(ThreadLoopListener *loop_listener);
+  void remove_loop_listener(ThreadLoopListener *loop_listener);
+
  protected:
   Thread(const char *name);
   Thread(const char *name, OpMode op_mode);
@@ -183,6 +187,8 @@ class Thread {
 
   LockList<ThreadNotificationListener *>  *__notification_listeners;
 
+  LockList<ThreadLoopListener *> *__loop_listeners;
+
   static pthread_key_t   THREAD_KEY;
   static pthread_key_t   MAIN_THREAD_KEY;
   static pthread_mutex_t __thread_key_mutex;

- *commit* 58a1459aa0627f1f3a4c23151641d0c58f8daa09 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Thu Feb 19 16:53:22 2015 +0100
Subject: aspects: add SyncPointAspect

 .../{syncpoint_manager.cpp => syncpoint.cpp}       |   38 +++--
 .../inifins/{syncpoint_manager.h => syncpoint.h}   |   17 +-
 src/libs/aspect/manager.cpp                        |    3 +
 src/libs/aspect/syncpoint.cpp                      |  156 ++++++++++++++++++++
 src/libs/aspect/syncpoint.h                        |   63 ++++++++
 5 files changed, 253 insertions(+), 24 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/aspect/manager.cpp b/src/libs/aspect/manager.cpp
index e5058f6..6eb6775 100644
--- a/src/libs/aspect/manager.cpp
+++ b/src/libs/aspect/manager.cpp
@@ -38,6 +38,7 @@
 #include <aspect/inifins/vision_master.h>
 #include <aspect/inifins/vision.h>
 #include <aspect/inifins/syncpoint_manager.h>
+#include <aspect/inifins/syncpoint.h>
 #ifdef HAVE_WEBVIEW
 #  include <aspect/inifins/webview.h>
 #endif
@@ -262,6 +263,7 @@ AspectManager::register_default_inifins(BlackBoard *blackboard,
   VisionMasterAspectIniFin *vm_aif = new VisionMasterAspectIniFin();
   VisionAspectIniFin *vis_aif = new VisionAspectIniFin(vm_aif);
   SyncPointManagerAspectIniFin *spm_aif = new SyncPointManagerAspectIniFin(syncpoint_manager);
+  SyncPointAspectIniFin *sp_aif = new SyncPointAspectIniFin(syncpoint_manager);
 #ifdef HAVE_WEBVIEW
   WebviewAspectIniFin *web_aif = new WebviewAspectIniFin();
 #endif
@@ -289,6 +291,7 @@ AspectManager::register_default_inifins(BlackBoard *blackboard,
   __default_inifins[vm_aif->get_aspect_name()] = vm_aif;
   __default_inifins[vis_aif->get_aspect_name()] = vis_aif;
   __default_inifins[spm_aif->get_aspect_name()] = spm_aif;
+  __default_inifins[sp_aif->get_aspect_name()] = sp_aif;
 #ifdef HAVE_WEBVIEW
   __default_inifins[web_aif->get_aspect_name()] = web_aif;
 #endif

- *commit* 9c4748595bcf1dd2ff16c29a847ac700eb433484 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 27 16:56:32 2015 +0100
Subject: syncpoint: SyncPoints are now also barriers

 src/libs/syncpoint/exceptions.h    |   20 ++++-
 src/libs/syncpoint/syncbarrier.cpp |  110 +----------------------
 src/libs/syncpoint/syncbarrier.h   |   31 -------
 src/libs/syncpoint/syncpoint.cpp   |  172 ++++++++++++++++++++++++++++++------
 src/libs/syncpoint/syncpoint.h     |   48 ++++++++--
 5 files changed, 204 insertions(+), 177 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/exceptions.h b/src/libs/syncpoint/exceptions.h
index 988adf9..c3d7da0 100644
--- a/src/libs/syncpoint/exceptions.h
+++ b/src/libs/syncpoint/exceptions.h
@@ -175,14 +175,14 @@ class SyncPointMultipleWaitCallsException : public Exception
 /** A component tried to register as emitter but is already registered
  *
  */
-class SyncBarrierMultipleRegisterCallsException : public Exception
+class SyncPointMultipleRegisterCallsException : public Exception
 {
 public:
   /** Constructor.
    * @param component The calling component
    * @param identifier The identifier of the SyncBarrier
    */
-	SyncBarrierMultipleRegisterCallsException(const char * component,
+	SyncPointMultipleRegisterCallsException(const char * component,
     const char * identifier)
   {
     append("Component '%s' called register_emitter() on SyncBarrier '%s', but is already registered",
@@ -193,14 +193,14 @@ public:
 /** Emit was called on a SyncBarrier but the calling component is not registered
  *  as emitter
  */
-class SyncBarrierNonEmitterCalledEmitException : public Exception
+class SyncPointNonEmitterCalledEmitException : public Exception
 {
   public:
     /** Constructor.
      * @param component The calling component
      * @param identifier The identifier of the SyncPoint
      */
-	SyncBarrierNonEmitterCalledEmitException(const char * component,
+	SyncPointNonEmitterCalledEmitException(const char * component,
       const char *identifier)
     {
       append("Component '%s' called emit for SyncBarrier '%s', "
@@ -209,6 +209,18 @@ class SyncBarrierNonEmitterCalledEmitException : public Exception
     }
 };
 
+/** Invalid SyncPoint type.
+ */
+class SyncPointInvalidTypeException : public Exception
+{
+public:
+  /** Constructor. */
+  SyncPointInvalidTypeException()
+  {
+    append("Invalid SyncPoint Wakeup type.");
+  }
+};
+
 
 } // namespace fawkes
 
diff --git a/src/libs/syncpoint/syncbarrier.cpp b/src/libs/syncpoint/syncbarrier.cpp
index 43dcf9e..27c3c59 100644
--- a/src/libs/syncpoint/syncbarrier.cpp
+++ b/src/libs/syncpoint/syncbarrier.cpp
@@ -21,11 +21,6 @@
 
 #include <syncpoint/syncpoint.h>
 #include <syncpoint/syncbarrier.h>
-#include <syncpoint/exceptions.h>
-
-#include <utils/time/time.h>
-
-#include <core/threading/mutex_locker.h>
 
 #include <string.h>
 
@@ -70,112 +65,13 @@ SyncBarrier::SyncBarrier(string identifier) :
 
 }
 
-
-/** Emit the SyncBarrier.
- *  If all registered emitters have emitted the barriers, all waiters are woken up.
- *  @param component The identifier of the component emitting the SyncBarrier
- */
-void
-SyncBarrier::emit(const string & component)
-{
-  MutexLocker ml(mutex_);
-  if (!emitters_.count(component)) {
-    throw SyncBarrierNonEmitterCalledEmitException(component.c_str(),
-      get_identifier().c_str());
-  }
-
-  // we do NOT expect the component to be pending
-  // a component may call emit multiple times in a loop
-  pending_emitters_.erase(component);
-  emit_calls_.push_back(SyncPointCall(component));
-
-  // all emitters have emitted the signal, thus wake all waking components
-  if (pending_emitters_.empty()) {
-    waiting_watchers_.clear();
-    wait_condition_->wake_all();
-    reset_emitters_();
-  }
-
-  if (predecessor_) {
-    predecessor_->emit(component);
-  }
-}
-
 /** Wait for the SyncBarrier.
- *  If no emitters have registered for the barrier, return immediately.
- *  Otherwise, wait until all registered emitters have emitted the SyncBarrier.
- *  @param component The identifier of the component waiting for the SyncBarrier
- */
-void
-SyncBarrier::wait(const string & component)
-{
-  mutex_->lock();
-  bool need_to_wait = !emitters_.empty();
-  mutex_->unlock();
-  if (need_to_wait) {
-    SyncPoint::wait(component);
-  }
-}
-
-
-/** Register an emitter. A thread can only emit the barrier if it has been
- *  registered.
- *  @param component The identifier of the registering component.
+ * This waits until all registered emitters of the SyncBarrier have emitted the barrier.
  */
 void
-SyncBarrier::register_emitter(const string & component)
+SyncBarrier::wait(const std::string & component)
 {
-  MutexLocker ml(mutex_);
-  if (!emitters_.insert(component).second) {
-    throw SyncBarrierMultipleRegisterCallsException(component.c_str(),
-      get_identifier().c_str());
-  }
-  pending_emitters_.insert(component);
-  if (predecessor_) {
-    predecessor_->register_emitter(component);
-  }
-}
-
-/** Unregister an emitter. This removes the component from the barrier, thus
- *  other components will not wait for it anymore.
- *  @param component The identifier of the component which is unregistered.
- */
-void
-SyncBarrier::unregister_emitter(const string & component) {
-  // TODO should this throw if the calling component is not registered?
-  MutexLocker ml(mutex_);
-  pending_emitters_.erase(component);
-  emitters_.erase(component);
-  if (predecessor_) {
-    predecessor_->unregister_emitter(component);
-  }
-}
-
-/** Check if the barrier is already open,
- *  i.e. if all registered emitters have already emitted the barrier.
- *  @return true if the SyncBarrier has been emitted.
- */
-bool
-SyncBarrier::is_emitted() const {
-	MutexLocker ml(mutex_);
-	return pending_emitters_.empty();
-}
-
-/** Reset all emitters. After reset, all registered emitters are again pending.
- *  Any waiter will block until all emitters have emitted the barrier again.
- */
-void
-SyncBarrier::reset_emitters() {
-	MutexLocker ml(mutex_);
-	reset_emitters_();
-}
-
-/** Helper function. This allows to reset emitters both with mutex_ locked
- *  and unlocked.
- */
-void
-SyncBarrier::reset_emitters_() {
-  pending_emitters_ = emitters_;
+  SyncPoint::wait(component, SyncPoint::WAIT_FOR_ALL);
 }
 
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncbarrier.h b/src/libs/syncpoint/syncbarrier.h
index b5d3663..325aa4a 100644
--- a/src/libs/syncpoint/syncbarrier.h
+++ b/src/libs/syncpoint/syncbarrier.h
@@ -24,9 +24,6 @@
 
 #include <syncpoint/syncpoint.h>
 
-#include <string>
-#include <set>
-
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
 }
@@ -38,37 +35,9 @@ class SyncBarrier : public SyncPoint
   public:
     SyncBarrier(std::string identifier);
 
-    /** register as emitter */
-    virtual void register_emitter(const std::string & component);
-
-    /** unregister as emitter */
-    virtual void unregister_emitter(const std::string & component);
-
-    /** send a signal to all waiting threads */
-    virtual void emit(const std::string & component);
-
     /** wait for the barrier */
     virtual void wait(const std::string & component);
 
-    /** check whether the barrier is already emitted */
-    virtual bool is_emitted() const;
-
-    /** set all registered emitter as pending */
-    void reset_emitters();
-
-    /**
-     * allow Syncpoint Manager to edit
-     */
-    friend class SyncPointManager;
-
-  private:
-    void reset_emitters_();
-
-  private:
-    std::set<std::string> emitters_;
-    std::set<std::string> pending_emitters_;
-
-    RefPtr<SyncBarrier> predecessor_;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index aa1c7c0..14e7f4e 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -56,18 +56,22 @@ namespace fawkes {
 SyncPoint::SyncPoint(string identifier)
     : identifier_(identifier),
       emit_calls_(CircularBuffer<SyncPointCall>(1000)),
-      wait_calls_(CircularBuffer<SyncPointCall>(1000)),
+      wait_for_one_calls_(CircularBuffer<SyncPointCall>(1000)),
+      wait_for_all_calls_(CircularBuffer<SyncPointCall>(1000)),
       creation_time_(Time()),
       mutex_(new Mutex()),
-      wait_condition_(new WaitCondition())
+      cond_wait_for_one_(new WaitCondition()),
+      cond_wait_for_all_(new WaitCondition())
 {
   if (identifier.empty()) {
-    delete wait_condition_;
+    delete cond_wait_for_one_;
+    delete cond_wait_for_all_;
     delete mutex_;
     throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
   if (identifier.compare(0,1,"/")) {
-    delete wait_condition_;
+    delete cond_wait_for_one_;
+    delete cond_wait_for_all_;
     delete mutex_;
     throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
@@ -75,7 +79,8 @@ SyncPoint::SyncPoint(string identifier)
   // The identifier may only end in '/' if '/' is the complete identifier.
   // '/' is allowed, '/some/' is not allowed
   if (identifier != "/" && !identifier.compare(identifier.size() - 1, 1, "/")) {
-    delete wait_condition_;
+    delete cond_wait_for_one_;
+    delete cond_wait_for_all_;
     delete mutex_;
     throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
@@ -83,7 +88,8 @@ SyncPoint::SyncPoint(string identifier)
 
 SyncPoint::~SyncPoint()
 {
-  delete wait_condition_;
+  delete cond_wait_for_one_;
+  delete cond_wait_for_all_;
   delete mutex_;
 }
 
@@ -123,44 +129,146 @@ SyncPoint::operator<(const SyncPoint &other) const
 void
 SyncPoint::emit(const std::string & component)
 {
-  mutex_->lock();
+  MutexLocker ml(mutex_);
   if (!watchers_.count(component)) {
-    mutex_->unlock();
     throw SyncPointNonWatcherCalledEmitException(component.c_str(), get_identifier().c_str());
   }
-  waiting_watchers_.clear();
+
+  // unlock all wait_for_one waiters
+  watchers_wait_for_one_.clear();
+  cond_wait_for_one_->wake_all();
+
+  // unlock all wait_for_all waiters if all pending emitters have emitted
+
+  if (!emitters_.count(component)) {
+    throw SyncPointNonEmitterCalledEmitException(component.c_str(),
+      get_identifier().c_str());
+  }
+  // we do NOT expect the component to be pending
+  // a component may call emit multiple times in a loop
+  pending_emitters_.erase(component);
+  if (pending_emitters_.empty()) {
+    // all emitters have emitted the signal, thus wake all waking components
+    watchers_wait_for_all_.clear();
+    cond_wait_for_all_->wake_all();
+    reset_emitters();
+  }
+
   emit_calls_.push_back(SyncPointCall(component));
-  mutex_->unlock();
-  wait_condition_->wake_all();
+
+  ml.unlock();
+
   if (predecessor_) {
     predecessor_->emit(component);
   }
 }
 
-/** Wait until SyncPoint is emitted
+/** Wait until SyncPoint is emitted.
+ * Either wait until a single emitter has emitted the SyncPoint, or wait
+ * until all registered emitters have emitted the SyncPoint.
  * @param component The identifier of the component waiting for the SyncPoint
+ * @param type the wakeup type. If this is set to WAIT_FOR_ONE, wait returns
+ * when a single emitter has emitted the SyncPoint. If set to WAIT_FOR_ALL, wait
+ * until all registered emitters have emitted the SyncPoint.
+ * @see SyncPoint::WakeupType
  */
 void
-SyncPoint::wait(const std::string & component) {
-  mutex_->lock();
+SyncPoint::wait(const std::string & component, WakeupType type /* = WAIT_FOR_ONE */) {
+  MutexLocker ml(mutex_);
+
+  std::set<std::string> *watchers;
+  WaitCondition *cond;
+  CircularBuffer<SyncPointCall> *calls;
+  // set watchers, cond and calls depending of the Wakeup type
+  if (type == WAIT_FOR_ONE) {
+    watchers = &watchers_wait_for_one_;
+    cond = cond_wait_for_one_;
+    calls = &wait_for_one_calls_;
+  } else if (type == WAIT_FOR_ALL) {
+    watchers = &watchers_wait_for_all_;
+    cond = cond_wait_for_all_;
+    calls = &wait_for_all_calls_;
+  } else {
+    throw SyncPointInvalidTypeException();
+  }
+
   // check if calling component is registered for this SyncPoint
   if (!watchers_.count(component)) {
-    mutex_->unlock();
     throw SyncPointNonWatcherCalledWaitException(component.c_str(), get_identifier().c_str());
   }
   // check if calling component is not already waiting
-  if (waiting_watchers_.count(component)) {
-    mutex_->unlock();
+  if (watchers->count(component)) {
     throw SyncPointMultipleWaitCallsException(component.c_str(), get_identifier().c_str());
   }
-  waiting_watchers_.insert(component);
-  mutex_->unlock();
+
+  /* if type == WAIT_FOR_ALL but no emitter has registered, we can
+   * immediately return
+   * if type == WAIT_FOR_ONE, we always wait
+   */
+  bool need_to_wait = !emitters_.empty() || type == WAIT_FOR_ONE;
+  if (need_to_wait) {
+    watchers->insert(component);
+  }
+  ml.unlock();
   Time start;
-  wait_condition_->wait();
+  if (need_to_wait) {
+    cond->wait();
+  }
   Time wait_time = Time() - start;
-  mutex_->lock();
-  wait_calls_.push_back(SyncPointCall(component, start, wait_time));
-  mutex_->unlock();
+  ml.relock();
+  calls->push_back(SyncPointCall(component, start, wait_time));
+}
+
+/** Wait for a single emitter.
+ * @param component The identifier of the calling component.
+ */
+void
+SyncPoint::wait_for_one(const string & component)
+{
+  wait(component, WAIT_FOR_ONE);
+}
+
+/** Wait for all registered emitters.
+ * @param component The identifier of the calling component.
+ */
+void
+SyncPoint::wait_for_all(const string & component)
+{
+  wait(component, WAIT_FOR_ALL);
+}
+
+
+/** Register an emitter. A thread can only emit the barrier if it has been
+ *  registered.
+ *  @param component The identifier of the registering component.
+ */
+void
+SyncPoint::register_emitter(const string & component)
+{
+  MutexLocker ml(mutex_);
+  if (!emitters_.insert(component).second) {
+    throw SyncPointMultipleRegisterCallsException(component.c_str(),
+      get_identifier().c_str());
+  }
+  pending_emitters_.insert(component);
+  if (predecessor_) {
+    predecessor_->register_emitter(component);
+  }
+}
+
+/** Unregister an emitter. This removes the component from the barrier, thus
+ *  other components will not wait for it anymore.
+ *  @param component The identifier of the component which is unregistered.
+ */
+void
+SyncPoint::unregister_emitter(const string & component) {
+  // TODO should this throw if the calling component is not registered?
+  MutexLocker ml(mutex_);
+  pending_emitters_.erase(component);
+  emitters_.erase(component);
+  if (predecessor_) {
+    predecessor_->unregister_emitter(component);
+  }
 }
 
 /** Add a watcher to the watch list
@@ -186,12 +294,19 @@ SyncPoint::get_watchers() const {
 }
 
 /**
- * @return a copy of the wait call buffer
+ * @return a copy of the wait call buffer with the given type
+ * @param type the type of the wait call buffer
  */
 CircularBuffer<SyncPointCall>
-SyncPoint::get_wait_calls() const {
+SyncPoint::get_wait_calls(WakeupType type /* = WAIT_FOR_ONE */) const {
   MutexLocker ml(mutex_);
-  return wait_calls_;
+  if (type == WAIT_FOR_ONE) {
+    return wait_for_one_calls_;
+  } else if (type == WAIT_FOR_ALL) {
+    return wait_for_all_calls_;
+  } else {
+    throw SyncPointInvalidTypeException();
+  }
 }
 
 
@@ -204,4 +319,9 @@ SyncPoint::get_emit_calls() const {
   return emit_calls_;
 }
 
+void
+SyncPoint::reset_emitters() {
+  pending_emitters_ = emitters_;
+}
+
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index c5adafb..4a4955f 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -45,21 +45,39 @@ class SyncPointManager;
 class SyncPoint
 {
   public:
+    /** Type to define when a thread wakes up after waiting for a SyncPoint.
+     * A thread can be either wake up if ANY other thread emits the SyncPoint,
+     * or if ALL registered threads emit the SyncPoint.
+     */
+    typedef enum {
+      WAIT_FOR_ONE,
+      WAIT_FOR_ALL,
+      NONE
+    } WakeupType;
+
     SyncPoint(std::string identifier);
     virtual ~SyncPoint();
 
     /** send a signal to all waiting threads */
     virtual void emit(const std::string & component);
 
-    /** wait for the sync point to be emitted */
-    virtual void wait(const std::string & component);
+    /** wait for the sync point to be emitted by any other component */
+    virtual void wait(const std::string & component, WakeupType = WAIT_FOR_ONE);
+    virtual void wait_for_one(const std::string & component);
+    virtual void wait_for_all(const std::string & component);
+
+    /** register as emitter */
+    virtual void register_emitter(const std::string & component);
+
+    /** unregister as emitter */
+    virtual void unregister_emitter(const std::string & component);
 
     std::string get_identifier() const;
     bool operator==(const SyncPoint & other) const;
     bool operator<(const SyncPoint & other) const;
 
     std::set<std::string> get_watchers() const;
-    CircularBuffer<SyncPointCall> get_wait_calls() const;
+    CircularBuffer<SyncPointCall> get_wait_calls(WakeupType type = WAIT_FOR_ONE) const;
     CircularBuffer<SyncPointCall> get_emit_calls() const;
 
 
@@ -76,26 +94,38 @@ class SyncPoint
     const std::string identifier_;
     /** Set of all components which use this SyncPoint */
     std::set<std::string> watchers_;
-    /** Set of all components which are currently waiting for the SyncPoint */
-    std::set<std::string> waiting_watchers_;
+    /** Set of all components which are currently waiting for a single emitter */
+    std::set<std::string> watchers_wait_for_one_;
+    /** Set of all components which are currently waiting on the barrier */
+    std::set<std::string> watchers_wait_for_all_;
 
     /** A buffer of the most recent emit calls. */
     CircularBuffer<SyncPointCall> emit_calls_;
-    /** A buffer of the most recent wait calls. */
-    CircularBuffer<SyncPointCall> wait_calls_;
+    /** A buffer of the most recent wait calls of type WAIT_FOR_ONE. */
+    CircularBuffer<SyncPointCall> wait_for_one_calls_;
+    /** A buffer of the most recent wait calls of type WAIT_FOR_ALL. */
+    CircularBuffer<SyncPointCall> wait_for_all_calls_;
     /** Time when this SyncPoint was created */
     const Time creation_time_;
 
     /** Mutex used to protect all member variables */
     Mutex *mutex_;
-    /** WaitCondition which is used for wait() and emit() */
-    WaitCondition *wait_condition_;
+    /** WaitCondition which is used for wait_for_one() */
+    WaitCondition *cond_wait_for_one_;
+    /** WaitCondition which is used for wait_for_all() */
+    WaitCondition *cond_wait_for_all_;
+
+  private:
+    void reset_emitters();
 
   private:
     /** The predecessor SyncPoint, which is the SyncPoint one level up
      *  e.g. "/test/sp" -> "/test"
      */
     RefPtr<SyncPoint> predecessor_;
+
+    std::set<std::string> emitters_;
+    std::set<std::string> pending_emitters_;
 };
 
 } // end namespace fawkes

- *commit* f6843ce0bdcfec0363666adac078bcf0c50f9d65 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 27 18:02:57 2015 +0100
Subject: syncpoint: remove SyncBarriers

 src/libs/syncpoint/syncbarrier.cpp |   77 ------------------------------------
 src/libs/syncpoint/syncbarrier.h   |   45 ---------------------
 2 files changed, 0 insertions(+), 122 deletions(-)


- *commit* f3e862f439fdcaf3cc635af57c1bc21730e86d93 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 27 18:11:55 2015 +0100
Subject: syncpoint: remove SyncBarrier support in aspects

 src/libs/aspect/syncpoint.cpp            |   23 ++-----
 src/libs/aspect/syncpoint.h              |    3 +-
 src/libs/aspect/syncpoint_manager.h      |    2 -
 src/libs/syncpoint/syncpoint_manager.cpp |  101 ------------------------------
 src/libs/syncpoint/syncpoint_manager.h   |   15 -----
 5 files changed, 6 insertions(+), 138 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/aspect/syncpoint.cpp b/src/libs/aspect/syncpoint.cpp
index a106d68..ece5810 100644
--- a/src/libs/aspect/syncpoint.cpp
+++ b/src/libs/aspect/syncpoint.cpp
@@ -84,18 +84,11 @@ void
 SyncPointAspect::init_SyncPointAspect(Thread *thread, SyncPointManager *manager)
 {
   if (has_input_syncpoint_) {
-    if (type_in_ == SyncPoint::WakeupType::WAIT_FOR_ONE) {
-      sp_in_ = manager->get_syncpoint(thread->name(), identifier_in_);
-    } else if (type_in_ == SyncPoint::WakeupType::WAIT_FOR_ALL) {
-      sp_in_ = manager->get_syncbarrier(thread->name(), identifier_in_);
-    } else {
-      // TODO there is an extra exception for this
-      throw Exception("Input syncpoint required but input has invalid syncpoint type.");
-    }
+    sp_in_ = manager->get_syncpoint(thread->name(), identifier_in_);
   }
 
   if (has_output_syncpoint_) {
-    sp_out_ = manager->get_syncbarrier(thread->name(), identifier_out_);
+    sp_out_ = manager->get_syncpoint(thread->name(), identifier_out_);
     sp_out_->register_emitter(thread->name());
   }
 
@@ -113,17 +106,11 @@ void
 SyncPointAspect::finalize_SyncPointAspect(Thread *thread, SyncPointManager *manager)
 {
   if (has_input_syncpoint_) {
-    if (type_in_ == SyncPoint::WakeupType::WAIT_FOR_ONE) {
-      manager->release_syncpoint(thread->name(), sp_in_);
-    } else if (type_in_ == SyncPoint::WakeupType::WAIT_FOR_ALL) {
-      manager->release_syncbarrier(thread->name(), sp_in_);
-    } else {
-      throw Exception("Input syncpoint required but input has invalid syncpoint type.");
-    }
+    manager->release_syncpoint(thread->name(), sp_in_);
   }
 
   if (has_output_syncpoint_) {
-    manager->release_syncbarrier(thread->name(), sp_out_);
+    manager->release_syncpoint(thread->name(), sp_out_);
   }
 
   if (has_input_syncpoint_ || has_output_syncpoint_) {
@@ -138,7 +125,7 @@ void
 SyncPointAspect::pre_loop(Thread *thread)
 {
   if (has_input_syncpoint_) {
-    sp_in_->wait(thread->name());
+    sp_in_->wait(thread->name(), type_in_);
   }
 }
 
diff --git a/src/libs/aspect/syncpoint.h b/src/libs/aspect/syncpoint.h
index c1e92ef..20b0019 100644
--- a/src/libs/aspect/syncpoint.h
+++ b/src/libs/aspect/syncpoint.h
@@ -24,7 +24,6 @@
 
 #include <aspect/aspect.h>
 #include <syncpoint/syncpoint.h>
-#include <syncpoint/syncbarrier.h>
 #include <syncpoint/syncpoint_manager.h>
 #include <core/threading/thread_loop_listener.h>
 
@@ -55,7 +54,7 @@ class SyncPointAspect : public virtual Aspect, public ThreadLoopListener
     bool has_input_syncpoint_;
     bool has_output_syncpoint_;
     RefPtr<SyncPoint> sp_in_;
-    RefPtr<SyncBarrier> sp_out_;
+    RefPtr<SyncPoint> sp_out_;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/aspect/syncpoint_manager.h b/src/libs/aspect/syncpoint_manager.h
index bb6e2a6..a00b9d1 100644
--- a/src/libs/aspect/syncpoint_manager.h
+++ b/src/libs/aspect/syncpoint_manager.h
@@ -25,8 +25,6 @@
 #include <aspect/aspect.h>
 #include <syncpoint/syncpoint_manager.h>
 
-#include <set>
-
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
 }
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 1703dfd..526b074 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -75,23 +75,6 @@ SyncPointManager::get_syncpoint(const std::string & component, const std::string
 }
 
 /**
- * Get a SyncBarrier. This allows accessing the SyncBarrier's wait() and emit() methods
- * @param component The name of the component calling the method
- * @param identifier The identifier of the requested SyncBarrier
- * @return A RefPtr to a SyncBarrier which is shared by all threads with this
- * SyncBarrier.
- * @throw SyncPointInvalidComponentException thrown if component name is invalid
- * @throw SyncPointAlreadyOpenedException thrown if SyncPoint is already opened
- * by the component
- */
-RefPtr<SyncBarrier>
-SyncPointManager::get_syncbarrier(const std::string & component, const std::string & identifier)
-{
-  MutexLocker ml(mutex_);
-  return get_syncbarrier_no_lock(component, identifier);
-}
-
-/**
  * Release a SyncPoint. After releasing the SyncPoint, its wait() and emit()
  * methods cannot be called anymore by the releasing component.
  * This also releases the SyncPoint's predecessor if existent.
@@ -109,30 +92,6 @@ SyncPointManager::release_syncpoint(const std::string & component, RefPtr<SyncPo
   release_syncpoint_no_lock(component, sync_point);
 }
 
-/**
- * Release a SyncBarrier. After releasing the SyncBarrier, its wait() and emit()
- * methods cannot be called anymore by the releasing component
- * @param component The releasing component
- * @param sync_barrier A RefPtr to the released SyncBarrier
- * @throw SyncPointReleasedDoesNotExistException thrown if the SyncBarrier doesn't
- * exist, i.e. is not in the list of the manager's SyncBarriers.
- * @throw SyncPointReleasedByNonWatcherException The releasing component is not
- * a watcher of the SyncBarrier
- */
-void
-SyncPointManager::release_syncbarrier(const std::string & component, RefPtr<SyncBarrier> sync_barrier)
-{
-  MutexLocker ml(mutex_);
-  std::set<RefPtr<SyncBarrier> >::iterator sp_it = syncbarriers_.find(
-      sync_barrier);
-  if (sp_it == syncbarriers_.end()) {
-    throw SyncPointReleasedDoesNotExistException(component.c_str(), sync_barrier->get_identifier().c_str());
-  }
-  if (!(*sp_it)->watchers_.erase(component)) {
-    throw SyncPointReleasedByNonWatcherException(component.c_str(), sync_barrier->get_identifier().c_str());
-  }
-}
-
 /** @class SyncPointSetLessThan "syncpoint_manager.h"
  * Compare sets of syncpoints
  */
@@ -161,17 +120,6 @@ SyncPointManager::get_syncpoints() {
 }
 
 /**
- * Get the current list of all SyncBarriers managed by this SyncPointManager
- * @return a set of SyncBarriers
- */
-std::set<RefPtr<SyncBarrier>, SyncPointSetLessThan >
-SyncPointManager::get_syncbarriers() {
-  MutexLocker ml(mutex_);
-  return syncbarriers_;
-}
-
-
-/**
  * Get DOT graph for all SyncPoints
  * @param max_age Show only SyncPoint calls which are younger than max_age
  * @return string representation of DOT graph
@@ -287,36 +235,6 @@ SyncPointManager::get_syncpoint_no_lock(const std::string & component, const std
   return *sp_it;
 }
 
-RefPtr<SyncBarrier>
-SyncPointManager::get_syncbarrier_no_lock(const std::string & component, const std::string & identifier)
-{
-  if (component == "") {
-    throw SyncPointInvalidComponentException(component.c_str(), identifier.c_str());
-  }
-  // insert a new SyncBarrier if no SyncBarrier with the same identifier exists,
-  // otherwise, use that SyncBarrier
-  std::pair<std::set<RefPtr<SyncBarrier> >::iterator, bool> ret =
-      syncbarriers_.insert(RefPtr<SyncBarrier>(new SyncBarrier(identifier)));
-
-  std::set<RefPtr<SyncBarrier> >::iterator it = ret.first;
-
-  // add component to the set of watchers
-  // check if component is already a watcher
-  // insert returns a pair whose second element is false if element already exists
-  if (!(*it)->add_watcher(component).second) {
-    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
-  }
-
-  if (identifier != "/") {
-    // create prefix SyncBarriers.
-    // If this is the root SyncBarrier ("/"), there will be no prefix
-    std::string prefix = find_prefix(identifier);
-    RefPtr<SyncBarrier> predecessor = get_syncbarrier_no_lock(component, prefix);
-    (*it)->predecessor_ = predecessor;
-  }
-
-  return *it;
-}
 
 void
 SyncPointManager::release_syncpoint_no_lock(const std::string & component, RefPtr<SyncPoint> sync_point)
@@ -335,24 +253,5 @@ SyncPointManager::release_syncpoint_no_lock(const std::string & component, RefPt
   }
 }
 
-void
-SyncPointManager::release_syncbarrier_no_lock(
-  const std::string & component, RefPtr<SyncBarrier> sync_barrier)
-{
-  MutexLocker ml(mutex_);
-  std::set<RefPtr<SyncBarrier> >::iterator sp_it = syncbarriers_.find(
-      sync_barrier);
-  if (sp_it == syncbarriers_.end()) {
-    throw SyncPointReleasedDoesNotExistException(component.c_str(),
-        sync_barrier->get_identifier().c_str());
-  }
-  if (!(*sp_it)->watchers_.erase(component)) {
-    throw SyncPointReleasedByNonWatcherException(component.c_str(),
-        sync_barrier->get_identifier().c_str());
-  }
 
-  if (sync_barrier->predecessor_) {
-    release_syncbarrier_no_lock(component, sync_barrier->predecessor_);
-  }
-}
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index 701013a..971ba2b 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -26,7 +26,6 @@
 #include <string>
 
 #include <syncpoint/syncpoint.h>
-#include <syncpoint/syncbarrier.h>
 #include <core/utils/refptr.h>
 #include <core/threading/mutex.h>
 
@@ -51,20 +50,13 @@ class SyncPointManager
     RefPtr<SyncPoint> get_syncpoint(const std::string & component, const std::string & identifier);
     void release_syncpoint(const std::string & component, RefPtr<SyncPoint> syncpoint);
 
-    RefPtr<SyncBarrier> get_syncbarrier(const std::string & component, const std::string & identifier);
-    void release_syncbarrier(const std::string & component, RefPtr<SyncBarrier> syncpoint);
-
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > get_syncpoints();
-    std::set<RefPtr<SyncBarrier>, SyncPointSetLessThan > get_syncbarriers();
-
 
     std::string all_syncpoints_as_dot(float max_age);
 
   protected:
     /** Set of all existing SyncPoints */
     std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints_;
-    /** Set of all existing SyncBarriers */
-    std::set<RefPtr<SyncBarrier>, SyncPointSetLessThan > syncbarriers_;
     /** Mutex used for all SyncPointManager calls */
     Mutex *mutex_;
 
@@ -74,13 +66,6 @@ class SyncPointManager
       const std::string & identifier);
     void release_syncpoint_no_lock(const std::string & component,
       RefPtr<SyncPoint> syncpoint);
-    RefPtr<SyncBarrier> get_syncbarrier_no_lock(const std::string & component,
-      const std::string & identifier);
-    void release_syncbarrier_no_lock(const std::string & component,
-      RefPtr<SyncBarrier> sync_barrier);
-
-
-
 
 
 };

- *commit* dfc3f07724456e3de0399e4ab419f2149e5280a6 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 27 18:14:01 2015 +0100
Subject: syncpoint: remove SyncBarriers from unit tests

 src/libs/syncpoint/tests/test_syncpoint.cpp |   38 ++++++++++++--------------
 1 files changed, 18 insertions(+), 20 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 7a8e6a0..8449ec1 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -370,6 +370,7 @@ TEST_F(SyncPointManagerTest, ParallelWaitsReturn)
 
   string component = "emitter";
   RefPtr<SyncPoint> sp = manager->get_syncpoint(component, sp_identifier);
+  sp->register_emitter(component);
   for (uint i = 0; i < num_wait_calls; i++) {
     sp->emit(component);
     usleep(10000);
@@ -431,6 +432,7 @@ TEST_F(SyncPointManagerTest, SyncPointHierarchy)
 
   usleep(10000);
   RefPtr<SyncPoint> sp = manager->get_syncpoint("emitter", "/test/topic/sp");
+  sp->register_emitter("emitter");
   sp->emit("emitter");
   usleep(10000);
 
@@ -451,17 +453,17 @@ TEST_F(SyncPointManagerTest, SyncPointHierarchy)
 TEST_F(SyncBarrierTest, EmitWithoutRegister)
 {
   string component = "emitter";
-  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
-  ASSERT_THROW(barrier->emit(component), SyncBarrierNonEmitterCalledEmitException);
+  RefPtr<SyncPoint> barrier = manager->get_syncpoint(component, "/test/barrier");
+  ASSERT_THROW(barrier->emit(component), SyncPointNonEmitterCalledEmitException);
 }
 
 /** Register multiple times */
 TEST_F(SyncBarrierTest, MultipleRegisterCalls)
 {
   string component = "emitter";
-  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier(component, "/test/barrier");
+  RefPtr<SyncPoint> barrier = manager->get_syncpoint(component, "/test/barrier");
   EXPECT_NO_THROW(barrier->register_emitter(component));
-  ASSERT_THROW(barrier->register_emitter(component), SyncBarrierMultipleRegisterCallsException);
+  ASSERT_THROW(barrier->register_emitter(component), SyncPointMultipleRegisterCallsException);
 }
 
 /** get a SyncBarrier and wait for it */
@@ -471,10 +473,10 @@ void * start_barrier_waiter_thread(void * data) {
   asprintf(&comp, "component %u", params->thread_nr);
   string component = comp;
   free(comp);
-  RefPtr<SyncBarrier> sp;
-  sp = params->manager->get_syncbarrier(component, params->sp_identifier);
+  RefPtr<SyncPoint> sp;
+  sp = params->manager->get_syncpoint(component, params->sp_identifier);
   for (uint i = 0; i < params->num_wait_calls; i++) {
-    sp->wait(component);
+    sp->wait(component, SyncPoint::WAIT_FOR_ALL);
   }
   pthread_exit(NULL);
 }
@@ -486,8 +488,8 @@ void * start_barrier_emitter_thread(void * data) {
   asprintf(&comp, "emitter %u", params->thread_nr);
   string component = comp;
   free(comp);
-  RefPtr<SyncBarrier> sp;
-  EXPECT_NO_THROW(sp = params->manager->get_syncbarrier(component, params->sp_identifier));
+  RefPtr<SyncPoint> sp;
+  EXPECT_NO_THROW(sp = params->manager->get_syncpoint(component, params->sp_identifier));
   sp->register_emitter(component);
   for (uint i = 0; i < params->num_wait_calls; i++) {
     sp->emit(component);
@@ -507,7 +509,7 @@ public:
   : identifier_(identifier),
     manager_(manager)
   {
-    barrier_ = manager->get_syncbarrier(identifier_, syncbarrier);
+    barrier_ = manager->get_syncpoint(identifier_, syncbarrier);
     barrier_->register_emitter(identifier_);
   }
 
@@ -515,7 +517,7 @@ public:
   virtual ~Emitter()
   {
     barrier_->unregister_emitter(identifier_);
-    manager_->release_syncbarrier(identifier_, barrier_);
+    manager_->release_syncpoint(identifier_, barrier_);
   }
 
   /** emit the SyncBarrier */
@@ -526,7 +528,7 @@ public:
 
 private:
   string identifier_;
-  RefPtr<SyncBarrier> barrier_;
+  RefPtr<SyncPoint> barrier_;
   RefPtr<SyncPointManager> manager_;
 };
 
@@ -535,8 +537,7 @@ private:
 TEST_F(SyncBarrierTest,WaitWithNoRegisteredEmitter)
 {
   string barrier_id = "/test/barrier";
-  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier("main loop", barrier_id);
-  barrier->reset_emitters();
+  RefPtr<SyncPoint> barrier = manager->get_syncpoint("main loop", barrier_id);
   const uint num_waiter_threads = 1;
   const uint num_wait_calls = 1;
   pthread_t waiter_threads[num_waiter_threads];
@@ -572,8 +573,7 @@ TEST_F(SyncBarrierTest, WaitForAllEmitters)
   Emitter em1("emitter 1", barrier_id, manager);
   Emitter em2("emitter 2", barrier_id, manager);
 
-  RefPtr<SyncBarrier> barrier = manager->get_syncbarrier("main loop", barrier_id);
-  barrier->reset_emitters();
+  RefPtr<SyncPoint> barrier = manager->get_syncpoint("main loop", barrier_id);
 
   const uint num_waiter_threads = 50;
   const uint num_wait_calls = 1;
@@ -628,13 +628,11 @@ TEST_F(SyncBarrierTest, BarriersAreIndependent)
   Emitter em1("em1", barrier1_id, manager);
   Emitter em2("em2", barrier2_id, manager);
 
-  RefPtr<SyncBarrier> barrier1 = manager->get_syncbarrier("m1",
+  RefPtr<SyncPoint> barrier1 = manager->get_syncpoint("m1",
     barrier1_id);
-  barrier1->reset_emitters();
 
-  RefPtr<SyncBarrier> barrier2 = manager->get_syncbarrier("m2",
+  RefPtr<SyncPoint> barrier2 = manager->get_syncpoint("m2",
     barrier2_id);
-  barrier2->reset_emitters();
 
   const uint num_waiter_threads = 50;
   const uint num_wait_calls = 1;

- *commit* 52878ce9e059f6f544febde918b7b2c493498575 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 27 20:14:49 2015 +0100
Subject: syncpoint: do not throw an exception if SyncPoint is already opened

 src/libs/syncpoint/syncpoint_manager.cpp    |    6 +-----
 src/libs/syncpoint/tests/test_syncpoint.cpp |    2 --
 2 files changed, 1 insertions(+), 7 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 526b074..39696f2 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -218,11 +218,7 @@ SyncPointManager::get_syncpoint_no_lock(const std::string & component, const std
   std::set<RefPtr<SyncPoint> >::iterator sp_it = insert_ret.first;
 
   // add component to the set of watchers
-  // check if component is already a watcher
-  // insert returns a pair whose second element is false if element already exists
-  if (!(*sp_it)->add_watcher(component).second) {
-    throw SyncPointAlreadyOpenedException(component.c_str(), identifier.c_str());
-  }
+  (*sp_it)->add_watcher(component);
 
   if (identifier != "/") {
     // create prefix SyncPoints.
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 8449ec1..c3c05f1 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -188,8 +188,6 @@ TEST_F(SyncPointManagerTest, WatcherSet)
   ASSERT_NO_THROW(manager->get_syncpoint("component 1", "/test"));
   ASSERT_NO_THROW(manager->get_syncpoint("component 2", "/test"));
   ASSERT_NO_THROW(manager->get_syncpoint("component 3", "/test"));
-  ASSERT_THROW(manager->get_syncpoint("component 1", "/test"), SyncPointAlreadyOpenedException);
-
 }
 
 /** Test what happens if we acquire a SyncPoint, release it, and then acquire it

- *commit* ca44a7c2f46539939aaeb9d84c0be65bb162bb9c - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Feb 27 20:20:15 2015 +0100
Subject: core: properly lock loop_listeners before access

 src/libs/core/threading/thread.cpp |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/core/threading/thread.cpp b/src/libs/core/threading/thread.cpp
index 36ca109..648ace8 100644
--- a/src/libs/core/threading/thread.cpp
+++ b/src/libs/core/threading/thread.cpp
@@ -959,19 +959,23 @@ Thread::run()
     if ( ! finalize_prepared ) {
       __loop_done = false;
 
+      __loop_listeners->lock();
       for (LockList<ThreadLoopListener *>::iterator it = __loop_listeners->begin();
           it != __loop_listeners->end();
           it++) {
         (*it)->pre_loop(this);
       }
+      __loop_listeners->unlock();
 
       loop();
 
+      __loop_listeners->lock();
       for (LockList<ThreadLoopListener *>::reverse_iterator it = __loop_listeners->rbegin();
           it != __loop_listeners->rend();
           it++) {
         (*it)->post_loop(this);
       }
+      __loop_listeners->unlock();
     }
     loop_mutex->unlock();
 

- *commit* 231d81d17b6909f3c9d72c75377a6a556b6a3070 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Mar 4 17:02:55 2015 +0100
Subject: aspects: make the BlockedTimingAspect a SyncPointAspect

 src/libs/Makefile                          |    2 +-
 src/libs/aspect/blocked_timing.cpp         |   49 +++++++++++++++++++++++++
 src/libs/aspect/blocked_timing.h           |   10 +++++-
 src/libs/aspect/inifins/blocked_timing.cpp |    5 ---
 src/libs/aspect/syncpoint.cpp              |    4 +-
 src/libs/baseapp/main_thread.cpp           |   53 ++++++++++++++++++++++-----
 src/libs/baseapp/main_thread.h             |    8 ++++
 src/libs/baseapp/run.cpp                   |    1 +
 8 files changed, 113 insertions(+), 19 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/Makefile b/src/libs/Makefile
index 6a50896..a6d8498 100644
--- a/src/libs/Makefile
+++ b/src/libs/Makefile
@@ -46,7 +46,7 @@ navgraph: core utils aspect
 interfaces: core interface
 config: core netcomm utils logging
 plugin: core netcomm utils config logging
-aspect: core utils blackboard netcomm config plugin webview logging tf pcl_utils
+aspect: core utils blackboard netcomm config plugin webview logging tf pcl_utils syncpoint
 lua: core utils blackboard config logging
 interfaces: core interface
 gui_utils: core netcomm blackboard interface plugin logging
diff --git a/src/libs/aspect/blocked_timing.cpp b/src/libs/aspect/blocked_timing.cpp
index 103ce8f..7bb58c5 100644
--- a/src/libs/aspect/blocked_timing.cpp
+++ b/src/libs/aspect/blocked_timing.cpp
@@ -52,6 +52,9 @@ namespace fawkes {
  * @param wakeup_hook hook when this thread should be woken up
  */
 BlockedTimingAspect::BlockedTimingAspect(WakeupHook wakeup_hook)
+    : SyncPointAspect(SyncPoint::WAIT_FOR_ALL,
+        blocked_timing_hook_to_start_syncpoint(wakeup_hook),
+        blocked_timing_hook_to_end_syncpoint(wakeup_hook))
 {
   add_aspect("BlockedTimingAspect");
   __wakeup_hook = wakeup_hook;
@@ -98,4 +101,50 @@ BlockedTimingAspect::blocked_timing_hook_to_string(WakeupHook hook)
   }
 }
 
+/** Get the syncpoint identifier corresponding to the end of a wakeup hook.
+ * This is the syncpoint emitted at the end of a hook.
+ * @param hook wakeup hook to get the syncpoint identifier for
+ * @return the identifier of the corresponding syncpoint
+ */
+std::string
+BlockedTimingAspect::blocked_timing_hook_to_end_syncpoint(WakeupHook hook)
+{
+  switch (hook) {
+    case WAKEUP_HOOK_PRE_LOOP:       return "/preloop/end";
+    case WAKEUP_HOOK_SENSOR_ACQUIRE: return "/sensors/acquire/end";
+    case WAKEUP_HOOK_SENSOR_PREPARE: return "/sensors/prepare/end";
+    case WAKEUP_HOOK_SENSOR_PROCESS: return "/sensors/process/end";
+    case WAKEUP_HOOK_WORLDSTATE:     return "/worldstate/end";
+    case WAKEUP_HOOK_THINK:          return "/agent/end";
+    case WAKEUP_HOOK_SKILL:          return "/skill/end";
+    case WAKEUP_HOOK_ACT:            return "/act/main/end";
+    case WAKEUP_HOOK_ACT_EXEC:       return "/act/exec/end";
+    case WAKEUP_HOOK_POST_LOOP:      return "/postloop/end";
+    default: throw Exception("Unknown blocked timing wakeup hook");
+  }
+}
+
+/** Get the syncpoint identifier corresponding to the start of a wakeup hook.
+ * This is the syncpoint waited for at the start of a hook.
+ * @param hook wakeup hook to get the syncpoint identifier for
+ * @return the identifier of the corresponding syncpoint
+ */
+std::string
+BlockedTimingAspect::blocked_timing_hook_to_start_syncpoint(WakeupHook hook)
+{
+  switch (hook) {
+    case WAKEUP_HOOK_PRE_LOOP:       return "/preloop/start";
+    case WAKEUP_HOOK_SENSOR_ACQUIRE: return "/sensors/acquire/start";
+    case WAKEUP_HOOK_SENSOR_PREPARE: return "/sensors/prepare/start";
+    case WAKEUP_HOOK_SENSOR_PROCESS: return "/sensors/process/start";
+    case WAKEUP_HOOK_WORLDSTATE:     return "/worldstate/start";
+    case WAKEUP_HOOK_THINK:          return "/agent/start";
+    case WAKEUP_HOOK_SKILL:          return "/skill/start";
+    case WAKEUP_HOOK_ACT:            return "/act/main/start";
+    case WAKEUP_HOOK_ACT_EXEC:       return "/act/exec/start";
+    case WAKEUP_HOOK_POST_LOOP:      return "/postloop/start";
+    default: throw Exception("Unknown blocked timing wakeup hook");
+  }
+}
+
 } // end namespace fawkes
diff --git a/src/libs/aspect/blocked_timing.h b/src/libs/aspect/blocked_timing.h
index 58c22d6..4a095ac 100644
--- a/src/libs/aspect/blocked_timing.h
+++ b/src/libs/aspect/blocked_timing.h
@@ -26,12 +26,17 @@
 
 #include <aspect/aspect.h>
 
+#include <aspect/syncpoint.h>
+
+#include <map>
+#include <string>
+
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
 }
 #endif
 
-class BlockedTimingAspect : public virtual Aspect
+class BlockedTimingAspect : public SyncPointAspect
 {
  public:
   /** Type to define at which hook the thread is woken up.
@@ -59,6 +64,9 @@ class BlockedTimingAspect : public virtual Aspect
 
   static const char *  blocked_timing_hook_to_string(WakeupHook hook);
 
+  static std::string blocked_timing_hook_to_start_syncpoint(WakeupHook hook);
+  static std::string blocked_timing_hook_to_end_syncpoint(WakeupHook hook);
+
   WakeupHook blockedTimingAspectHook() const;
 
  private:
diff --git a/src/libs/aspect/inifins/blocked_timing.cpp b/src/libs/aspect/inifins/blocked_timing.cpp
index dc69af8..5551b81 100644
--- a/src/libs/aspect/inifins/blocked_timing.cpp
+++ b/src/libs/aspect/inifins/blocked_timing.cpp
@@ -54,11 +54,6 @@ BlockedTimingAspectIniFin::init(Thread *thread)
 					  "has not. ", thread->name());
   }
 
-  if ( thread->opmode() != Thread::OPMODE_WAITFORWAKEUP ) {
-    throw CannotInitializeThreadException("Thread '%s' not in WAITFORWAKEUP mode"
-					  " (required for BlockedTimingAspect)",
-					  thread->name());
-  }
 }
 
 void
diff --git a/src/libs/aspect/syncpoint.cpp b/src/libs/aspect/syncpoint.cpp
index ece5810..53f7995 100644
--- a/src/libs/aspect/syncpoint.cpp
+++ b/src/libs/aspect/syncpoint.cpp
@@ -50,7 +50,7 @@ SyncPointAspect::SyncPointAspect(SyncPoint::WakeupType type_in, std::string iden
     identifier_out_(identifier_out), sp_in_(NULL), sp_out_(NULL)
 {
   add_aspect("SyncPointAspect");
-  has_input_syncpoint_ = true;
+  has_input_syncpoint_ = (identifier_in != "");
   has_output_syncpoint_ = (identifier_out != "");
 }
 
@@ -60,7 +60,7 @@ SyncPointAspect::SyncPointAspect(SyncPoint::WakeupType type_in, std::string iden
  * @param identifier_out identifier of the output syncpoint
  */
 SyncPointAspect::SyncPointAspect(std::string identifier_out)
-  : type_in_(SyncPoint::WakeupType::NONE), identifier_in_(""),
+  : type_in_(SyncPoint::NONE), identifier_in_(""),
     identifier_out_(identifier_out), sp_in_(NULL), sp_out_(NULL)
 {
   add_aspect("SyncPointAspect");
diff --git a/src/libs/baseapp/main_thread.cpp b/src/libs/baseapp/main_thread.cpp
index 6cbef6a..ae0875f 100644
--- a/src/libs/baseapp/main_thread.cpp
+++ b/src/libs/baseapp/main_thread.cpp
@@ -65,6 +65,7 @@ namespace fawkes {
  * @param multi_logger basic multi logger to use, a network logger will be
  * added in the ctor.
  * @param thread_manager thread manager used to wakeup threads
+ * @param syncpoint_manager syncpoint manager used to manage syncpoints
  * @param plugin_manager plugin manager to load the desired plugins
  * @param load_plugins string with comma-separated list of names of plugins
  * to load on startup.
@@ -73,6 +74,7 @@ namespace fawkes {
 FawkesMainThread::FawkesMainThread(Configuration *config,
 				   MultiLogger *multi_logger,
 				   ThreadManager *thread_manager,
+				   SyncPointManager *syncpoint_manager,
 				   PluginManager *plugin_manager,
 				   const char *load_plugins,
                                    const char *default_plugin)
@@ -80,6 +82,7 @@ FawkesMainThread::FawkesMainThread(Configuration *config,
 {
   __plugin_manager    = plugin_manager;
   __thread_manager    = thread_manager;
+  __syncpoint_manager = syncpoint_manager;
   __multi_logger      = multi_logger;
   __config            = config;
 
@@ -208,6 +211,36 @@ FawkesMainThread::full_start()
 void
 FawkesMainThread::once()
 {
+  // register to all syncpoints of the main loop
+  std::vector<BlockedTimingAspect::WakeupHook> hooks;
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_PRE_LOOP);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_ACQUIRE);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_PREPARE);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_PROCESS);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_WORLDSTATE);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_THINK);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_SKILL);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_ACT);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_ACT_EXEC);
+  hooks.push_back(BlockedTimingAspect::WAKEUP_HOOK_POST_LOOP);
+
+  try {
+    for (std::vector<BlockedTimingAspect::WakeupHook>::const_iterator it =
+        hooks.begin(); it != hooks.end(); it++) {
+      __syncpoints_start_hook.push_back(
+        __syncpoint_manager->get_syncpoint("FawkesMainThread",
+          BlockedTimingAspect::blocked_timing_hook_to_start_syncpoint(*it)));
+      __syncpoints_start_hook.back()->register_emitter("FawkesMainThread");
+      __syncpoints_end_hook.push_back(
+        __syncpoint_manager->get_syncpoint("FawkesMainThread",
+          BlockedTimingAspect::blocked_timing_hook_to_end_syncpoint(*it)));
+    }
+  } catch (Exception &e) {
+    __multi_logger->log_error("FawkesMainThread",
+      "Failed to acquire mainloop syncpoint");
+    throw;
+  }
+
   // if plugins passed on command line or in init options, load!
   if ( __load_plugins) {
     try {
@@ -306,16 +339,16 @@ FawkesMainThread::loop()
 	__multi_logger->log_warn("FawkesMainThread", e);
       }
     } else {
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_PRE_LOOP,       __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_ACQUIRE, __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_PREPARE, __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SENSOR_PROCESS, __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_WORLDSTATE,     __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_THINK,          __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_SKILL,          __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_ACT,            __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_ACT_EXEC,       __max_thread_time_usec);
-      safe_wake(BlockedTimingAspect::WAKEUP_HOOK_POST_LOOP,      __max_thread_time_usec);
+      uint num_hooks = __syncpoints_start_hook.size();
+      if (__syncpoints_end_hook.size() != num_hooks) {
+        __multi_logger->log_error("FawkesMainThread",
+          "Hook syncpoints are not initialized properly, not waking up any threads!");
+      } else {
+        for (uint i = 0; i < num_hooks; i++) {
+          __syncpoints_start_hook[i]->emit("FawkesMainThread");
+          __syncpoints_end_hook[i]->wait_for_all("FawkesMainThread");
+        }
+      }
     }
     __mainloop_mutex->unlock();
     set_cancel_state(old_state);
diff --git a/src/libs/baseapp/main_thread.h b/src/libs/baseapp/main_thread.h
index d4d6eaf..c0d6543 100644
--- a/src/libs/baseapp/main_thread.h
+++ b/src/libs/baseapp/main_thread.h
@@ -24,6 +24,7 @@
 #ifndef __LIBS_BASEAPP_MAIN_THREAD_H_
 #define __LIBS_BASEAPP_MAIN_THREAD_H_
 
+#include <syncpoint/syncpoint_manager.h>
 #include <baseapp/thread_manager.h>
 #include <core/threading/thread.h>
 #include <aspect/mainloop/employer.h>
@@ -33,6 +34,7 @@
 
 #include <list>
 #include <string>
+#include <vector>
 #include <getopt.h>
 
 namespace fawkes {
@@ -53,6 +55,7 @@ class InterruptibleBarrier;
 class Barrier;
 class Mutex;
 class ThreadManager;
+class SyncPointManager;
 class FawkesNetworkManager;
 
 class FawkesMainThread
@@ -63,6 +66,7 @@ class FawkesMainThread
   FawkesMainThread(Configuration *config,
 		   MultiLogger *multi_logger,
 		   ThreadManager *thread_manager,
+		   SyncPointManager *syncpoint_manager,
 		   PluginManager *plugin_manager,
 		   const char *load_plugins,
                    const char *default_plugin = 0);
@@ -128,6 +132,7 @@ class FawkesMainThread
   char                 *__load_plugins;
 
   ThreadManager        *__thread_manager;
+  SyncPointManager     *__syncpoint_manager;
   PluginManager        *__plugin_manager;
 
   std::list<std::string>        __recovered_threads;
@@ -139,6 +144,9 @@ class FawkesMainThread
   Time                         *__loop_end;
   bool                          __enable_looptime_warnings;
 
+  std::vector<RefPtr<SyncPoint> > __syncpoints_start_hook;
+  std::vector<RefPtr<SyncPoint> > __syncpoints_end_hook;
+
 };
 
 } // end namespace fawkes
diff --git a/src/libs/baseapp/run.cpp b/src/libs/baseapp/run.cpp
index a715d1e..2293eac 100644
--- a/src/libs/baseapp/run.cpp
+++ b/src/libs/baseapp/run.cpp
@@ -385,6 +385,7 @@ init(InitOptions options, int & retval)
   // *** Create main thread, but do not start, yet
   main_thread = new fawkes::FawkesMainThread(config, logger,
 					     thread_manager,
+					     syncpoint_manager,
 					     plugin_manager,
 					     options.load_plugin_list(),
                                              options.default_plugin());

- *commit* a6e660a15e7d31cb69e8cab458e64b882e0753b1 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Thu Mar 5 15:50:22 2015 +0100
Subject: syncpoint: add syncpoint test plugin

 src/plugins/Makefile                               |    2 +-
 .../ffinfo => plugins/syncpoint-test}/Makefile     |   25 ++++---
 src/plugins/syncpoint-test/test_plugin.cpp         |   70 ++++++++++++++++++++
 .../test_thread.cpp}                               |   44 ++++++-------
 .../test_thread.h}                                 |   25 ++++----
 5 files changed, 119 insertions(+), 47 deletions(-)

_Diff for modified files_:
diff --git a/src/plugins/Makefile b/src/plugins/Makefile
index caee20b..032b643 100644
--- a/src/plugins/Makefile
+++ b/src/plugins/Makefile
@@ -28,7 +28,7 @@ SUBDIRS	= bbsync bblogger webview ttmainloop rrd rrdweb \
 	  clips-tf openprs openprs-agent eclipse-clp \
 	  mongodb mongodb_log \
 	  openni refboxcomm ros player xmlrpc gossip \
-	  robot_state_publisher gazebo dynamixel navgraph-interactive
+	  robot_state_publisher gazebo dynamixel navgraph-interactive syncpoint-test
 
 include $(BUILDSYSDIR)/rules.mk
 

- *commit* 4c27def80e1cb4ef9e8886dbed0174aca621a01c - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Mar 6 19:15:16 2015 +0100
Subject: syncpoint: do not throw on multiple register calls

 src/libs/syncpoint/exceptions.h             |   18 ------------------
 src/libs/syncpoint/syncpoint.cpp            |    5 +----
 src/libs/syncpoint/tests/test_syncpoint.cpp |    2 +-
 3 files changed, 2 insertions(+), 23 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/exceptions.h b/src/libs/syncpoint/exceptions.h
index c3d7da0..7fbe10d 100644
--- a/src/libs/syncpoint/exceptions.h
+++ b/src/libs/syncpoint/exceptions.h
@@ -172,24 +172,6 @@ class SyncPointMultipleWaitCallsException : public Exception
     }
 };
 
-/** A component tried to register as emitter but is already registered
- *
- */
-class SyncPointMultipleRegisterCallsException : public Exception
-{
-public:
-  /** Constructor.
-   * @param component The calling component
-   * @param identifier The identifier of the SyncBarrier
-   */
-	SyncPointMultipleRegisterCallsException(const char * component,
-    const char * identifier)
-  {
-    append("Component '%s' called register_emitter() on SyncBarrier '%s', but is already registered",
-        component, identifier);
-  }
-};
-
 /** Emit was called on a SyncBarrier but the calling component is not registered
  *  as emitter
  */
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 14e7f4e..57efeab 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -246,10 +246,7 @@ void
 SyncPoint::register_emitter(const string & component)
 {
   MutexLocker ml(mutex_);
-  if (!emitters_.insert(component).second) {
-    throw SyncPointMultipleRegisterCallsException(component.c_str(),
-      get_identifier().c_str());
-  }
+  emitters_.insert(component);
   pending_emitters_.insert(component);
   if (predecessor_) {
     predecessor_->register_emitter(component);
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index c3c05f1..58e6e6c 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -461,7 +461,7 @@ TEST_F(SyncBarrierTest, MultipleRegisterCalls)
   string component = "emitter";
   RefPtr<SyncPoint> barrier = manager->get_syncpoint(component, "/test/barrier");
   EXPECT_NO_THROW(barrier->register_emitter(component));
-  ASSERT_THROW(barrier->register_emitter(component), SyncPointMultipleRegisterCallsException);
+  EXPECT_NO_THROW(barrier->register_emitter(component));
 }
 
 /** get a SyncBarrier and wait for it */

- *commit* da417c46f10118cf7acf0fca929a639ba4efcb63 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Mar 18 12:44:46 2015 +0100
Subject: aspects: require continuous mode in blocked timing aspect

 src/libs/aspect/inifins/blocked_timing.cpp |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/aspect/inifins/blocked_timing.cpp b/src/libs/aspect/inifins/blocked_timing.cpp
index 5551b81..0b7f5e9 100644
--- a/src/libs/aspect/inifins/blocked_timing.cpp
+++ b/src/libs/aspect/inifins/blocked_timing.cpp
@@ -54,6 +54,12 @@ BlockedTimingAspectIniFin::init(Thread *thread)
 					  "has not. ", thread->name());
   }
 
+  if ( thread->opmode() != Thread::OPMODE_CONTINUOUS) {
+    throw CannotInitializeThreadException("Thread '%s' not in CONTINUOUS mode"
+                                          " (required for BlockedTimingAspect)",
+                                          thread->name());
+    )
+
 }
 
 void

- *commit* d5d546f8b2d67c2688490e20cbc4aa2a86bad7a3 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Mar 18 12:50:04 2015 +0100
Subject: syncpoint: add equal operator for std::strings

 src/libs/syncpoint/syncpoint.cpp |   12 ++++++++++++
 src/libs/syncpoint/syncpoint.h   |    2 ++
 2 files changed, 14 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 57efeab..3978765 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -112,6 +112,18 @@ SyncPoint::operator==(const SyncPoint &other) const
   return identifier_ == other.get_identifier();
 }
 
+/** EqualOperator.
+ * A SyncPoint is equal to a given string iff the string is equal to the
+ * SyncPoint's identifier.
+ * @param other the string to compare
+ * @return true if the identifier of the SyncPoint matches the given string
+ */
+bool
+SyncPoint::operator==(const string & other) const
+{
+  return identifier_ == other;
+}
+
 /** LessThan Operator.
  * Compare two SyncPoints using their identifiers.
  * @param other The other SyncPoint
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 4a4955f..5c1bc47 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -33,6 +33,7 @@
 
 #include <set>
 #include <map>
+#include <string>
 
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
@@ -74,6 +75,7 @@ class SyncPoint
 
     std::string get_identifier() const;
     bool operator==(const SyncPoint & other) const;
+    bool operator==(const std::string & other) const;
     bool operator<(const SyncPoint & other) const;
 
     std::set<std::string> get_watchers() const;

- *commit* fcf2e6e6b71683289689689aa5fc043b8cef22da - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Mar 18 12:53:35 2015 +0100
Subject: syncpoint: fix calculation of call frequency

 src/libs/syncpoint/syncpoint_call_stats.cpp |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint_call_stats.cpp b/src/libs/syncpoint/syncpoint_call_stats.cpp
index 33d76b7..ebf2040 100644
--- a/src/libs/syncpoint/syncpoint_call_stats.cpp
+++ b/src/libs/syncpoint/syncpoint_call_stats.cpp
@@ -95,7 +95,7 @@ SyncPointCallStats::get_last_call() const
 float
 SyncPointCallStats::get_call_frequency() const
 {
-  return (last_call_.in_sec() - first_call_.in_sec()) / num_calls_;
+  return num_calls_ / (last_call_.in_sec() - first_call_.in_sec());
 }
 
 /** Get the average wait time. For emit calls, this is 0.

- *commit* a17fd5fbe197492267b5ae91d3b634c7001eaedd - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Mar 18 14:17:14 2015 +0100
Subject: syncpoint: adapt visualization to the two types of wait calls

 src/libs/syncpoint/syncpoint_manager.cpp |   45 ++++++++++++++++++++++++-----
 1 files changed, 37 insertions(+), 8 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 39696f2..b06642e 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -137,6 +137,12 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
   MutexLocker ml(mutex_);
   for (std::set<RefPtr<SyncPoint>, SyncPointSetLessThan>::const_iterator sp_it = syncpoints_.begin();
       sp_it != syncpoints_.end(); sp_it++) {
+    graph << "\"" << (*sp_it)->get_identifier() << "\""
+        << " [shape=box];";
+  }
+
+  for (std::set<RefPtr<SyncPoint>, SyncPointSetLessThan>::const_iterator sp_it = syncpoints_.begin();
+      sp_it != syncpoints_.end(); sp_it++) {
     Time lifetime = Time() - (*sp_it)->creation_time_;
     graph << "\"" << (*sp_it)->get_identifier() << "\";";
 
@@ -162,17 +168,17 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
       }
     }
 
-    // WAIT CALLS
-    CircularBuffer<SyncPointCall> wait_calls = (*sp_it)->get_wait_calls();
+    // WAIT FOR ONE CALLS
+    CircularBuffer<SyncPointCall> wait_one_calls = (*sp_it)->get_wait_calls(SyncPoint::WAIT_FOR_ONE);
     // generate call stats
-    std::map<std::string, SyncPointCallStats> wait_call_stats;
-    for (CircularBuffer<SyncPointCall>::iterator waitcalls_it = wait_calls.begin();
-        waitcalls_it != wait_calls.end(); waitcalls_it++) {
-      wait_call_stats[waitcalls_it->get_caller()].update_calls(*waitcalls_it);
+    std::map<std::string, SyncPointCallStats> wait_one_call_stats;
+    for (CircularBuffer<SyncPointCall>::iterator waitcalls_it = wait_one_calls.begin();
+        waitcalls_it != wait_one_calls.end(); waitcalls_it++) {
+      wait_one_call_stats[waitcalls_it->get_caller()].update_calls(*waitcalls_it);
     }
 
-    for (std::map<std::string, SyncPointCallStats>::iterator wait_call_stats_it = wait_call_stats.begin();
-        wait_call_stats_it != wait_call_stats.end(); wait_call_stats_it++) {
+    for (std::map<std::string, SyncPointCallStats>::iterator wait_call_stats_it = wait_one_call_stats.begin();
+        wait_call_stats_it != wait_one_call_stats.end(); wait_call_stats_it++) {
       float age = (Time() - wait_call_stats_it->second.get_last_call()).in_sec();
       if (age < max_age) {
       graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> "
@@ -183,6 +189,29 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
           << "\"" << "];";
       }
     }
+
+    // WAIT FOR ALL CALLS
+    CircularBuffer<SyncPointCall> wait_all_calls = (*sp_it)->get_wait_calls(SyncPoint::WAIT_FOR_ALL);
+    // generate call stats
+    std::map<std::string, SyncPointCallStats> wait_all_call_stats;
+    for (CircularBuffer<SyncPointCall>::iterator waitcalls_it = wait_all_calls.begin();
+        waitcalls_it != wait_all_calls.end(); waitcalls_it++) {
+      wait_all_call_stats[waitcalls_it->get_caller()].update_calls(*waitcalls_it);
+    }
+
+    for (std::map<std::string, SyncPointCallStats>::iterator wait_call_stats_it = wait_all_call_stats.begin();
+        wait_call_stats_it != wait_all_call_stats.end(); wait_call_stats_it++) {
+      float age = (Time() - wait_call_stats_it->second.get_last_call()).in_sec();
+      if (age < max_age) {
+      graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> "
+          << "\"" << wait_call_stats_it->first << "\"" << " [label=" << "\""
+          << " avg=" << wait_call_stats_it->second.get_waittime_average() <<  "s"
+          << " age=" << age << "s"
+          //<< " max=" << max_wait_time << "s"
+          << "\"" << "];";
+      }
+    }
+
   }
   graph << "}";
   return graph.str();

- *commit* 92cce9b6a954673987eecb99fd2cdf94ddc4bada - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Tue Mar 24 21:47:08 2015 +0100
Subject: aspects: BlockedTimingAspect with wait-for-wakeup and syncpoints

 src/libs/aspect/blocked_timing.cpp         |   36 ++++++++++++++++++++++++++++
 src/libs/aspect/blocked_timing.h           |   21 +++++++++++++++-
 src/libs/aspect/inifins/blocked_timing.cpp |   19 +++++++++++---
 3 files changed, 71 insertions(+), 5 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/aspect/blocked_timing.cpp b/src/libs/aspect/blocked_timing.cpp
index 7bb58c5..4a2dd2a 100644
--- a/src/libs/aspect/blocked_timing.cpp
+++ b/src/libs/aspect/blocked_timing.cpp
@@ -25,6 +25,7 @@
 #include <core/threading/thread.h>
 #include <core/exception.h>
 
+
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
 }
@@ -58,15 +59,39 @@ BlockedTimingAspect::BlockedTimingAspect(WakeupHook wakeup_hook)
 {
   add_aspect("BlockedTimingAspect");
   __wakeup_hook = wakeup_hook;
+  __loop_listener = new BlockedTimingLoopListener();
 }
 
 
 /** Virtual empty destructor. */
 BlockedTimingAspect::~BlockedTimingAspect()
 {
+  delete __loop_listener;
+}
+
+
+/** Init BlockedTiming aspect.
+ * This intializes the aspect and adds the loop listener to the thread.
+ * @param thread thread which uses this aspect
+ */
+void
+BlockedTimingAspect::init_BlockedTimingAspect(Thread *thread)
+{
+  thread->add_loop_listener(__loop_listener);
+  thread->wakeup();
 }
 
 
+/** Finalize BlockedTiming aspect.
+ * This finalizes the aspect and removes the loop listener from the thread.
+ * @param thread thread which uses this aspect
+ */
+void
+BlockedTimingAspect::finalize_BlockedTimingAspect(Thread *thread)
+{
+  thread->remove_loop_listener(__loop_listener);
+}
+
 /** Get the wakeup hook.
  * The wakeup hook defines when this thread should be woken up. This heavily
  * depends on the used main thread.
@@ -147,4 +172,15 @@ BlockedTimingAspect::blocked_timing_hook_to_start_syncpoint(WakeupHook hook)
   }
 }
 
+
+/** The post loop function of the BlockedTimingAspect
+ * This function is called right after the loop of the thread with the aspect.
+ * @param thread thread this loop listener belongs to
+ */
+void
+BlockedTimingLoopListener::post_loop(Thread *thread)
+{
+  thread->wakeup();
+}
+
 } // end namespace fawkes
diff --git a/src/libs/aspect/blocked_timing.h b/src/libs/aspect/blocked_timing.h
index 4a095ac..5a11f81 100644
--- a/src/libs/aspect/blocked_timing.h
+++ b/src/libs/aspect/blocked_timing.h
@@ -25,8 +25,8 @@
 #define __ASPECT_BLOCKED_TIMING_H_
 
 #include <aspect/aspect.h>
-
 #include <aspect/syncpoint.h>
+#include <core/threading/thread_loop_listener.h>
 
 #include <map>
 #include <string>
@@ -36,6 +36,21 @@ namespace fawkes {
 }
 #endif
 
+
+/** @class BlockedTimingLoopListener
+ * Loop Listener of the BlockedTimingAspect.
+ * This loop listener immediately wakes up the thread after loop returned.
+ * The thread will then wait for the syncpoint of the next iteration.
+ * The BlockedTimingAspect cannot be derived from ThreadLoopListener because
+ * the SyncPointAspect is already derived from ThreadLoopListener and we need
+ * another listener. Therefore, use composition instead.
+ */
+class BlockedTimingLoopListener : public ThreadLoopListener
+{
+ public:
+  void post_loop(Thread *thread);
+};
+
 class BlockedTimingAspect : public SyncPointAspect
 {
  public:
@@ -67,10 +82,14 @@ class BlockedTimingAspect : public SyncPointAspect
   static std::string blocked_timing_hook_to_start_syncpoint(WakeupHook hook);
   static std::string blocked_timing_hook_to_end_syncpoint(WakeupHook hook);
 
+  void init_BlockedTimingAspect(Thread *thread);
+  void finalize_BlockedTimingAspect(Thread *thread);
+
   WakeupHook blockedTimingAspectHook() const;
 
  private:
   WakeupHook __wakeup_hook;
+  BlockedTimingLoopListener *__loop_listener;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/aspect/inifins/blocked_timing.cpp b/src/libs/aspect/inifins/blocked_timing.cpp
index 0b7f5e9..1a39fd9 100644
--- a/src/libs/aspect/inifins/blocked_timing.cpp
+++ b/src/libs/aspect/inifins/blocked_timing.cpp
@@ -45,7 +45,7 @@ BlockedTimingAspectIniFin::BlockedTimingAspectIniFin()
 void
 BlockedTimingAspectIniFin::init(Thread *thread)
 {
-  BlockedTimingAspect *blocked_timing_thread __unused;
+  BlockedTimingAspect *blocked_timing_thread;
   blocked_timing_thread = dynamic_cast<BlockedTimingAspect *>(thread);
 
   if (blocked_timing_thread == 0) {
@@ -54,17 +54,28 @@ BlockedTimingAspectIniFin::init(Thread *thread)
 					  "has not. ", thread->name());
   }
 
-  if ( thread->opmode() != Thread::OPMODE_CONTINUOUS) {
-    throw CannotInitializeThreadException("Thread '%s' not in CONTINUOUS mode"
+  if ( thread->opmode() != Thread::OPMODE_WAITFORWAKEUP) {
+    throw CannotInitializeThreadException("Thread '%s' not in WAITFORWAKEUP mode"
                                           " (required for BlockedTimingAspect)",
                                           thread->name());
-    )
+  }
 
+  blocked_timing_thread->init_BlockedTimingAspect(thread);
 }
 
 void
 BlockedTimingAspectIniFin::finalize(Thread *thread)
 {
+  BlockedTimingAspect *blocked_timing_thread;
+    blocked_timing_thread = dynamic_cast<BlockedTimingAspect *>(thread);
+
+  if (blocked_timing_thread == 0) {
+    throw CannotInitializeThreadException("Thread '%s' claims to have the "
+      "BlockedTimingAspect, but RTTI says it "
+      "has not. ", thread->name());
+  }
+
+  blocked_timing_thread->finalize_BlockedTimingAspect(thread);
 }
 
 

- *commit* 2376ae52c96155c82e6baa14b80a257f27131959 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Tue Mar 24 21:55:24 2015 +0100
Subject: core: provide stubs for the ThreadLoopListener hooks

 src/libs/core/threading/thread_loop_listener.cpp |   20 ++++++++++++++++++++
 src/libs/core/threading/thread_loop_listener.h   |    4 ++--
 2 files changed, 22 insertions(+), 2 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/core/threading/thread_loop_listener.cpp b/src/libs/core/threading/thread_loop_listener.cpp
index b22d0e5..6be93e2 100644
--- a/src/libs/core/threading/thread_loop_listener.cpp
+++ b/src/libs/core/threading/thread_loop_listener.cpp
@@ -46,5 +46,25 @@ ThreadLoopListener::~ThreadLoopListener()
 {
 }
 
+/** Empty stub for the pre loop function of the loop listener.
+ * This function is called right before the loop of the thread with the aspect.
+ * Provide a stub such that not every derived class must implement the function.
+ * @param thread thread this loop listener belongs to
+ */
+void
+ThreadLoopListener::pre_loop(Thread *thread)
+{
+}
+
+/** Empty stub for the post loop function of the loop listener.
+ * This function is called right after the loop of the thread with the aspect.
+ * Provide a stub such that not every derived class must implement the function.
+ * @param thread thread this loop listener belongs to
+ */
+void
+ThreadLoopListener::post_loop(Thread *thread)
+{
+}
+
 
 } // end namespace fawkes
diff --git a/src/libs/core/threading/thread_loop_listener.h b/src/libs/core/threading/thread_loop_listener.h
index 79a0ac0..f145bb7 100644
--- a/src/libs/core/threading/thread_loop_listener.h
+++ b/src/libs/core/threading/thread_loop_listener.h
@@ -34,8 +34,8 @@ class ThreadLoopListener
  public:
   virtual ~ThreadLoopListener();
 
-  virtual void pre_loop(Thread *thread)     = 0;
-  virtual void post_loop(Thread *thread)    = 0;
+  virtual void pre_loop(Thread *thread);
+  virtual void post_loop(Thread *thread);
 };
 
 

- *commit* 02c0acce00d0e93f58ae9f9e9e5a64eda3172dc5 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Mar 25 10:28:23 2015 +0100
Subject: core: do not protect pre and post loop hooks with loop mutex

 src/libs/core/threading/thread.cpp |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/core/threading/thread.cpp b/src/libs/core/threading/thread.cpp
index 648ace8..8ec142b 100644
--- a/src/libs/core/threading/thread.cpp
+++ b/src/libs/core/threading/thread.cpp
@@ -955,7 +955,7 @@ Thread::run()
 
     loopinterrupt_antistarve_mutex->stopby();
 
-    loop_mutex->lock();
+
     if ( ! finalize_prepared ) {
       __loop_done = false;
 
@@ -967,7 +967,9 @@ Thread::run()
       }
       __loop_listeners->unlock();
 
+      loop_mutex->lock();
       loop();
+      loop_mutex->unlock();
 
       __loop_listeners->lock();
       for (LockList<ThreadLoopListener *>::reverse_iterator it = __loop_listeners->rbegin();
@@ -977,7 +979,6 @@ Thread::run()
       }
       __loop_listeners->unlock();
     }
-    loop_mutex->unlock();
 
     __loop_done_mutex->lock();
     __loop_done = true;

- *commit* d9015159e01589dbceff325c128552449547ca20 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed May 20 15:50:43 2015 +0200
Subject: syncpoint: support components with multiple hierarchical syncpoints

 src/libs/syncpoint/syncpoint.cpp            |   43 ++++++--
 src/libs/syncpoint/syncpoint.h              |   17 +++-
 src/libs/syncpoint/syncpoint_manager.cpp    |   30 ++++-
 src/libs/syncpoint/syncpoint_manager.h      |    6 +-
 src/libs/syncpoint/tests/test_syncpoint.cpp |  168 +++++++++++++++++++++++++-
 5 files changed, 237 insertions(+), 27 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 3978765..f9c1025 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -156,9 +156,13 @@ SyncPoint::emit(const std::string & component)
     throw SyncPointNonEmitterCalledEmitException(component.c_str(),
       get_identifier().c_str());
   }
-  // we do NOT expect the component to be pending
-  // a component may call emit multiple times in a loop
-  pending_emitters_.erase(component);
+  // 1. we do NOT expect the component to be pending
+  //    a component may call emit multiple times in a loop
+  // 2. only erase the component once; it may be registered multiple times
+  multiset<string>::iterator it_pending = pending_emitters_.find(component);
+  if (it_pending != pending_emitters_.end()) {
+    pending_emitters_.erase(it_pending);
+  }
   if (pending_emitters_.empty()) {
     // all emitters have emitted the signal, thus wake all waking components
     watchers_wait_for_all_.clear();
@@ -265,18 +269,28 @@ SyncPoint::register_emitter(const string & component)
   }
 }
 
-/** Unregister an emitter. This removes the component from the barrier, thus
+/** Unregister an emitter. This removes the component from the syncpoint, thus
  *  other components will not wait for it anymore.
  *  @param component The identifier of the component which is unregistered.
+ *  @param emit_if_pending if this is set to true and the component is a
+ *         pending emitter, emit the syncpoint before releasing it.
  */
 void
-SyncPoint::unregister_emitter(const string & component) {
+SyncPoint::unregister_emitter(const string & component, bool emit_if_pending) {
   // TODO should this throw if the calling component is not registered?
   MutexLocker ml(mutex_);
-  pending_emitters_.erase(component);
-  emitters_.erase(component);
+  if (emit_if_pending && is_pending(component)) {
+    ml.unlock();
+    emit(component);
+    ml.relock();
+  }
+
+  // erase a single element from the set of emitters
+  multiset<string>::iterator it_emitter = emitters_.find(component);
+  emitters_.erase(it_emitter);
   if (predecessor_) {
-    predecessor_->unregister_emitter(component);
+    // never emit the predecessor if it's pending; it is already emitted above
+    predecessor_->unregister_emitter(component, false);
   }
 }
 
@@ -318,6 +332,14 @@ SyncPoint::get_wait_calls(WakeupType type /* = WAIT_FOR_ONE */) const {
   }
 }
 
+/**
+ * @return a copy of the set of registered emitters
+ */
+multiset<string>
+SyncPoint::get_emitters() const
+{
+  return emitters_;
+}
 
 /**
  * @return a copy of the emit call buffer
@@ -333,4 +355,9 @@ SyncPoint::reset_emitters() {
   pending_emitters_ = emitters_;
 }
 
+bool
+SyncPoint::is_pending(string component) {
+  return pending_emitters_.count(component) > 0;
+}
+
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 5c1bc47..d687f2d 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -41,6 +41,12 @@ namespace fawkes {
 #endif
 
 class SyncPointManager;
+class SyncPoint;
+
+class SyncPointSetLessThan {
+  public:
+    bool operator()(const RefPtr<SyncPoint> sp1, const RefPtr<SyncPoint> sp2) const;
+};
 
 
 class SyncPoint
@@ -71,7 +77,7 @@ class SyncPoint
     virtual void register_emitter(const std::string & component);
 
     /** unregister as emitter */
-    virtual void unregister_emitter(const std::string & component);
+    virtual void unregister_emitter(const std::string & component, bool emit_if_pending = true);
 
     std::string get_identifier() const;
     bool operator==(const SyncPoint & other) const;
@@ -79,6 +85,7 @@ class SyncPoint
     bool operator<(const SyncPoint & other) const;
 
     std::set<std::string> get_watchers() const;
+    std::multiset<std::string> get_emitters() const;
     CircularBuffer<SyncPointCall> get_wait_calls(WakeupType type = WAIT_FOR_ONE) const;
     CircularBuffer<SyncPointCall> get_emit_calls() const;
 
@@ -119,6 +126,7 @@ class SyncPoint
 
   private:
     void reset_emitters();
+    bool is_pending(std::string component);
 
   private:
     /** The predecessor SyncPoint, which is the SyncPoint one level up
@@ -126,8 +134,11 @@ class SyncPoint
      */
     RefPtr<SyncPoint> predecessor_;
 
-    std::set<std::string> emitters_;
-    std::set<std::string> pending_emitters_;
+    /** all successors */
+    std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > successors_;
+
+    std::multiset<std::string> emitters_;
+    std::multiset<std::string> pending_emitters_;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index b06642e..dd61059 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -254,6 +254,7 @@ SyncPointManager::get_syncpoint_no_lock(const std::string & component, const std
     // If this is the root SyncPoint ("/"), there will be no prefix
     std::string prefix = find_prefix(identifier);
     RefPtr<SyncPoint> predecessor = get_syncpoint_no_lock(component, prefix);
+    predecessor->successors_.insert(*sp_it);
     (*sp_it)->predecessor_ = predecessor;
   }
 
@@ -262,15 +263,21 @@ SyncPointManager::get_syncpoint_no_lock(const std::string & component, const std
 
 
 void
-SyncPointManager::release_syncpoint_no_lock(const std::string & component, RefPtr<SyncPoint> sync_point)
+SyncPointManager::release_syncpoint_no_lock(const std::string & component,
+  RefPtr<SyncPoint> sync_point)
 {
-  std::set<RefPtr<SyncPoint> >::iterator sp_it = syncpoints_.find(
-      sync_point);
+  std::set<RefPtr<SyncPoint> >::iterator sp_it = syncpoints_.find(sync_point);
   if (sp_it == syncpoints_.end()) {
-    throw SyncPointReleasedDoesNotExistException(component.c_str(), sync_point->get_identifier().c_str());
+    throw SyncPointReleasedDoesNotExistException(component.c_str(),
+        sync_point->get_identifier().c_str());
+  }
+  if (component_watches_any_successor(sync_point, component)) {
+    // successor is watched, do not release the syncpoint yet
+    return;
   }
   if (!(*sp_it)->watchers_.erase(component)) {
-    throw SyncPointReleasedByNonWatcherException(component.c_str(), sync_point->get_identifier().c_str());
+    throw SyncPointReleasedByNonWatcherException(component.c_str(),
+        sync_point->get_identifier().c_str());
   }
 
   if (sync_point->predecessor_) {
@@ -278,5 +285,18 @@ SyncPointManager::release_syncpoint_no_lock(const std::string & component, RefPt
   }
 }
 
+bool
+SyncPointManager::component_watches_any_successor(
+  const RefPtr<SyncPoint> syncpoint, const std::string component) const
+{
+  for (std::set<RefPtr<SyncPoint> >::const_iterator it = syncpoint->successors_.begin();
+      it != syncpoint->successors_.end();
+      it++) {
+    if ((*it)->get_watchers().count(component)) {
+      return true;
+    }
+  }
+  return false;
+}
 
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index 971ba2b..9c301dc 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -36,10 +36,6 @@ namespace fawkes {
 
 class SyncPoint;
 
-class SyncPointSetLessThan {
-  public:
-    bool operator()(const RefPtr<SyncPoint> sp1, const RefPtr<SyncPoint> sp2) const;
-};
 
 class SyncPointManager
 {
@@ -66,6 +62,8 @@ class SyncPointManager
       const std::string & identifier);
     void release_syncpoint_no_lock(const std::string & component,
       RefPtr<SyncPoint> syncpoint);
+    bool component_watches_any_successor(const RefPtr<SyncPoint> sp,
+      const std::string component) const;
 
 
 };
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 58e6e6c..11ab436 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -203,7 +203,9 @@ TEST_F(SyncPointManagerTest, ReleaseAndReacquire)
   ASSERT_EQ(1, syncpoints.count(RefPtr<SyncPoint>(new SyncPoint("/test"))));
   for (set<RefPtr<SyncPoint> >::const_iterator sp_it = syncpoints.begin();
       sp_it != syncpoints.end(); sp_it++) {
-    EXPECT_EQ(1, (*sp_it)->get_watchers().count(comp)) << "for component " << comp;
+    EXPECT_EQ(1, (*sp_it)->get_watchers().count(comp))
+        << "for component '" << comp << "' and SyncPoint '"
+        << (*sp_it)->get_identifier() << "'";
   }
   manager->release_syncpoint(comp, sp);
   for (set<RefPtr<SyncPoint> >::const_iterator sp_it = syncpoints.begin();
@@ -238,6 +240,61 @@ TEST_F(SyncPointManagerTest, SyncPointManagerExceptions) {
         SyncPointInvalidIdentifierException);
 }
 
+TEST_F(SyncPointManagerTest, SyncPointHierarchyRegisteredWatchers)
+{
+  string comp = "component1";
+  string id = "/test/sp1";
+  RefPtr<SyncPoint> sp = manager->get_syncpoint(comp, "/test/sp1");
+  set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints = manager->get_syncpoints();
+  set<RefPtr<SyncPoint>>::iterator sp_test_it = syncpoints.find(RefPtr<SyncPoint>(new SyncPoint("/test")));
+  set<RefPtr<SyncPoint>>::iterator sp_root_it = syncpoints.find(RefPtr<SyncPoint>(new SyncPoint("/")));
+  ASSERT_NE(syncpoints.end(), sp_test_it);
+  ASSERT_NE(syncpoints.end(), sp_root_it);
+  RefPtr<SyncPoint> sp_test = *sp_test_it;
+  RefPtr<SyncPoint> sp_root = *sp_root_it;
+  EXPECT_EQ(1, syncpoints.count(sp_test));
+  EXPECT_EQ(1, syncpoints.count(sp_root));
+  EXPECT_EQ(1, sp->get_watchers().count(comp));
+  EXPECT_EQ(1, sp_test->get_watchers().count(comp));
+  EXPECT_EQ(0, sp_test->get_watchers().count(id));
+  EXPECT_EQ(1, sp_root->get_watchers().count(comp));
+  EXPECT_EQ(0, sp_root->get_watchers().count(id));
+  EXPECT_EQ(0,
+      sp_root->get_watchers().count(
+          sp_test->get_identifier()));
+
+  manager->release_syncpoint(comp, sp);
+  EXPECT_EQ(0, sp_test->get_watchers().count(id));
+}
+
+TEST_F(SyncPointManagerTest, SyncPointComponentRegistersForMultipleSyncPoints)
+{
+  string comp = "component1";
+  string sp1_id = "/test/sp1";
+  string sp2_id = "/test/sp2";
+  RefPtr<SyncPoint> sp1 = manager->get_syncpoint(comp, sp1_id);
+  // the following should not throw
+  // if it does, registering for the predecessor '/test' may be broken
+  RefPtr<SyncPoint> sp2 = manager->get_syncpoint(comp, sp2_id);
+  RefPtr<SyncPoint> predecessor = *manager->get_syncpoints().find(
+      RefPtr<SyncPoint>(new SyncPoint("/test")));
+  EXPECT_EQ(1, sp1->get_watchers().count(comp))
+      << comp << " is not registered for " << sp1->get_identifier()
+      << ", but should be!";
+  EXPECT_EQ(1, sp2->get_watchers().count(comp))
+      << comp << " is not registered for " << sp2->get_identifier()
+      << ", but should be!";
+  EXPECT_EQ(1, predecessor->get_watchers().count(comp))
+      << comp << " is not registered for " << predecessor->get_identifier()
+      << ", but should be!";
+
+  manager->release_syncpoint(comp, sp1);
+  EXPECT_EQ(1, sp2->get_watchers().count(comp));
+  EXPECT_EQ(1, predecessor->get_watchers().count(comp))
+      << comp << " is not registered for " << predecessor->get_identifier()
+      << ", but should be!";
+}
+
 // helper function used for testing wait()
 void * call_wait(void *data)
 {
@@ -265,21 +322,26 @@ struct waiter_thread_params {
     /** SyncPointManager passed to the thread */
     RefPtr<SyncPointManager> manager;
     /** Thread number */
-    uint thread_nr;
+    uint thread_nr = 0;
     /** Number of wait calls the thread should make */
     uint num_wait_calls;
     /** Name of the SyncPoint */
     string sp_identifier;
+    /** Name of the component */
+    string component = "";
 };
 
 
 /** get a SyncPoint and wait for it */
 void * start_waiter_thread(void * data) {
   waiter_thread_params *params = (waiter_thread_params *)data;
-  char *comp;
-  asprintf(&comp, "component %u", params->thread_nr);
-  string component = comp;
-  free(comp);
+  string component = params->component;
+  if (component == "") {
+    char *comp;
+    asprintf(&comp, "component %u", params->thread_nr);
+    component = comp;
+    free(comp);
+  }
   RefPtr<SyncPoint> sp = params->manager->get_syncpoint(component, params->sp_identifier);
   for (uint i = 0; i < params->num_wait_calls; i++) {
     sp->wait(component);
@@ -455,7 +517,8 @@ TEST_F(SyncBarrierTest, EmitWithoutRegister)
   ASSERT_THROW(barrier->emit(component), SyncPointNonEmitterCalledEmitException);
 }
 
-/** Register multiple times */
+/** Register multiple times
+ * This is allowed, but the component should then also emit multiple times */
 TEST_F(SyncBarrierTest, MultipleRegisterCalls)
 {
   string component = "emitter";
@@ -741,3 +804,94 @@ TEST_F(SyncBarrierTest, SyncBarrierHierarchy)
   }
 }
 
+/** One component registers as emitter for two syncpoints, two other components
+ *  wait for the first and second syncpoint respectively.
+ *  Then, the first component unregisters for the first syncpoint.
+ *  Test whether it is still registered for the second syncpoint.
+ *  A third waiter waits for the predecessor syncpoint and should also still be
+ *  waiting after the emitter has unregistered for the first syncpoint.
+ */
+TEST_F(SyncPointManagerTest, OneEmitterRegistersForMultipleSyncPointsHierarchyTest)
+{
+  string id_sp1 = "/test/sp1";
+  string id_sp2 = "/test/sp2";
+  string id_sp_pred = "/test";
+  string id_emitter = "component_emitter";
+  string id_waiter1 = "component_waiter1";
+  string id_waiter2 = "component_waiter2";
+  string id_waiter3 = "component_waiter_on_predecessor";
+
+  RefPtr<SyncPoint> sp1 = manager->get_syncpoint(id_emitter, id_sp1);
+  RefPtr<SyncPoint> sp2 = manager->get_syncpoint(id_emitter, id_sp2);
+  manager->get_syncpoint(id_waiter1, id_sp1);
+  manager->get_syncpoint(id_waiter2, id_sp2);
+  RefPtr<SyncPoint> pred = manager->get_syncpoint(id_waiter3, id_sp_pred);
+  sp1->register_emitter(id_emitter);
+  sp2->register_emitter(id_emitter);
+  EXPECT_EQ(1, sp1->get_emitters().count(id_emitter));
+  EXPECT_EQ(1, sp2->get_emitters().count(id_emitter));
+  // this should be 2 as the emitter has registered twice
+  EXPECT_EQ(2, pred->get_emitters().count(id_emitter));
+
+
+  waiter_thread_params *params1 = new waiter_thread_params();
+  params1->manager = manager;
+  params1->component = id_waiter1;
+  params1->num_wait_calls = 1;
+  params1->sp_identifier = id_sp1;
+
+  waiter_thread_params *params2 = new waiter_thread_params();
+  params2->manager = manager;
+  params2->component = id_waiter2;
+  params2->num_wait_calls = 1;
+  params2->sp_identifier = id_sp2;
+
+  waiter_thread_params *params3 = new waiter_thread_params();
+  params3->manager = manager;
+  params3->component = id_waiter3;
+  params3->num_wait_calls = 1;
+  params3->sp_identifier = id_sp_pred;
+
+  pthread_t pthread1;
+  pthread_create(&pthread1, &attrs, start_barrier_waiter_thread, params1);
+  pthread_t pthread2;
+  pthread_create(&pthread2, &attrs, start_barrier_waiter_thread, params2);
+  pthread_t pthread3;
+  pthread_create(&pthread3, &attrs, start_barrier_waiter_thread, params3);
+
+  usleep(10000);
+  sp1->emit(id_emitter);
+  usleep(10000);
+  EXPECT_EQ(0, pthread_tryjoin_np(pthread1, NULL));
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread2, NULL));
+  // this should be EBUSY as the component has registered twice for '/test'
+  // and thus should emit '/test' also twice (by hierarchical emit calls)
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread3, NULL));
+  sp2->emit(id_emitter);
+  usleep(10000);
+  EXPECT_EQ(0, pthread_tryjoin_np(pthread2, NULL));
+  EXPECT_EQ(0, pthread_tryjoin_np(pthread3, NULL));
+
+  sp2->unregister_emitter(id_emitter);
+  EXPECT_EQ(1, sp1->get_emitters().count(id_emitter));
+  EXPECT_EQ(0, sp2->get_emitters().count(id_emitter));
+  EXPECT_EQ(1, pred->get_emitters().count(id_emitter));
+
+  pthread_create(&pthread1, &attrs, start_barrier_waiter_thread, params1);
+  pthread_create(&pthread2, &attrs, start_barrier_waiter_thread, params2);
+  pthread_create(&pthread3, &attrs, start_barrier_waiter_thread, params3);
+
+  usleep(10000);
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread1, NULL));
+  ASSERT_EQ(0, pthread_tryjoin_np(pthread2, NULL));
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread3, NULL));
+
+  sp1->emit(id_emitter);
+  usleep(10000);
+  ASSERT_EQ(0, pthread_tryjoin_np(pthread1, NULL));
+  ASSERT_EQ(0, pthread_tryjoin_np(pthread3, NULL));
+  delete params1;
+  delete params2;
+  delete params3;
+
+}

- *commit* e934ffeda8801a63f34b11ef7b4929d5e9242b76 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Thu May 21 14:24:19 2015 +0200
Subject: syncpoint: correctly manage pending components of predecessor syncpoints

 src/libs/syncpoint/exceptions.h             |    5 +-
 src/libs/syncpoint/syncpoint.cpp            |   55 +++++++++++++++++------
 src/libs/syncpoint/syncpoint.h              |    4 ++
 src/libs/syncpoint/tests/test_syncpoint.cpp |   63 +++++++++++++++++++++++---
 4 files changed, 101 insertions(+), 26 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/exceptions.h b/src/libs/syncpoint/exceptions.h
index 7fbe10d..5ea9d87 100644
--- a/src/libs/syncpoint/exceptions.h
+++ b/src/libs/syncpoint/exceptions.h
@@ -185,9 +185,8 @@ class SyncPointNonEmitterCalledEmitException : public Exception
 	SyncPointNonEmitterCalledEmitException(const char * component,
       const char *identifier)
     {
-      append("Component '%s' called emit for SyncBarrier '%s', "
-	  "but is not a registered emitter",
-          component, identifier);
+      append("Component '%s' called emit for SyncPoint '%s', "
+          "but is not a registered emitter", component, identifier);
     }
 };
 
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index f9c1025..61b7984 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -61,7 +61,8 @@ SyncPoint::SyncPoint(string identifier)
       creation_time_(Time()),
       mutex_(new Mutex()),
       cond_wait_for_one_(new WaitCondition()),
-      cond_wait_for_all_(new WaitCondition())
+      cond_wait_for_all_(new WaitCondition()),
+      last_emitter_reset_(Time(0l))
 {
   if (identifier.empty()) {
     delete cond_wait_for_one_;
@@ -141,9 +142,21 @@ SyncPoint::operator<(const SyncPoint &other) const
 void
 SyncPoint::emit(const std::string & component)
 {
+  emit(component, true);
+}
+
+/** Wake up all components which are waiting for this SyncPoint
+ * @param component The identifier of the component emitting the SyncPoint
+ * @param remove_from_pending if set to true, the component will be removed
+ *        from the pending emitters for this syncpoint
+ */
+void
+SyncPoint::emit(const std::string & component, bool remove_from_pending)
+{
   MutexLocker ml(mutex_);
   if (!watchers_.count(component)) {
-    throw SyncPointNonWatcherCalledEmitException(component.c_str(), get_identifier().c_str());
+    throw SyncPointNonWatcherCalledEmitException(component.c_str(),
+        get_identifier().c_str());
   }
 
   // unlock all wait_for_one waiters
@@ -156,18 +169,29 @@ SyncPoint::emit(const std::string & component)
     throw SyncPointNonEmitterCalledEmitException(component.c_str(),
       get_identifier().c_str());
   }
-  // 1. we do NOT expect the component to be pending
-  //    a component may call emit multiple times in a loop
-  // 2. only erase the component once; it may be registered multiple times
-  multiset<string>::iterator it_pending = pending_emitters_.find(component);
-  if (it_pending != pending_emitters_.end()) {
-    pending_emitters_.erase(it_pending);
-  }
-  if (pending_emitters_.empty()) {
-    // all emitters have emitted the signal, thus wake all waking components
-    watchers_wait_for_all_.clear();
-    cond_wait_for_all_->wake_all();
-    reset_emitters();
+
+  /* 1. remember whether the component was pending; if so, it may be removed
+   *    from the pending components of the predecessor. Otherwise, it should
+   *    not be removed
+   * 2. only erase the component once; it may be registered multiple times
+   */
+  bool pred_remove_from_pending = false;
+  if (remove_from_pending) {
+    multiset<string>::iterator it_pending = pending_emitters_.find(component);
+    if (it_pending != pending_emitters_.end()) {
+      pending_emitters_.erase(it_pending);
+      if (predecessor_) {
+        if (last_emitter_reset_ <= predecessor_->last_emitter_reset_) {
+          pred_remove_from_pending = true;
+        }
+      }
+      if (pending_emitters_.empty()) {
+        // all emitters have emitted the signal, thus wake all waking components
+        watchers_wait_for_all_.clear();
+        cond_wait_for_all_->wake_all();
+        reset_emitters();
+      }
+    }
   }
 
   emit_calls_.push_back(SyncPointCall(component));
@@ -175,7 +199,7 @@ SyncPoint::emit(const std::string & component)
   ml.unlock();
 
   if (predecessor_) {
-    predecessor_->emit(component);
+    predecessor_->emit(component, pred_remove_from_pending);
   }
 }
 
@@ -352,6 +376,7 @@ SyncPoint::get_emit_calls() const {
 
 void
 SyncPoint::reset_emitters() {
+  last_emitter_reset_ = Time();
   pending_emitters_ = emitters_;
 }
 
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index d687f2d..a0cb0a3 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -97,6 +97,8 @@ class SyncPoint
 
   protected:
     std::pair<std::set<std::string>::iterator,bool> add_watcher(std::string watcher);
+    /** send a signal to all waiting threads */
+    virtual void emit(const std::string & component, bool remove_from_pending);
 
   protected:
     /** The unique identifier of the SyncPoint */
@@ -139,6 +141,8 @@ class SyncPoint
 
     std::multiset<std::string> emitters_;
     std::multiset<std::string> pending_emitters_;
+
+    Time last_emitter_reset_;
 };
 
 } // end namespace fawkes
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index 11ab436..bc3a571 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -664,11 +664,6 @@ TEST_F(SyncBarrierTest, WaitForAllEmitters)
 
   em1.emit();
 
-  sleep(1);
-  for (uint i = 0; i < num_waiter_threads; i++) {
-    EXPECT_EQ(EBUSY, pthread_tryjoin_np(waiter_threads[i], NULL));
-  }
-
   em2.emit();
 
   sleep(1);
@@ -862,15 +857,15 @@ TEST_F(SyncPointManagerTest, OneEmitterRegistersForMultipleSyncPointsHierarchyTe
   usleep(10000);
   sp1->emit(id_emitter);
   usleep(10000);
-  EXPECT_EQ(0, pthread_tryjoin_np(pthread1, NULL));
+  ASSERT_EQ(0, pthread_tryjoin_np(pthread1, NULL));
   EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread2, NULL));
   // this should be EBUSY as the component has registered twice for '/test'
   // and thus should emit '/test' also twice (by hierarchical emit calls)
   EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread3, NULL));
   sp2->emit(id_emitter);
   usleep(10000);
-  EXPECT_EQ(0, pthread_tryjoin_np(pthread2, NULL));
-  EXPECT_EQ(0, pthread_tryjoin_np(pthread3, NULL));
+  ASSERT_EQ(0, pthread_tryjoin_np(pthread2, NULL));
+  ASSERT_EQ(0, pthread_tryjoin_np(pthread3, NULL));
 
   sp2->unregister_emitter(id_emitter);
   EXPECT_EQ(1, sp1->get_emitters().count(id_emitter));
@@ -895,3 +890,55 @@ TEST_F(SyncPointManagerTest, OneEmitterRegistersForMultipleSyncPointsHierarchyTe
   delete params3;
 
 }
+
+/** Test if an exception is thrown if a registered emitter is currently not
+ * pending
+ */
+TEST_F(SyncBarrierTest, NonPendingEmitterEmits)
+{
+  Emitter em1("em1", "/barrier", manager);
+  // register a second emitter to avoid immediate reset after emit
+  Emitter em2("em2", "/barrier", manager);
+  EXPECT_NO_THROW(em1.emit());
+  EXPECT_NO_THROW(em1.emit());
+}
+
+/** Test if a component waiting for a syncpoint is woken up
+ * if an emitter is registered for two successor syncpoints and the emitter
+ * emits the same syncpoint twice
+ */
+TEST_F(SyncPointManagerTest, EmitterEmitsSameSyncPointTwiceTest)
+{
+  RefPtr<SyncPoint> sp1 = manager->get_syncpoint("emitter", "/test/sp1");
+  RefPtr<SyncPoint> sp2 = manager->get_syncpoint("emitter", "/test/sp2");
+  RefPtr<SyncPoint> sp_pred = manager->get_syncpoint("waiter", "/test");
+
+  sp1->register_emitter("emitter");
+  sp2->register_emitter("emitter");
+
+  waiter_thread_params *params1 = new waiter_thread_params();
+  params1->manager = manager;
+  params1->component = "waiter";
+  params1->num_wait_calls = 1;
+  params1->sp_identifier = "/test";
+
+  pthread_t pthread1;
+  pthread_create(&pthread1, &attrs, start_barrier_waiter_thread, params1);
+
+  usleep(10000);
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread1, NULL));
+
+  sp1->emit("emitter");
+  usleep(10000);
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread1, NULL));
+
+  sp1->emit("emitter");
+  usleep(10000);
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(pthread1, NULL));
+
+  sp2->emit("emitter");
+  usleep(10000);
+  ASSERT_EQ(0, pthread_tryjoin_np(pthread1, NULL));
+
+  delete params1;
+}

- *commit* d8c6b2fb2e4e6f1e0fb2dab22df63c7e5a36b982 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Jul 22 15:02:21 2015 +0200
Subject: core: release the loop listeners' mutex when joining the thread

 src/libs/core/threading/thread.cpp |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/core/threading/thread.cpp b/src/libs/core/threading/thread.cpp
index 8ec142b..9f1509a 100644
--- a/src/libs/core/threading/thread.cpp
+++ b/src/libs/core/threading/thread.cpp
@@ -631,6 +631,16 @@ Thread::join()
     // mutex above could happen!
     loop_mutex->try_lock();
     loop_mutex->unlock();
+
+    // Force unlock of the loop listeners' mutex. If the thread is canceled
+    // during a loop listener call (pre_loop or post_loop), the thread cannot
+    // be finalized because this LockList is still locked, and any aspect using
+    // a LoopListener will try to remove itself from the LockList during
+    // finalization, leading to a deadlock. It is safe to unlock the mutex
+    // because the thread is already joined and thus no more loop listener calls
+    // will occur.
+    __loop_listeners->try_lock();
+    __loop_listeners->unlock();
   }
 }
 

- *commit* 538921a69e8de75af25c8c1fe668f37a24584cd1 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Thu Jul 23 13:56:45 2015 +0200
Subject: syncpoint: improve syncpoint visualization

 src/libs/syncpoint/syncpoint_call_stats.cpp |   12 ++++++++
 src/libs/syncpoint/syncpoint_call_stats.h   |    1 +
 src/libs/syncpoint/syncpoint_manager.cpp    |   37 ++++++++++++++++++--------
 3 files changed, 38 insertions(+), 12 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint_call_stats.cpp b/src/libs/syncpoint/syncpoint_call_stats.cpp
index ebf2040..969cf75 100644
--- a/src/libs/syncpoint/syncpoint_call_stats.cpp
+++ b/src/libs/syncpoint/syncpoint_call_stats.cpp
@@ -95,6 +95,9 @@ SyncPointCallStats::get_last_call() const
 float
 SyncPointCallStats::get_call_frequency() const
 {
+  if (num_calls_ <= 1) {
+    return 0.f;
+  }
   return num_calls_ / (last_call_.in_sec() - first_call_.in_sec());
 }
 
@@ -107,4 +110,13 @@ SyncPointCallStats::get_waittime_average() const
   return total_wait_time_.in_sec() / num_calls_;
 }
 
+/** Get total number of calls.
+ * @return the total number of calls
+ */
+unsigned int
+SyncPointCallStats::get_num_calls() const
+{
+  return num_calls_;
+}
+
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint_call_stats.h b/src/libs/syncpoint/syncpoint_call_stats.h
index 7bad11b..53041be 100644
--- a/src/libs/syncpoint/syncpoint_call_stats.h
+++ b/src/libs/syncpoint/syncpoint_call_stats.h
@@ -41,6 +41,7 @@ class SyncPointCallStats {
     Time get_last_call() const;
     float get_call_frequency() const;
     float get_waittime_average() const;
+    unsigned int get_num_calls() const;
 
   private:
     Time first_call_;
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index dd61059..465ade5 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -164,6 +164,7 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
           << "\"" << " [label=\""
           << " freq=" << emit_call_stats_it->second.get_call_frequency() << "Hz"
           << " age=" << age << "s"
+          << " #calls=" << emit_call_stats_it->second.get_num_calls()
           << "\"" << "];";
       }
     }
@@ -181,12 +182,18 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
         wait_call_stats_it != wait_one_call_stats.end(); wait_call_stats_it++) {
       float age = (Time() - wait_call_stats_it->second.get_last_call()).in_sec();
       if (age < max_age) {
-      graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> "
-          << "\"" << wait_call_stats_it->first << "\"" << " [label=" << "\""
-          << " avg=" << wait_call_stats_it->second.get_waittime_average() <<  "s"
-          << " age=" << age << "s"
-          //<< " max=" << max_wait_time << "s"
-          << "\"" << "];";
+        graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> "
+            << "\"" << wait_call_stats_it->first << "\"" << " [label=" << "\""
+            << " avg=" << wait_call_stats_it->second.get_waittime_average() <<  "s"
+            << " age=" << age << "s"
+            << " #calls=" << wait_call_stats_it->second.get_num_calls()
+            //          << " max=" << max_wait_time << "s"
+            << "\"";
+        if ((*sp_it)->watchers_wait_for_one_.count(wait_call_stats_it->first)) {
+          graph << ",color=\"red\"";
+        }
+        graph << ",style=dotted";
+        graph << "];";
       }
     }
 
@@ -203,12 +210,18 @@ SyncPointManager::all_syncpoints_as_dot(float max_age)
         wait_call_stats_it != wait_all_call_stats.end(); wait_call_stats_it++) {
       float age = (Time() - wait_call_stats_it->second.get_last_call()).in_sec();
       if (age < max_age) {
-      graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> "
-          << "\"" << wait_call_stats_it->first << "\"" << " [label=" << "\""
-          << " avg=" << wait_call_stats_it->second.get_waittime_average() <<  "s"
-          << " age=" << age << "s"
-          //<< " max=" << max_wait_time << "s"
-          << "\"" << "];";
+        graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> "
+            << "\"" << wait_call_stats_it->first << "\"" << " [label=" << "\""
+            << " avg=" << wait_call_stats_it->second.get_waittime_average() <<  "s"
+            << " age=" << age << "s"
+            << " #calls=" << wait_call_stats_it->second.get_num_calls()
+            //<< " max=" << max_wait_time << "s"
+            << "\"";
+        if ((*sp_it)->watchers_wait_for_all_.count(wait_call_stats_it->first)) {
+          graph << ",color=\"red\"";
+        }
+        graph << ",style=dashed";
+        graph << "];";
       }
     }
 

- *commit* 079607de1b7e1984cfaf894e681dcc4d2ce186bf - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Thu Jul 23 14:33:23 2015 +0200
Subject: syncpoint: wake up all components in the same hierarchy simultaneously

 src/libs/syncpoint/syncpoint.cpp |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index 61b7984..b9827f0 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -196,8 +196,6 @@ SyncPoint::emit(const std::string & component, bool remove_from_pending)
 
   emit_calls_.push_back(SyncPointCall(component));
 
-  ml.unlock();
-
   if (predecessor_) {
     predecessor_->emit(component, pred_remove_from_pending);
   }

- *commit* 99bae6ef6ecf55d5a23d6e8cba5e7a398ddbd7a0 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Fri Jul 24 17:56:08 2015 +0200
Subject: syncpoint: add the possibility of time-limited waits

 src/libs/Makefile                           |    4 +-
 src/libs/baseapp/main_thread.cpp            |    3 +-
 src/libs/baseapp/run.cpp                    |    2 +-
 src/libs/syncpoint/syncpoint.cpp            |   78 ++++++++++++++++++-
 src/libs/syncpoint/syncpoint.h              |   18 ++++-
 src/libs/syncpoint/syncpoint_manager.cpp    |    8 +-
 src/libs/syncpoint/syncpoint_manager.h      |    5 +-
 src/libs/syncpoint/tests/Makefile           |    3 +-
 src/libs/syncpoint/tests/test_syncpoint.cpp |  108 ++++++++++++++++++++++-----
 9 files changed, 196 insertions(+), 33 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/Makefile b/src/libs/Makefile
index a6d8498..d90e161 100644
--- a/src/libs/Makefile
+++ b/src/libs/Makefile
@@ -53,7 +53,7 @@ gui_utils: core netcomm blackboard interface plugin logging
 logging: core utils netcomm
 naoutils: core utils
 webview: core utils logging
-baseapp: core utils aspect config netcomm blackboard plugin logging
+baseapp: core utils aspect config netcomm blackboard plugin logging syncpoint
 tf: core utils blackboard interface interfaces
 fvutils: core utils netcomm logging
 fvcams fvmodels fvfilters fvclassifiers fvstereo fvwidgets: core utils fvutils logging
@@ -65,7 +65,7 @@ endif
 protobuf_clips: core logging protobuf_comm
 pcl_utils: core tf
 kdl_parser: core
-syncpoint: core 
+syncpoint: core logging
 
 include $(BUILDSYSDIR)/rules.mk
 include $(LIBSRCDIR)/extlibs.mk
diff --git a/src/libs/baseapp/main_thread.cpp b/src/libs/baseapp/main_thread.cpp
index ae0875f..a2c1a5f 100644
--- a/src/libs/baseapp/main_thread.cpp
+++ b/src/libs/baseapp/main_thread.cpp
@@ -346,7 +346,8 @@ FawkesMainThread::loop()
       } else {
         for (uint i = 0; i < num_hooks; i++) {
           __syncpoints_start_hook[i]->emit("FawkesMainThread");
-          __syncpoints_end_hook[i]->wait_for_all("FawkesMainThread");
+          __syncpoints_end_hook[i]->reltime_wait_for_all("FawkesMainThread",
+              0, __max_thread_time_nanosec);
         }
       }
     }
diff --git a/src/libs/baseapp/run.cpp b/src/libs/baseapp/run.cpp
index 2293eac..5247247 100644
--- a/src/libs/baseapp/run.cpp
+++ b/src/libs/baseapp/run.cpp
@@ -356,7 +356,7 @@ init(InitOptions options, int & retval)
   aspect_manager     = new AspectManager();
   thread_manager     = new ThreadManager(aspect_manager, aspect_manager);
 
-  syncpoint_manager  = new SyncPointManager();
+  syncpoint_manager  = new SyncPointManager(logger);
 
   plugin_manager     = new PluginManager(thread_manager, config,
 					 "/fawkes/meta_plugins/",
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index b9827f0..d39cfe0 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -52,8 +52,9 @@ namespace fawkes {
 /** Constructor.
  * @param identifier The identifier of the SyncPoint. This must be in absolute
  * path style, e.g. '/some/syncpoint'.
+ * @param logger The logger to use for error messages.
  */
-SyncPoint::SyncPoint(string identifier)
+SyncPoint::SyncPoint(string identifier, MultiLogger *logger)
     : identifier_(identifier),
       emit_calls_(CircularBuffer<SyncPointCall>(1000)),
       wait_for_one_calls_(CircularBuffer<SyncPointCall>(1000)),
@@ -62,6 +63,7 @@ SyncPoint::SyncPoint(string identifier)
       mutex_(new Mutex()),
       cond_wait_for_one_(new WaitCondition()),
       cond_wait_for_all_(new WaitCondition()),
+      logger_(logger),
       last_emitter_reset_(Time(0l))
 {
   if (identifier.empty()) {
@@ -204,14 +206,24 @@ SyncPoint::emit(const std::string & component, bool remove_from_pending)
 /** Wait until SyncPoint is emitted.
  * Either wait until a single emitter has emitted the SyncPoint, or wait
  * until all registered emitters have emitted the SyncPoint.
+ * If wait_sec != 0 or wait_nsec !=0, then only wait for
+ * wait_sec + wait_nsec*10^-9 seconds.
+ * If the maximal wait time has been exceeded, a warning is shown and the
+ * SyncPoint is released.
  * @param component The identifier of the component waiting for the SyncPoint
  * @param type the wakeup type. If this is set to WAIT_FOR_ONE, wait returns
  * when a single emitter has emitted the SyncPoint. If set to WAIT_FOR_ALL, wait
  * until all registered emitters have emitted the SyncPoint.
+ * @param wait_sec number of seconds to wait for the SyncPoint
+ * @param wait_nsec number of nanoseconds to wait for the SyncPoint
  * @see SyncPoint::WakeupType
  */
 void
-SyncPoint::wait(const std::string & component, WakeupType type /* = WAIT_FOR_ONE */) {
+SyncPoint::wait(const std::string & component,
+  WakeupType type /* = WAIT_FOR_ONE */, uint wait_sec /* = 0 */,
+  uint wait_nsec /* = 0 */)
+{
+
   MutexLocker ml(mutex_);
 
   std::set<std::string> *watchers;
@@ -250,7 +262,12 @@ SyncPoint::wait(const std::string & component, WakeupType type /* = WAIT_FOR_ONE
   ml.unlock();
   Time start;
   if (need_to_wait) {
-    cond->wait();
+    if (!cond->reltimed_wait(wait_sec, wait_nsec)) {
+      ml.relock();
+      // wait failed, default
+      handle_default(component, type, wait_sec, wait_nsec);
+      ml.unlock();
+    }
   }
   Time wait_time = Time() - start;
   ml.relock();
@@ -275,6 +292,29 @@ SyncPoint::wait_for_all(const string & component)
   wait(component, WAIT_FOR_ALL);
 }
 
+/** Wait for a single emitter for the given time.
+ * @param component The identifier of the calling component.
+ * @param wait_sec number of seconds to wait
+ * @param wait_nsec number of nanoseconds to wait additionally to wait_sec
+ */
+void
+SyncPoint::reltime_wait_for_one(const string & component, uint wait_sec,
+  uint wait_nsec)
+{
+  wait(component, SyncPoint::WAIT_FOR_ONE, wait_sec, wait_nsec);
+}
+
+/** Wait for all registered emitters for the given time.
+ * @param component The identifier of the calling component.
+ * @param wait_sec number of seconds to wait
+ * @param wait_nsec number of nanoseconds to wait additionally to wait_sec
+ */
+void
+SyncPoint::reltime_wait_for_all(const string & component, uint wait_sec,
+  uint wait_nsec)
+{
+  wait(component, SyncPoint::WAIT_FOR_ALL, wait_sec, wait_nsec);
+}
 
 /** Register an emitter. A thread can only emit the barrier if it has been
  *  registered.
@@ -383,4 +423,36 @@ SyncPoint::is_pending(string component) {
   return pending_emitters_.count(component) > 0;
 }
 
+void
+SyncPoint::handle_default(string component, WakeupType type,
+  uint max_time_sec, uint max_time_nsec)
+{
+  logger_->log_warn(component.c_str(),
+      "Thread time limit exceeded while waiting for syncpoint '%s'. "
+      "Time limit: %f sec.",
+      get_identifier().c_str(),
+      max_time_sec + static_cast<float>(max_time_nsec) / 1000000000.f);
+  bad_components_.insert(pending_emitters_.begin(), pending_emitters_.end());
+  if (bad_components_.size() > 1) {
+    string bad_components_string = "";
+    for (set<string>::const_iterator it = bad_components_.begin();
+        it != bad_components_.end(); it++) {
+      bad_components_string += " " + *it;
+    }
+    logger_->log_warn(component.c_str(), "bad components:%s",
+        bad_components_string.c_str());
+  }
+  else if (bad_components_.size() == 1) {
+    logger_->log_warn(component.c_str(), "bad component: %s",
+        bad_components_.begin()->c_str());
+  }
+  else if (type == SyncPoint::WAIT_FOR_ALL) {
+    throw Exception("SyncPoints: component %s defaulted, "
+        "but there is no pending emitter. This is probably a bug.",
+        component.c_str());
+  }
+
+  watchers_wait_for_all_.erase(component);
+  watchers_wait_for_one_.erase(component);
+}
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index a0cb0a3..0301766 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -31,6 +31,8 @@
 #include <core/utils/refptr.h>
 #include <core/utils/circular_buffer.h>
 
+#include <logging/multi.h>
+
 #include <set>
 #include <map>
 #include <string>
@@ -62,16 +64,22 @@ class SyncPoint
       NONE
     } WakeupType;
 
-    SyncPoint(std::string identifier);
+    SyncPoint(std::string identifier, MultiLogger *logger);
     virtual ~SyncPoint();
 
     /** send a signal to all waiting threads */
     virtual void emit(const std::string & component);
 
     /** wait for the sync point to be emitted by any other component */
-    virtual void wait(const std::string & component, WakeupType = WAIT_FOR_ONE);
+    virtual void wait(const std::string & component, WakeupType = WAIT_FOR_ONE,
+      uint wait_sec = 0, uint wait_nsec = 0);
     virtual void wait_for_one(const std::string & component);
     virtual void wait_for_all(const std::string & component);
+    /** wait for the sync point, but abort after given time */
+    virtual void reltime_wait_for_one(const std::string & component,
+      uint wait_sec, uint wait_nsec);
+    virtual void reltime_wait_for_all(const std::string & component,
+      uint wait_sec, uint wait_nsec);
 
     /** register as emitter */
     virtual void register_emitter(const std::string & component);
@@ -125,10 +133,14 @@ class SyncPoint
     WaitCondition *cond_wait_for_one_;
     /** WaitCondition which is used for wait_for_all() */
     WaitCondition *cond_wait_for_all_;
+    /** Logger */
+    MultiLogger *logger_;
 
   private:
     void reset_emitters();
     bool is_pending(std::string component);
+    void handle_default(std::string component, WakeupType type,
+      uint max_time_sec, uint max_time_nsec);
 
   private:
     /** The predecessor SyncPoint, which is the SyncPoint one level up
@@ -142,6 +154,8 @@ class SyncPoint
     std::multiset<std::string> emitters_;
     std::multiset<std::string> pending_emitters_;
 
+    std::set<std::string> bad_components_;
+
     Time last_emitter_reset_;
 };
 
diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp
index 465ade5..4b5e93c 100644
--- a/src/libs/syncpoint/syncpoint_manager.cpp
+++ b/src/libs/syncpoint/syncpoint_manager.cpp
@@ -45,8 +45,9 @@ namespace fawkes {
  * @see SyncPoint
  */
 
-SyncPointManager::SyncPointManager()
-: mutex_(new Mutex())
+SyncPointManager::SyncPointManager(MultiLogger *logger)
+: mutex_(new Mutex()),
+  logger_(logger)
 {
 }
 
@@ -256,7 +257,8 @@ SyncPointManager::get_syncpoint_no_lock(const std::string & component, const std
   // insert a new SyncPoint if no SyncPoint with the same identifier exists,
   // otherwise, use that SyncPoint
   std::pair<std::set<RefPtr<SyncPoint> >::iterator,bool> insert_ret;
-  insert_ret = syncpoints_.insert(RefPtr<SyncPoint>(new SyncPoint(identifier)));
+  insert_ret = syncpoints_.insert(
+      RefPtr<SyncPoint>(new SyncPoint(identifier, logger_)));
   std::set<RefPtr<SyncPoint> >::iterator sp_it = insert_ret.first;
 
   // add component to the set of watchers
diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h
index 9c301dc..82fc13f 100644
--- a/src/libs/syncpoint/syncpoint_manager.h
+++ b/src/libs/syncpoint/syncpoint_manager.h
@@ -29,6 +29,8 @@
 #include <core/utils/refptr.h>
 #include <core/threading/mutex.h>
 
+#include <logging/multi.h>
+
 namespace fawkes {
 #if 0 /* just to make Emacs auto-indent happy */
 }
@@ -40,7 +42,7 @@ class SyncPoint;
 class SyncPointManager
 {
   public:
-    SyncPointManager();
+    SyncPointManager(MultiLogger *logger);
     virtual ~SyncPointManager();
 
     RefPtr<SyncPoint> get_syncpoint(const std::string & component, const std::string & identifier);
@@ -64,6 +66,7 @@ class SyncPointManager
       RefPtr<SyncPoint> syncpoint);
     bool component_watches_any_successor(const RefPtr<SyncPoint> sp,
       const std::string component) const;
+    MultiLogger *logger_;
 
 
 };
diff --git a/src/libs/syncpoint/tests/Makefile b/src/libs/syncpoint/tests/Makefile
index a8112e6..4c773fa 100644
--- a/src/libs/syncpoint/tests/Makefile
+++ b/src/libs/syncpoint/tests/Makefile
@@ -18,7 +18,8 @@ include $(BASEDIR)/etc/buildsys/config.mk
 include $(BASEDIR)/etc/buildsys/gtest.mk
 
 CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable
-LIBS_gtest_syncpoint += stdc++ fawkescore fawkesutils fawkessyncpoint pthread
+LIBS_gtest_syncpoint += stdc++ fawkescore fawkesutils fawkessyncpoint pthread \
+                        fawkeslogging
 
 OBJS_gtest_syncpoint += test_syncpoint.o
 OBJS_all = $(OBJS_gtest_syncpoint)
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index bc3a571..c539875 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -32,11 +32,15 @@
 #include <libs/syncpoint/syncpoint_manager.h>
 #include <libs/syncpoint/exceptions.h>
 
+#include <logging/multi.h>
+#include <logging/cache.h>
+
 #include <core/utils/refptr.h>
 
 using namespace fawkes;
 using namespace std;
 
+
 /** @class SyncPointTest
  * Test class for SyncPoint
  * This class tests basic functionality of SyncPoints
@@ -50,11 +54,18 @@ class SyncPointTest : public ::testing::Test
      */
     virtual void SetUp()
     {
+      logger_ = new MultiLogger();
       string id1 = "/id1";
       string id2 = "/id2";
-      sp1 = new SyncPoint(id1);
-      sp2 = new SyncPoint(id1);
-      sp3 = new SyncPoint(id2);
+      sp1 = new SyncPoint(id1, logger_);
+      sp2 = new SyncPoint(id1, logger_);
+      sp3 = new SyncPoint(id2, logger_);
+    }
+
+    /** Clean up */
+    virtual void TearDown()
+    {
+      delete logger_;
     }
 
 
@@ -66,6 +77,10 @@ class SyncPointTest : public ::testing::Test
     RefPtr<SyncPoint> sp2;
     RefPtr<SyncPoint> sp3;
     /**@}*/
+
+    /** Logger for testing */
+    MultiLogger *logger_;
+
 };
 
 /** @class SyncPointManagerTest
@@ -80,7 +95,10 @@ class SyncPointManagerTest : public ::testing::Test
      */
     SyncPointManagerTest()
     {
-      manager = new SyncPointManager();
+      logger_ = new MultiLogger();
+      cache_logger_ = new CacheLogger();
+      logger_->add_logger(cache_logger_);
+      manager = new SyncPointManager(logger_);
 
       pthread_attr_init(&attrs);
 
@@ -92,6 +110,8 @@ class SyncPointManagerTest : public ::testing::Test
     virtual ~SyncPointManagerTest()
     {
       pthread_attr_destroy(&attrs);
+      delete logger_;
+//      delete cache_logger_;
     }
 
     /**
@@ -99,6 +119,12 @@ class SyncPointManagerTest : public ::testing::Test
      */
     RefPtr<SyncPointManager> manager;
 
+    /** Logger used to initialize SyncPoints */
+    MultiLogger *logger_;
+
+    /** Cache Logger used for testing */
+    CacheLogger *cache_logger_;
+
     /** Thread attributes */
     pthread_attr_t attrs;
 };
@@ -170,17 +196,31 @@ TEST_F(SyncPointManagerTest, SyncPointManager)
   ASSERT_EQ(0u, manager->get_syncpoints().size());
   manager->get_syncpoint("test", "/test/1");
   ASSERT_EQ(3u, manager->get_syncpoints().size());
-  ASSERT_EQ(manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))), 1u);
+  ASSERT_EQ(1u,
+      manager->get_syncpoints().count(
+          RefPtr<SyncPoint>(new SyncPoint("/test/1", logger_))));
   manager->get_syncpoint("test2", "/test/2");
   ASSERT_EQ(4u, manager->get_syncpoints().size());
-  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))));
-  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))));
+  ASSERT_EQ(1u,
+      manager->get_syncpoints().count(
+          RefPtr<SyncPoint>(new SyncPoint("/test/1", logger_))));
+  ASSERT_EQ(1u,
+      manager->get_syncpoints().count(
+          RefPtr<SyncPoint>(new SyncPoint("/test/2", logger_))));
   manager->get_syncpoint("test3", "/test/1");
   ASSERT_EQ(4u, manager->get_syncpoints().size());
-  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/1"))));
-  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test/2"))));
-  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/"))));
-  ASSERT_EQ(1u, manager->get_syncpoints().count(RefPtr<SyncPoint>(new SyncPoint("/test"))));
+  ASSERT_EQ(1u,
+      manager->get_syncpoints().count(
+          RefPtr<SyncPoint>(new SyncPoint("/test/1", logger_))));
+  ASSERT_EQ(1u,
+      manager->get_syncpoints().count(
+          RefPtr<SyncPoint>(new SyncPoint("/test/2", logger_))));
+  ASSERT_EQ(1u,
+      manager->get_syncpoints().count(
+          RefPtr<SyncPoint>(new SyncPoint("/", logger_))));
+  ASSERT_EQ(1u,
+      manager->get_syncpoints().count(
+          RefPtr<SyncPoint>(new SyncPoint("/test", logger_))));
 }
 
 TEST_F(SyncPointManagerTest, WatcherSet)
@@ -200,7 +240,9 @@ TEST_F(SyncPointManagerTest, ReleaseAndReacquire)
   string id = "/test/sp1";
   RefPtr<SyncPoint> sp = manager->get_syncpoint(comp, id);
   set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints = manager->get_syncpoints();
-  ASSERT_EQ(1, syncpoints.count(RefPtr<SyncPoint>(new SyncPoint("/test"))));
+  ASSERT_EQ(1,
+      syncpoints.count(
+          RefPtr<SyncPoint>(new SyncPoint("/test", logger_))));
   for (set<RefPtr<SyncPoint> >::const_iterator sp_it = syncpoints.begin();
       sp_it != syncpoints.end(); sp_it++) {
     EXPECT_EQ(1, (*sp_it)->get_watchers().count(comp))
@@ -218,14 +260,16 @@ TEST_F(SyncPointManagerTest, ReleaseAndReacquire)
 
 TEST_F(SyncPointTest, EmptyIdentifier)
 {
-  ASSERT_THROW(sp1 = new SyncPoint(""), SyncPointInvalidIdentifierException);
+  ASSERT_THROW(sp1 = new SyncPoint("", NULL), SyncPointInvalidIdentifierException);
 }
 
 TEST_F(SyncPointTest, InvalidIdentifier)
 {
-  EXPECT_THROW(sp1 = new SyncPoint("invalid"), SyncPointInvalidIdentifierException);
-  EXPECT_NO_THROW(sp1 = new SyncPoint("/"));
-  EXPECT_THROW(sp1 = new SyncPoint("/test/"), SyncPointInvalidIdentifierException);
+  EXPECT_THROW(sp1 = new SyncPoint("invalid", NULL),
+      SyncPointInvalidIdentifierException);
+  EXPECT_NO_THROW(sp1 = new SyncPoint("/", NULL));
+  EXPECT_THROW(sp1 = new SyncPoint("/test/", NULL),
+      SyncPointInvalidIdentifierException);
 }
 
 TEST_F(SyncPointManagerTest, SyncPointManagerExceptions) {
@@ -246,8 +290,10 @@ TEST_F(SyncPointManagerTest, SyncPointHierarchyRegisteredWatchers)
   string id = "/test/sp1";
   RefPtr<SyncPoint> sp = manager->get_syncpoint(comp, "/test/sp1");
   set<RefPtr<SyncPoint>, SyncPointSetLessThan > syncpoints = manager->get_syncpoints();
-  set<RefPtr<SyncPoint>>::iterator sp_test_it = syncpoints.find(RefPtr<SyncPoint>(new SyncPoint("/test")));
-  set<RefPtr<SyncPoint>>::iterator sp_root_it = syncpoints.find(RefPtr<SyncPoint>(new SyncPoint("/")));
+  set<RefPtr<SyncPoint>>::iterator sp_test_it = syncpoints.find(
+      RefPtr<SyncPoint>(new SyncPoint("/test", logger_)));
+  set<RefPtr<SyncPoint>>::iterator sp_root_it = syncpoints.find(
+      RefPtr<SyncPoint>(new SyncPoint("/", logger_)));
   ASSERT_NE(syncpoints.end(), sp_test_it);
   ASSERT_NE(syncpoints.end(), sp_root_it);
   RefPtr<SyncPoint> sp_test = *sp_test_it;
@@ -277,7 +323,7 @@ TEST_F(SyncPointManagerTest, SyncPointComponentRegistersForMultipleSyncPoints)
   // if it does, registering for the predecessor '/test' may be broken
   RefPtr<SyncPoint> sp2 = manager->get_syncpoint(comp, sp2_id);
   RefPtr<SyncPoint> predecessor = *manager->get_syncpoints().find(
-      RefPtr<SyncPoint>(new SyncPoint("/test")));
+      RefPtr<SyncPoint>(new SyncPoint("/test", logger_)));
   EXPECT_EQ(1, sp1->get_watchers().count(comp))
       << comp << " is not registered for " << sp1->get_identifier()
       << ", but should be!";
@@ -942,3 +988,27 @@ TEST_F(SyncPointManagerTest, EmitterEmitsSameSyncPointTwiceTest)
 
   delete params1;
 }
+
+
+/** helper function used for testing reltime_wait() */
+void * call_timed_wait(void *data)
+{
+  SyncPoint * sp = (SyncPoint *)(data);
+  sp->reltime_wait_for_all("waiter", 0, 1000000);
+  return NULL;
+}
+
+/** Test if the component returns when using reltime_wait */
+TEST_F(SyncPointManagerTest, RelTimeWaitTest)
+{
+  RefPtr<SyncPoint> sp1 = manager->get_syncpoint("emitter", "/test/sp1");
+  manager->get_syncpoint("waiter", "/test/sp1");
+  sp1->register_emitter("emitter");
+  pthread_t thread;
+  pthread_create(&thread, NULL, call_timed_wait, (void *) *sp1);
+  usleep(2000000);
+  ASSERT_EQ(0, pthread_tryjoin_np(thread, NULL));
+  /* The SyncPoint should have logged the error */
+  ASSERT_GT(cache_logger_->get_messages().size(), 0);
+
+}

- *commit* 2ebd7b36ae3206417a572d4ebee89101e25e2398 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Aug 3 15:56:05 2015 +0200
Subject: syncpoint: allow waiter to lock all emitters

 src/libs/core/threading/wait_condition.h    |    2 +
 src/libs/syncpoint/syncpoint.cpp            |   83 ++++++++++++++++++-----
 src/libs/syncpoint/syncpoint.h              |   12 ++++
 src/libs/syncpoint/tests/test_syncpoint.cpp |   95 +++++++++++++++++++++++++++
 4 files changed, 175 insertions(+), 17 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/core/threading/wait_condition.h b/src/libs/core/threading/wait_condition.h
index 2d0ca09..77b2f14 100644
--- a/src/libs/core/threading/wait_condition.h
+++ b/src/libs/core/threading/wait_condition.h
@@ -29,6 +29,8 @@ namespace fawkes {
 class WaitConditionData;
 class Mutex;
 
+void cleanup_mutex(void *);
+
 class WaitCondition {
  public:
   WaitCondition(Mutex *mutex = 0);
diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp
index d39cfe0..dc16c07 100644
--- a/src/libs/syncpoint/syncpoint.cpp
+++ b/src/libs/syncpoint/syncpoint.cpp
@@ -61,39 +61,34 @@ SyncPoint::SyncPoint(string identifier, MultiLogger *logger)
       wait_for_all_calls_(CircularBuffer<SyncPointCall>(1000)),
       creation_time_(Time()),
       mutex_(new Mutex()),
-      cond_wait_for_one_(new WaitCondition()),
-      cond_wait_for_all_(new WaitCondition()),
+      mutex_next_wait_(new Mutex()),
+      mutex_wait_for_one_(new Mutex()),
+      cond_wait_for_one_(new WaitCondition(mutex_wait_for_one_)),
+      mutex_wait_for_all_(new Mutex()),
+      cond_wait_for_all_(new WaitCondition(mutex_wait_for_all_)),
       logger_(logger),
       last_emitter_reset_(Time(0l))
 {
   if (identifier.empty()) {
-    delete cond_wait_for_one_;
-    delete cond_wait_for_all_;
-    delete mutex_;
+    cleanup();
     throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
   if (identifier.compare(0,1,"/")) {
-    delete cond_wait_for_one_;
-    delete cond_wait_for_all_;
-    delete mutex_;
+    cleanup();
     throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
   // check if last charater is '/'
   // The identifier may only end in '/' if '/' is the complete identifier.
   // '/' is allowed, '/some/' is not allowed
   if (identifier != "/" && !identifier.compare(identifier.size() - 1, 1, "/")) {
-    delete cond_wait_for_one_;
-    delete cond_wait_for_all_;
-    delete mutex_;
+    cleanup();
     throw SyncPointInvalidIdentifierException(identifier.c_str());
   }
 }
 
 SyncPoint::~SyncPoint()
 {
-  delete cond_wait_for_one_;
-  delete cond_wait_for_all_;
-  delete mutex_;
+  cleanup();
 }
 
 /**
@@ -155,6 +150,7 @@ SyncPoint::emit(const std::string & component)
 void
 SyncPoint::emit(const std::string & component, bool remove_from_pending)
 {
+  mutex_next_wait_->stopby();
   MutexLocker ml(mutex_);
   if (!watchers_.count(component)) {
     throw SyncPointNonWatcherCalledEmitException(component.c_str(),
@@ -163,9 +159,10 @@ SyncPoint::emit(const std::string & component, bool remove_from_pending)
 
   // unlock all wait_for_one waiters
   watchers_wait_for_one_.clear();
+  mutex_wait_for_one_->lock();
   cond_wait_for_one_->wake_all();
+  mutex_wait_for_one_->unlock();
 
-  // unlock all wait_for_all waiters if all pending emitters have emitted
 
   if (!emitters_.count(component)) {
     throw SyncPointNonEmitterCalledEmitException(component.c_str(),
@@ -187,10 +184,13 @@ SyncPoint::emit(const std::string & component, bool remove_from_pending)
           pred_remove_from_pending = true;
         }
       }
+
+      // unlock all wait_for_all waiters if all pending emitters have emitted
       if (pending_emitters_.empty()) {
-        // all emitters have emitted the signal, thus wake all waking components
         watchers_wait_for_all_.clear();
+        mutex_wait_for_all_->lock();
         cond_wait_for_all_->wake_all();
+        mutex_wait_for_all_->unlock();
         reset_emitters();
       }
     }
@@ -229,14 +229,17 @@ SyncPoint::wait(const std::string & component,
   std::set<std::string> *watchers;
   WaitCondition *cond;
   CircularBuffer<SyncPointCall> *calls;
+  Mutex *mutex_cond;
   // set watchers, cond and calls depending of the Wakeup type
   if (type == WAIT_FOR_ONE) {
     watchers = &watchers_wait_for_one_;
     cond = cond_wait_for_one_;
+    mutex_cond = mutex_wait_for_one_;
     calls = &wait_for_one_calls_;
   } else if (type == WAIT_FOR_ALL) {
     watchers = &watchers_wait_for_all_;
     cond = cond_wait_for_all_;
+    mutex_cond = mutex_wait_for_all_;
     calls = &wait_for_all_calls_;
   } else {
     throw SyncPointInvalidTypeException();
@@ -259,8 +262,20 @@ SyncPoint::wait(const std::string & component,
   if (need_to_wait) {
     watchers->insert(component);
   }
-  ml.unlock();
+
+  /* Check if emitters are currently waiting for this component.
+   * If so, wake them up *after* locking the WaitCondition's mutex.
+   * Only this way we can guarantee that this component will certainly call
+   * wait before the emitters emit
+   */
   Time start;
+  mutex_cond->lock();
+  pthread_cleanup_push(cleanup_mutex, mutex_cond);
+  if (emit_locker_ == component) {
+    mutex_next_wait_->unlock();
+    emit_locker_ = "";
+  }
+  ml.unlock();
   if (need_to_wait) {
     if (!cond->reltimed_wait(wait_sec, wait_nsec)) {
       ml.relock();
@@ -269,6 +284,8 @@ SyncPoint::wait(const std::string & component,
       ml.unlock();
     }
   }
+  mutex_cond->unlock();
+  pthread_cleanup_pop(0);
   Time wait_time = Time() - start;
   ml.relock();
   calls->push_back(SyncPointCall(component, start, wait_time));
@@ -316,6 +333,27 @@ SyncPoint::reltime_wait_for_all(const string & component, uint wait_sec,
   wait(component, SyncPoint::WAIT_FOR_ALL, wait_sec, wait_nsec);
 }
 
+
+/** Lock the SyncPoint for emitters until the specified component does the next
+ *  wait() call. This forces an emitter of this SyncPoint to wait during the
+ *  emit until the waiter calls wait(). This is useful if you want to guarantee
+ *  that the waiter does not call wait() immediately after the emitter has
+ *  called emit().
+ *  @param component the component locking the SyncPoint
+ */
+void
+SyncPoint::lock_until_next_wait(const string & component)
+{
+  MutexLocker ml(mutex_);
+  if (mutex_next_wait_->try_lock()) {
+    emit_locker_ = component;
+  } else {
+    logger_->log_warn("SyncPoints", "%s tried to call lock_until_next_wait, "
+        "but another component already did the same. Ignoring.",
+        component.c_str());
+  }
+}
+
 /** Register an emitter. A thread can only emit the barrier if it has been
  *  registered.
  *  @param component The identifier of the registering component.
@@ -455,4 +493,15 @@ SyncPoint::handle_default(string component, WakeupType type,
   watchers_wait_for_all_.erase(component);
   watchers_wait_for_one_.erase(component);
 }
+
+void
+SyncPoint::cleanup()
+{
+  delete cond_wait_for_one_;
+  delete mutex_wait_for_one_;
+  delete cond_wait_for_all_;
+  delete mutex_wait_for_all_;
+  delete mutex_next_wait_;
+  delete mutex_;
+}
 } // namespace fawkes
diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h
index 0301766..ab8b2ab 100644
--- a/src/libs/syncpoint/syncpoint.h
+++ b/src/libs/syncpoint/syncpoint.h
@@ -87,6 +87,8 @@ class SyncPoint
     /** unregister as emitter */
     virtual void unregister_emitter(const std::string & component, bool emit_if_pending = true);
 
+    void lock_until_next_wait(const std::string & component);
+
     std::string get_identifier() const;
     bool operator==(const SyncPoint & other) const;
     bool operator==(const std::string & other) const;
@@ -129,10 +131,17 @@ class SyncPoint
 
     /** Mutex used to protect all member variables */
     Mutex *mutex_;
+    /** Mutex used to allow lock_until_next_wait */
+    Mutex *mutex_next_wait_;
+    /** Mutex used for cond_wait_for_one_ */
+    Mutex *mutex_wait_for_one_;
     /** WaitCondition which is used for wait_for_one() */
     WaitCondition *cond_wait_for_one_;
+    /** Mutex used for cond_wait_for_all_ */
+    Mutex *mutex_wait_for_all_;
     /** WaitCondition which is used for wait_for_all() */
     WaitCondition *cond_wait_for_all_;
+
     /** Logger */
     MultiLogger *logger_;
 
@@ -141,6 +150,7 @@ class SyncPoint
     bool is_pending(std::string component);
     void handle_default(std::string component, WakeupType type,
       uint max_time_sec, uint max_time_nsec);
+    void cleanup();
 
   private:
     /** The predecessor SyncPoint, which is the SyncPoint one level up
@@ -156,6 +166,8 @@ class SyncPoint
 
     std::set<std::string> bad_components_;
 
+    std::string emit_locker_;
+
     Time last_emitter_reset_;
 };
 
diff --git a/src/libs/syncpoint/tests/test_syncpoint.cpp b/src/libs/syncpoint/tests/test_syncpoint.cpp
index c539875..ad64e29 100644
--- a/src/libs/syncpoint/tests/test_syncpoint.cpp
+++ b/src/libs/syncpoint/tests/test_syncpoint.cpp
@@ -1012,3 +1012,98 @@ TEST_F(SyncPointManagerTest, RelTimeWaitTest)
   ASSERT_GT(cache_logger_->get_messages().size(), 0);
 
 }
+
+/// @cond INTERNALS
+struct emitter_thread_data {
+    RefPtr<SyncPointManager> manager;
+    std::string name;
+    std::string sp_name;
+};
+/// @endcond
+
+/** helper function to call emit in a thread */
+void * call_emit(void * data)
+{
+  emitter_thread_data * tdata = (emitter_thread_data *) data;
+  RefPtr<SyncPoint> sp = tdata->manager->get_syncpoint(tdata->name, tdata->sp_name);
+  sp->register_emitter(tdata->name);
+  sp->emit(tdata->name);
+  return NULL;
+}
+
+/** Test the functionality of lock_until_next_wait */
+TEST_F(SyncPointManagerTest, LockUntilNextWaitTest)
+{
+  RefPtr<SyncPoint> sp = manager->get_syncpoint("component", "/test");
+
+  sp->lock_until_next_wait("component");
+  pthread_t thread;
+  emitter_thread_data * emitter_params = new emitter_thread_data();
+  emitter_params->manager = manager;
+  emitter_params->name = "emitter";
+  emitter_params->sp_name = "/test";
+  pthread_create(&thread, NULL, call_emit, (void *) emitter_params);
+
+  usleep(2000000);
+
+  EXPECT_EQ(EBUSY, pthread_tryjoin_np(thread, NULL));
+
+  pthread_t waiter_thread;
+  pthread_create(&waiter_thread, NULL, call_wait, (void *) *sp);
+
+  usleep(2000000);
+
+  ASSERT_EQ(0, pthread_tryjoin_np(thread, NULL));
+  ASSERT_EQ(0, pthread_tryjoin_np(waiter_thread, NULL));
+
+  delete emitter_params;
+}
+
+
+/** helper function used for testing wait() */
+void * call_wait_for_all(void *data)
+{
+  SyncPoint * sp = (SyncPoint *)(data);
+  sp->wait_for_all("waiter");
+  return NULL;
+}
+
+/** Test the functionality of lock_until_next_wait
+ *  Test whether the waiter really calls wait before ALL emitters call emit
+ *  This tests a potential race condition between wait() and emit() */
+TEST_F(SyncPointManagerTest, LockUntilNextWaitWaiterComesFirstTest)
+{
+  RefPtr<SyncPoint> sp = manager->get_syncpoint("waiter", "/test");
+
+  sp->lock_until_next_wait("waiter");
+
+  uint num_emitters = 100;
+  pthread_t emitter_thread[num_emitters];
+  emitter_thread_data * params[num_emitters];
+  for (uint i = 0; i < num_emitters; i++) {
+    params[i] = new emitter_thread_data();
+    params[i]->manager = manager;
+    string emitter_name = "emitter" + to_string(i);
+    params[i]->name = emitter_name;
+    params[i]->sp_name = "/test";
+    pthread_create(&emitter_thread[i], NULL, call_emit, (void *) params[i]);
+  }
+
+  usleep(2000000);
+
+  for (uint i = 0; i < num_emitters; i++) {
+    EXPECT_EQ(EBUSY, pthread_tryjoin_np(emitter_thread[i], NULL));
+  }
+
+  pthread_t waiter_thread;
+  pthread_create(&waiter_thread, NULL, call_wait_for_all, (void *) *sp);
+
+  usleep(2000000);
+
+  for (uint i = 0; i < num_emitters; i++) {
+    ASSERT_EQ(0, pthread_tryjoin_np(emitter_thread[i], NULL));
+    delete params[i];
+  }
+
+  ASSERT_EQ(0, pthread_tryjoin_np(waiter_thread, NULL));
+}

- *commit* adbd3195c18ccfe7b226a2bdc46c87de56e63127 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Mon Apr 11 13:53:16 2016 +0200
Subject: baseapp: add a mainloop based on syncpoints to have min/max loop time

 src/libs/baseapp/timing_thread.cpp |  121 ++++++++++++++++++++++++++++++++++++
 src/libs/baseapp/timing_thread.h   |   70 +++++++++++++++++++++
 2 files changed, 191 insertions(+), 0 deletions(-)


- *commit* 75ef4c9845fb8c627a68e7c2cc1b08347031d480 - - - - - - - - - -
Author:  Till Hofmann <hofmann at kbsg.rwth-aachen.de>
Date:    Wed Apr 13 16:13:39 2016 +0200
Subject: libs: add dependency of syncpoint on logging

 src/libs/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

_Diff for modified files_:
diff --git a/src/libs/Makefile b/src/libs/Makefile
index d90e161..bb5a537 100644
--- a/src/libs/Makefile
+++ b/src/libs/Makefile
@@ -65,7 +65,7 @@ endif
 protobuf_clips: core logging protobuf_comm
 pcl_utils: core tf
 kdl_parser: core
-syncpoint: core logging
+syncpoint: core logging utils
 
 include $(BUILDSYSDIR)/rules.mk
 include $(LIBSRCDIR)/extlibs.mk




-- 
Fawkes Robotics Framework                 http://www.fawkesrobotics.org


More information about the fawkes-commits mailing list