File indexing completed on 2025-01-18 10:17:35
0001
0002
0003
0004
0005 #pragma once
0006 #include <JANA/Services/JServiceLocator.h>
0007
0008 class JEventProcessor;
0009
0010 class JLockService : public JService {
0011
0012 public:
0013
0014 JLockService() {
0015 pthread_rwlock_init(&m_rw_locks_lock, nullptr);
0016 pthread_rwlock_init(&m_root_fill_locks_lock, nullptr);
0017 m_app_rw_lock = CreateLock("app");
0018 m_root_rw_lock = CreateLock("root");
0019 }
0020
0021 ~JLockService() override {
0022 for (const auto& pair : m_rw_locks) {
0023 delete pair.second;
0024 }
0025 for (const auto& pair : m_root_fill_rw_lock) {
0026 delete pair.second;
0027 }
0028 }
0029
0030 inline pthread_rwlock_t *CreateLock(const std::string &name, bool throw_exception_if_exists = true);
0031
0032 inline pthread_rwlock_t *ReadLock(const std::string &name);
0033
0034 inline pthread_rwlock_t *WriteLock(const std::string &name);
0035
0036 inline pthread_rwlock_t *Unlock(const std::string &name = std::string("app"));
0037
0038 inline pthread_rwlock_t *RootReadLock() {
0039 pthread_rwlock_rdlock(m_root_rw_lock);
0040 return m_root_rw_lock;
0041 }
0042
0043 inline pthread_rwlock_t *RootWriteLock() {
0044 pthread_rwlock_wrlock(m_root_rw_lock);
0045 return m_root_rw_lock;
0046 }
0047
0048 inline pthread_rwlock_t *RootUnLock() {
0049 pthread_rwlock_unlock(m_root_rw_lock);
0050 return m_root_rw_lock;
0051 }
0052
0053 inline pthread_rwlock_t *RootFillLock(JEventProcessor *proc);
0054
0055 inline pthread_rwlock_t *RootFillUnLock(JEventProcessor *proc);
0056
0057 pthread_rwlock_t* GetReadWriteLock(std::string &name) {
0058 return m_rw_locks.count( name ) == 0 ? nullptr : m_rw_locks[name];
0059 }
0060 pthread_rwlock_t* GetRootReadWriteLock() {
0061 return m_root_rw_lock;
0062 }
0063 pthread_rwlock_t* GetRootFillLock( JEventProcessor *proc ) {
0064 return m_root_fill_rw_lock.count( proc ) == 0 ? nullptr : m_root_fill_rw_lock[proc];
0065 }
0066
0067
0068 private:
0069
0070 std::map<std::string, pthread_rwlock_t *> m_rw_locks;
0071 pthread_rwlock_t *m_app_rw_lock = nullptr;
0072 pthread_rwlock_t *m_root_rw_lock = nullptr;
0073 pthread_rwlock_t m_rw_locks_lock {};
0074 pthread_rwlock_t m_root_fill_locks_lock {};
0075 std::map<JEventProcessor *, pthread_rwlock_t *> m_root_fill_rw_lock;
0076
0077 };
0078
0079 inline pthread_rwlock_t *JLockService::CreateLock(const std::string &name, bool throw_exception_if_exists) {
0080
0081 pthread_rwlock_wrlock(&m_rw_locks_lock);
0082
0083
0084 std::map<std::string, pthread_rwlock_t *>::iterator iter = m_rw_locks.find(name);
0085 pthread_rwlock_t *lock = (iter != m_rw_locks.end() ? iter->second : NULL);
0086
0087 if (lock != NULL) {
0088
0089 if (throw_exception_if_exists) {
0090 pthread_rwlock_unlock(&m_rw_locks_lock);
0091 std::string mess = "Trying to create JANA rw lock \"" + name + "\" when it already exists!";
0092 throw JException(mess);
0093 }
0094 } else {
0095
0096 lock = new pthread_rwlock_t;
0097 pthread_rwlock_init(lock, NULL);
0098 m_rw_locks[name] = lock;
0099 }
0100
0101
0102 pthread_rwlock_unlock(&m_rw_locks_lock);
0103
0104 return lock;
0105 }
0106
0107
0108
0109
0110 inline pthread_rwlock_t *JLockService::ReadLock(const std::string &name) {
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 pthread_rwlock_rdlock(&m_rw_locks_lock);
0124
0125
0126 std::map<std::string, pthread_rwlock_t *>::iterator iter = m_rw_locks.find(name);
0127 pthread_rwlock_t *lock = (iter != m_rw_locks.end() ? iter->second : NULL);
0128
0129
0130 pthread_rwlock_unlock(&m_rw_locks_lock);
0131
0132
0133
0134
0135
0136 if (lock == NULL) lock = CreateLock(name, false);
0137
0138
0139 if (lock != NULL) {
0140 pthread_rwlock_rdlock(lock);
0141 } else {
0142 std::string mess = "Unable to find or create lock \"" + name + "\" for reading!";
0143 throw JException(mess);
0144 }
0145
0146 return lock;
0147 }
0148
0149
0150
0151
0152 inline pthread_rwlock_t *JLockService::WriteLock(const std::string &name) {
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 pthread_rwlock_rdlock(&m_rw_locks_lock);
0166
0167
0168 std::map<std::string, pthread_rwlock_t *>::iterator iter = m_rw_locks.find(name);
0169 pthread_rwlock_t *lock = (iter != m_rw_locks.end() ? iter->second : NULL);
0170
0171
0172 pthread_rwlock_unlock(&m_rw_locks_lock);
0173
0174
0175
0176
0177
0178 if (lock == NULL) lock = CreateLock(name, false);
0179
0180
0181 if (lock != NULL) {
0182 pthread_rwlock_wrlock(lock);
0183 } else {
0184 std::string mess = "Unable to find or create lock \"" + name + "\" for writing!";
0185 throw JException(mess);
0186 }
0187
0188 return lock;
0189 }
0190
0191
0192
0193
0194 inline pthread_rwlock_t *JLockService::Unlock(const std::string &name) {
0195
0196
0197
0198
0199 pthread_rwlock_rdlock(&m_rw_locks_lock);
0200
0201
0202 std::map<std::string, pthread_rwlock_t *>::iterator iter = m_rw_locks.find(name);
0203 pthread_rwlock_t *lock = (iter != m_rw_locks.end() ? iter->second : NULL);
0204
0205
0206 pthread_rwlock_unlock(&m_rw_locks_lock);
0207
0208
0209 if (lock != NULL) {
0210 pthread_rwlock_unlock(lock);
0211 } else {
0212 std::string mess = "Unable to find lock \"" + name + "\" for unlocking!";
0213 throw JException(mess);
0214 }
0215
0216 return lock;
0217 }
0218
0219
0220
0221
0222 inline pthread_rwlock_t *JLockService::RootFillLock(JEventProcessor *proc) {
0223
0224
0225
0226
0227
0228 pthread_rwlock_t *lock;
0229
0230 pthread_rwlock_rdlock(&m_root_fill_locks_lock);
0231 auto iter = m_root_fill_rw_lock.find(proc);
0232 if (iter == m_root_fill_rw_lock.end()) {
0233 pthread_rwlock_unlock(&m_root_fill_locks_lock);
0234 pthread_rwlock_wrlock(&m_root_fill_locks_lock);
0235 auto iter_now = m_root_fill_rw_lock.find(proc);
0236 if(iter_now == m_root_fill_rw_lock.end()){
0237 lock = new pthread_rwlock_t;
0238 pthread_rwlock_init(lock, nullptr);
0239 m_root_fill_rw_lock[proc] = lock;
0240 }
0241 else{
0242 lock = iter_now->second;
0243 }
0244 }
0245 else {
0246 lock = iter->second;
0247 }
0248 pthread_rwlock_unlock(&m_root_fill_locks_lock);
0249 pthread_rwlock_wrlock(lock);
0250 return lock;
0251 }
0252
0253
0254
0255
0256 inline pthread_rwlock_t *JLockService::RootFillUnLock(JEventProcessor *proc) {
0257
0258
0259
0260
0261
0262 pthread_rwlock_rdlock(&m_root_fill_locks_lock);
0263 std::map<JEventProcessor *, pthread_rwlock_t *>::iterator iter = m_root_fill_rw_lock.find(proc);
0264 if (iter == m_root_fill_rw_lock.end()) {
0265 pthread_rwlock_unlock(&m_root_fill_locks_lock);
0266 throw JException(
0267 "Tried calling JLockService::RootFillUnLock with something other than a registered JEventProcessor!");
0268 }
0269 pthread_rwlock_t *lock = iter->second;
0270 pthread_rwlock_unlock(&m_root_fill_locks_lock);
0271 pthread_rwlock_unlock(lock);
0272 return lock;
0273 }
0274
0275