@@ -170,55 +170,71 @@ void SyncedEnforcer ::LoadFilteredPolicy(Filter f) {
170170
171171// SavePolicy saves the current policy (usually after changed with Casbin API) back to file/database.
172172void SyncedEnforcer ::SavePolicy () {
173- std::shared_lock <std::shared_mutex> lock (policyMutex);
173+ std::unique_lock <std::shared_mutex> lock (policyMutex);
174174 Enforcer::SavePolicy ();
175175}
176176
177177// BuildRoleLinks manually rebuild the role inheritance relations.
178178void SyncedEnforcer ::BuildRoleLinks () {
179- std::shared_lock <std::shared_mutex> lock (policyMutex);
179+ std::unique_lock <std::shared_mutex> lock (policyMutex);
180180 Enforcer::BuildRoleLinks ();
181181}
182182
183183// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
184184bool SyncedEnforcer ::Enforce (std::shared_ptr<IEvaluator> evalator) {
185- std::shared_lock <std::shared_mutex> lock (policyMutex);
185+ std::unique_lock <std::shared_mutex> lock (policyMutex);
186186 return Enforcer::Enforce (evalator);
187187}
188188
189189// Enforce with a vector param,decides whether a "subject" can access a
190190// "object" with the operation "action", input parameters are usually: (sub,
191191// obj, act).
192192bool SyncedEnforcer::Enforce (const DataVector& params) {
193- std::shared_lock <std::shared_mutex> lock (policyMutex);
193+ std::unique_lock <std::shared_mutex> lock (policyMutex);
194194 return Enforcer::Enforce (params);
195195}
196196
197197// Enforce with a vector param,decides whether a "subject" can access a
198198// "object" with the operation "action", input parameters are usually: (sub,
199199// obj, act).
200200bool SyncedEnforcer ::Enforce (const DataList& params) {
201- std::shared_lock <std::shared_mutex> lock (policyMutex);
201+ std::unique_lock <std::shared_mutex> lock (policyMutex);
202202 return Enforcer::Enforce (params);
203203}
204204
205205// Enforce with a map param,decides whether a "subject" can access a "object"
206206// with the operation "action", input parameters are usually: (sub, obj, act).
207207bool SyncedEnforcer ::Enforce (const DataMap& params) {
208- std::shared_lock <std::shared_mutex> lock (policyMutex);
208+ std::unique_lock <std::shared_mutex> lock (policyMutex);
209209 return Enforcer::Enforce (params);
210210}
211211
212212// BatchEnforce enforce in batches
213213std::vector<bool > SyncedEnforcer ::BatchEnforce (const std::initializer_list<DataList>& requests) {
214- std::shared_lock<std::shared_mutex> lock (policyMutex);
215- return Enforcer::BatchEnforce (requests);
214+ std::unique_lock<std::shared_mutex> lock (policyMutex);
215+
216+ // note: why not return Enforcer::BatchEnforce(requests) ?
217+ // Inside Enforcer::BatchEnforce, this->Enforce will be executed
218+ // but now 'this' is SyncedEnforcer, which means it will call SyncedEnforcer::Enforce
219+ // This will cause a deadlock
220+
221+ std::vector<bool > results;
222+ results.reserve (requests.size ());
223+ for (const auto & request : requests) {
224+ results.push_back (Enforcer::Enforce (request));
225+ }
226+ return results;
216227}
217228
218229// BatchEnforceWithMatcher enforce with matcher in batches
219230std::vector<bool > SyncedEnforcer::BatchEnforceWithMatcher (const std::string& matcher, const std::initializer_list<DataList>& requests) {
220- std::shared_lock<std::shared_mutex> lock (policyMutex);
221- return Enforcer::BatchEnforceWithMatcher (matcher, requests);
231+ std::unique_lock<std::shared_mutex> lock (policyMutex);
232+ std::vector<bool > results;
233+ results.reserve (requests.size ());
234+ for (const auto & request : requests) {
235+ results.push_back (Enforcer::EnforceWithMatcher (matcher, request));
236+ }
237+ return results;
222238}
223239
224240// GetAllSubjects gets the list of subjects that show up in the current policy.
0 commit comments