Skip to content

Commit e85c6fe

Browse files
authored
Merge pull request #28 from vetlewi/dev
Changed the version of the Histogram library to 2.0.0
2 parents 16aa40a + 0ac6da0 commit e85c6fe

24 files changed

+845
-200
lines changed

CMakeLists.txt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required(VERSION 3.15)
2-
project(XIA2tree VERSION 1.2.1 LANGUAGES C CXX)
2+
project(XIA2tree VERSION 1.3.0 LANGUAGES C CXX)
33

44
# Default to the project version when git information is unavailable
55
set(FULL_VERSION "${PROJECT_VERSION}")
@@ -18,7 +18,7 @@ CPMAddPackage("gh:TheLartians/PackageProject.cmake@1.13.0")
1818
find_package(Threads REQUIRED)
1919
find_package(ROOT REQUIRED COMPONENTS RIO Tree Hist)
2020

21-
CPMAddPackage("gh:vetlewi/Histogram@1.3.3")
21+
CPMAddPackage("gh:vetlewi/Histogram@2.0.0")
2222

2323
add_library(structopt INTERFACE)
2424
target_include_directories(structopt
@@ -88,6 +88,7 @@ add_library(XIAfuncs
8888
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Buffer.cpp
8989
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Calibrator.cpp
9090
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/MemoryMap.cpp
91+
#${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Sort.cpp
9192
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/MTSort.cpp
9293
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Splitter.cpp
9394
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Trigger.cpp
@@ -125,19 +126,23 @@ target_include_directories(UserSort
125126

126127
target_link_libraries(UserSort PRIVATE XIAfuncs)
127128

128-
set_target_properties(UserSort PROPERTIES CXX_STANDARD 17)
129+
set_target_properties(UserSort PROPERTIES CXX_STANDARD 20)
130+
set_target_properties(UserSort PROPERTIES POSITION_INDEPENDENT_CODE ON)
129131
add_library(OCL::UserSort ALIAS UserSort)
130132

131133
add_library(ParticleCoincidenceSort MODULE ParticleCoincidenceSort.cpp)
134+
set_target_properties(ParticleCoincidenceSort PROPERTIES POSITION_INDEPENDENT_CODE ON)
132135
target_link_libraries(ParticleCoincidenceSort PUBLIC OCL::UserSort)
133136

134137
add_library(Co60CoincidenceSort MODULE Co60_coincidence_sort.cpp)
138+
set_target_properties(Co60CoincidenceSort PROPERTIES POSITION_INDEPENDENT_CODE ON)
135139
target_link_libraries(Co60CoincidenceSort PUBLIC OCL::UserSort)
136140

137141
add_library(TimingInvestigation MODULE TimingInvestigation.cpp)
142+
set_target_properties(TimingInvestigation PROPERTIES POSITION_INDEPENDENT_CODE ON)
138143
target_link_libraries(TimingInvestigation PUBLIC OCL::UserSort)
139144

140-
set_target_properties(XIAfuncs PROPERTIES CXX_STANDARD 17)
145+
set_target_properties(XIAfuncs PROPERTIES CXX_STANDARD 20)
141146
target_link_libraries(XIAfuncs
142147
PUBLIC
143148
OCL::Histogram
@@ -157,7 +162,7 @@ target_link_libraries(Co60CoincidenceSort PRIVATE OCL::Histogram XIAfuncs UserSo
157162
target_link_libraries(TimingInvestigation PRIVATE OCL::Histogram XIAfuncs UserSort)
158163

159164
add_executable(XIA2tree main.cpp)
160-
set_target_properties(XIA2tree PROPERTIES CXX_STANDARD 17)
165+
set_target_properties(XIA2tree PROPERTIES CXX_STANDARD 20)
161166
target_link_libraries(XIA2tree PRIVATE OCL::Histogram UserSort XIAfuncs readerwriterqueue concurrentqueue)
162167
add_dependencies(XIA2tree ParticleCoincidenceSort)
163168

Co60_coincidence_sort.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class Co60CoincidenceSort : public UserSort
1818
public:
1919
Co60CoincidenceSort(ThreadSafeHistograms *hist);
2020
void FillEvent(const Triggered_event &event) override;
21-
void Flush() override;
2221
};
2322

2423

@@ -69,11 +68,4 @@ void Co60CoincidenceSort::FillEvent(const Triggered_event &event)
6968
}
7069
}
7170

72-
}
73-
74-
void Co60CoincidenceSort::Flush()
75-
{
76-
gamgam.force_flush();
77-
time_labr_fine.force_flush();
78-
timediff_de.force_flush();
7971
}

ParticleCoincidenceSort.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ class ParticleCoincidence : public UserSort
4646
ParticleCoincidence(ThreadSafeHistograms *hist, const OCL::UserConfiguration *user_config);
4747
~ParticleCoincidence() override = default;
4848
void FillEvent(const Triggered_event &event) override;
49-
void Flush() override;
5049

5150
};
5251

@@ -151,20 +150,4 @@ void ParticleCoincidence::FillEvent(const Triggered_event &event)
151150
}
152151
}
153152
}
154-
155-
}
156-
157-
void ParticleCoincidence::Flush()
158-
{
159-
de_thickness.force_flush();
160-
particle_energy.force_flush();
161-
excitation_energy.force_flush();
162-
exgam.force_flush();
163-
exgam_full.force_flush();
164-
gamgam.force_flush();
165-
part_gamgam.force_flush();
166-
sum_ex_gam.force_flush();
167-
gam_part_time.force_flush();
168-
std::cout << "Average thickness: " << thickness << std::endl;
169-
std::cout << "Counts: " << counts << std::endl;
170153
}

TimingInvestigation.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ class TimingInvestigation : public UserSort
3939
public:
4040
TimingInvestigation(ThreadSafeHistograms *hist);
4141
void FillEvent(const Triggered_event &event) override;
42-
void Flush() override;
4342

4443
};
4544

@@ -352,17 +351,4 @@ void TimingInvestigation::FillEvent(const Triggered_event &event)
352351
}*/
353352
}
354353
}
355-
}
356-
357-
void TimingInvestigation::Flush()
358-
{
359-
gamgam_time.force_flush();
360-
for ( auto &m : de_time_energy )
361-
m.force_flush();
362-
for ( auto &m : e_time_energy )
363-
m.force_flush();
364-
range.force_flush();
365-
gamgam_satelite.force_flush();
366-
gamgam_prompt.force_flush();
367-
gamgam_prompt_satelite.force_flush();
368354
}

include/Format/entry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct Entry_t {
2626
bool cfdfail;
2727

2828
// QDC values
29-
std::vector<uint32_t> qdc{0};
29+
std::array<uint32_t, 8> qdc{0};
3030

3131
// Traces
3232
std::vector<uint16_t> trace{0};

include/Format/xiaformat.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#ifndef XIAFORMAT_H
66
#define XIAFORMAT_H
7+
#include <array>
78

89
struct XIA_event_4_t;
910
struct XIA_event_6_t;
@@ -118,7 +119,7 @@ struct XIA_event_18_t : public XIA_base_t {
118119
uint16_t trace[];
119120
};
120121

121-
inline std::vector<uint32_t> getQDC(const XIA_base_t *event) {
122+
/*inline std::vector<uint32_t> getQDC(const XIA_base_t *event) {
122123
switch ( event->headerLen ) {
123124
case 12 :
124125
return {reinterpret_cast<const XIA_event_12_t *>(event)->qdc,
@@ -135,6 +136,27 @@ inline std::vector<uint32_t> getQDC(const XIA_base_t *event) {
135136
default:
136137
return std::vector<uint32_t>(0);
137138
}
139+
}*/
140+
141+
inline std::array<uint32_t, 8> getQDC(const XIA_base_t *event) {
142+
const uint32_t* qdc = nullptr;
143+
switch ( event->headerLen ) {
144+
case 12 :
145+
qdc = reinterpret_cast<const XIA_event_12_t *>(event)->qdc;
146+
break;
147+
case 14 :
148+
qdc = reinterpret_cast<const XIA_event_14_t *>(event)->qdc;
149+
break;
150+
case 16 :
151+
qdc = reinterpret_cast<const XIA_event_16_t *>(event)->qdc;
152+
break;
153+
case 18 :
154+
qdc = reinterpret_cast<const XIA_event_18_t *>(event)->qdc;
155+
break;
156+
default:
157+
return {};
158+
}
159+
return {qdc[0], qdc[1], qdc[2], qdc[3], qdc[4], qdc[5], qdc[6], qdc[7]};
138160
}
139161

140162
inline std::vector<uint16_t> getTrace(const XIA_base_t *event) {

include/RootInterface/TTreeManager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <TFile.h>
99
#include <TTree.h>
10+
#include <Compression.h>
1011

1112
#include <entry.h>
1213
#include <event.h>
@@ -28,7 +29,7 @@ namespace Task {
2829
bool cfdfail;
2930
double cfdcorr;
3031
unsigned short idx; //!< Index in list of detectors that the trigger corresponds to.
31-
std::vector<uint32_t> qdc;
32+
std::array<uint32_t, 8> qdc;
3233

3334
public:
3435
explicit TriggerEntry(TTree &tree);

include/Tasks/MTSort.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ namespace Task {
102102
class MTSort : public Base
103103
{
104104
private:
105-
TEventQueue_t &input_queue;
105+
MTEventQueue_t &input_queue;
106106
HistManager hm;
107107
const OCL::UserConfiguration& userConfig;
108108
std::unique_ptr<ROOT::TTreeManager> tree;
109109

110110
public:
111-
MTSort(TEventQueue_t &input, ThreadSafeHistograms &histograms, const OCL::UserConfiguration &config,
111+
MTSort(MTEventQueue_t &input, ThreadSafeHistograms &histograms, const OCL::UserConfiguration &config,
112112
const char *tree_name = nullptr, const char *user_sort = nullptr);
113113
~MTSort() override = default;
114114
void Run() override;
@@ -118,7 +118,7 @@ namespace Task {
118118
class Sorters
119119
{
120120
private:
121-
TEventQueue_t &input_queue;
121+
MTEventQueue_t &input_queue;
122122
ThreadSafeHistograms histograms;
123123
std::vector<MTSort *> sorters;
124124
const OCL::UserConfiguration &user_config;
@@ -127,7 +127,7 @@ namespace Task {
127127
std::vector<std::string> tree_files; //! To be returned to the user when everything is said and done.
128128

129129
public:
130-
Sorters(TEventQueue_t &input, OCL::UserConfiguration &config, const char *tree_name = nullptr, const char *user_sort = nullptr);
130+
Sorters(MTEventQueue_t &input, OCL::UserConfiguration &config, const char *tree_name = nullptr, const char *user_sort = nullptr);
131131
~Sorters();
132132
void flush();
133133
Histograms &GetHistograms(){

include/Tasks/Queue.h

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,64 +5,28 @@
55
#ifndef QUEUE_H
66
#define QUEUE_H
77

8-
#include <atomic>
98

109
#include <Format/entry.h>
1110
#include <Format/event.h>
1211
#include <Format/xiaformat.h>
1312

14-
#include <readerwriterqueue.h>
15-
#include <blockingconcurrentqueue.h>
16-
#include <readerwritercircularbuffer.h>
17-
#include <concurrentqueue.h>
18-
19-
namespace Task {
20-
21-
template<typename T>
22-
struct QueueWrapper
23-
{
24-
T queue;
25-
std::atomic<bool> done;
26-
27-
template<typename U>
28-
inline bool try_enqueue(U const &u){ return queue.try_enqueue(u); }
29-
30-
template<typename U>
31-
inline bool try_enqueue(U &&u){ return queue.try_enqueue(u); }
32-
33-
template<typename U>
34-
inline auto enqueue(U const &u){ return queue.enqueue(u); }
13+
#include "SPSCQueue.h"
14+
#include "SPMCQueue.h"
3515

36-
template<typename U>
37-
inline auto enqueue(U &&u){ return queue.enqueue(u); }
38-
39-
template<typename U>
40-
inline void wait_enqueue(U const &u){ queue.wait_enqueue(u); }
41-
42-
template<typename U>
43-
inline void wait_enqueue(U &&u){ queue.wait_enqueue(u); }
44-
45-
/*template <typename U, typename V>
46-
inline bool wait_enqueue_timed(U &u, V const &v){ return queue.wait_enqueue(u); }
47-
48-
template <typename U, typename V>
49-
inline bool wait_enqueue_timed(U &&u, V const &v){ return queue.wait_enqueue(u); }
16+
#include <blockingconcurrentqueue.h>
5017

51-
template<typename U, typename V>
52-
inline bool wait_dequeue_timed(U &u, V const &v){ return queue.wait_dequeue_timed(u, v); }*/
18+
//#define SIZE 16384
19+
#define SIZE 2048
20+
//#define SIZE 32
5321

54-
QueueWrapper(const size_t &capacity) : queue( capacity ), done( false ){}
55-
};
22+
namespace Task {
5623

57-
//using EntryQueue_t = QueueWrapper<moodycamel::BlockingReaderWriterCircularBuffer<entry_t>>;
58-
using XIAQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<const XIA_base_t *>;
59-
//using XIAQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<XIA_base_t>;
60-
using EntryQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<Entry_t>;
61-
using EventQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<std::vector<Entry_t>>;
62-
//using TEventQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<std::pair<std::vector<Entry_t>, size_t>>;
63-
using MCEventQueue_t = moodycamel::BlockingConcurrentQueue<std::vector<Entry_t>>;
64-
using TEventQueue_t = moodycamel::BlockingConcurrentQueue<std::pair<std::vector<Entry_t>, size_t>>;
65-
//using TEventQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<Triggered_event>;
24+
using XIAQueue_t = SPSCBlockingQueue<const XIA_base_t *, SIZE>;
25+
using EntryQueue_t = SPSCBlockingQueue<Entry_t, SIZE>;
26+
using EventQueue_t = SPSCBlockingQueue<std::vector<Entry_t>, SIZE>;
27+
using MCEventQueue_t = SPSCBlockingQueue<std::vector<Entry_t>, SIZE>;
28+
using TEventQueue_t = SPSCBlockingQueue<std::pair<std::vector<Entry_t>, int>, SIZE>;
29+
using MTEventQueue_t = moodycamel::BlockingConcurrentQueue<std::pair<std::vector<Entry_t>, int>>;
6630
}
6731

6832
#endif // QUEUE_H

include/Tasks/SPMCQueue.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <atomic>
2+
#include <array>
3+
#include <optional>
4+
#include <thread>
5+
#include <cstddef>
6+
7+
template<typename T, size_t Capacity>
8+
class SPMCBlockingQueue
9+
{
10+
static_assert((Capacity & (Capacity - 1)) == 0,
11+
"Capacity must be power of two");
12+
13+
private:
14+
15+
static constexpr size_t MASK = Capacity - 1;
16+
17+
alignas(64) std::array<T, Capacity> buffer;
18+
19+
alignas(64) std::atomic<size_t> read_index{0};
20+
alignas(64) std::atomic<size_t> write_index{0};
21+
22+
bool is_finish = false;
23+
24+
public:
25+
26+
bool empty() const
27+
{
28+
return write_index.load(std::memory_order_acquire) ==
29+
read_index.load(std::memory_order_acquire);
30+
}
31+
32+
// Single producer (blocking when full)
33+
void push(T value)
34+
{
35+
size_t w;
36+
37+
while (true)
38+
{
39+
w = write_index.load(std::memory_order_relaxed);
40+
size_t r = read_index.load(std::memory_order_acquire);
41+
42+
if (w - r < Capacity)
43+
break;
44+
45+
std::this_thread::yield(); // queue full
46+
}
47+
48+
buffer[w & MASK] = std::move(value);
49+
50+
write_index.store(w + 1, std::memory_order_release);
51+
}
52+
53+
// Multiple consumers
54+
std::optional<T> pop()
55+
{
56+
while (true)
57+
{
58+
size_t r = read_index.load(std::memory_order_relaxed);
59+
size_t w = write_index.load(std::memory_order_acquire);
60+
61+
if (r == w)
62+
return std::nullopt;
63+
64+
if (read_index.compare_exchange_weak(
65+
r,
66+
r + 1,
67+
std::memory_order_acq_rel,
68+
std::memory_order_relaxed))
69+
{
70+
T value = std::move(buffer[r & MASK]);
71+
return value;
72+
}
73+
}
74+
}
75+
76+
void mark_as_finish(){ is_finish = true; }
77+
bool is_not_finish() const { return !is_finish; }
78+
};

0 commit comments

Comments
 (0)