| 349 | } |
| 350 | |
| 351 | static int id_create_ranged_impl( |
| 352 | bthread_id_t* id, void* data, |
| 353 | int (*on_error)(bthread_id_t, void*, int), |
| 354 | int (*on_error2)(bthread_id_t, void*, int, const std::string&), |
| 355 | int range) { |
| 356 | if (range < 1 || range > ID_MAX_RANGE) { |
| 357 | LOG_IF(FATAL, range < 1) << "range must be positive, actually " << range; |
| 358 | LOG_IF(FATAL, range > ID_MAX_RANGE ) << "max of range is " |
| 359 | << ID_MAX_RANGE << ", actually " << range; |
| 360 | return EINVAL; |
| 361 | } |
| 362 | IdResourceId slot; |
| 363 | Id* const meta = get_resource(&slot); |
| 364 | if (meta) { |
| 365 | meta->data = data; |
| 366 | meta->on_error = on_error; |
| 367 | meta->on_error2 = on_error2; |
| 368 | CHECK(meta->pending_q.empty()); |
| 369 | uint32_t* butex = meta->butex; |
| 370 | if (0 == *butex || *butex + ID_MAX_RANGE + 2 < *butex) { |
| 371 | // Skip 0 so that bthread_id_t is never 0 |
| 372 | // avoid overflow to make comparisons simpler. |
| 373 | *butex = 1; |
| 374 | } |
| 375 | *meta->join_butex = *butex; |
| 376 | meta->first_ver = *butex; |
| 377 | meta->locked_ver = *butex + range; |
| 378 | *id = make_id(*butex, slot); |
| 379 | return 0; |
| 380 | } |
| 381 | return ENOMEM; |
| 382 | } |
| 383 | |
| 384 | } // namespace bthread |
| 385 |
no test coverage detected