1195{
1196 util::Preconditions::check_not_negative(
1197 permits, "permits must not be negative number.");
1198
1199 auto thread_id = get_thread_id();
1200 auto invocation_uid =
1201 get_context().get_hazelcast_client_implementation()->random_uuid();
1202
1203 auto do_try_acquire_once = ([=]() {
1204 auto start = std::chrono::steady_clock::now();
1205 auto use_timeout = timeout >= std::chrono::milliseconds::zero();
1206 auto session_id = session_manager_.acquire_session(group_id_, permits);
1207 auto request =
1208 client::protocol::codec::semaphore_acquire_encode(group_id_,
1209 object_name_,
1210 session_id,
1211 thread_id,
1212 invocation_uid,
1213 permits,
1214 timeout.count());
1215 return client::spi::impl::ClientInvocation::create(
1216 context_, request, object_name_)
1217 ->invoke()
1218 .then(
1219 boost::launch::sync,
1220 [=](boost::future<client::protocol::ClientMessage> f) {
1221 try {
1222 auto acquired = f.get().get_first_fixed_sized_field<bool>();
1223 if (!acquired) {
1224 session_manager_.release_session(group_id_, session_id);
1225 }
1226
1227
1228 return std::make_pair(acquired, false);
1229 } catch (client::exception::session_expired&) {
1230 session_manager_.invalidate_session(group_id_, session_id);
1231 if (use_timeout &&
1232 (timeout - (std::chrono::steady_clock::now() - start) <=
1233 std::chrono::milliseconds::zero())) {
1234 return std::make_pair(false, false);
1235 }
1236 return std::make_pair(false, true);
1237 } catch (client::exception::wait_key_cancelled&) {
1238 session_manager_.release_session(
1239 group_id_, session_id, permits);
1240 if (!use_timeout) {
1241 BOOST_THROW_EXCEPTION(client::exception::illegal_state(
1242 "session_semaphore::try_acquire_for_millis",
1243 (boost::format(
1244 "Semaphore[%1%] not acquired because the acquire "
1245 "call on the CP group is cancelled, possibly "
1246 "because of another indeterminate call from the "
1247 "same thread.") %
1248 object_name_)
1249 .str()));
1250 }
1251 return std::make_pair(false, false);
1252 }
1253 });
1254 });
1255
1256 return do_try_acquire_once().then(
1257 boost::launch::sync, [=](boost::future<std::pair<bool, bool>> f) {
1258 auto result = f.get();
1259 if (!result.second) {
1260 return result.first;
1261 }
1262 for (; result.second; result = do_try_acquire_once().get())
1263 ;
1264 return result.first;
1265 });
1266}