Skip to content

Commit

Permalink
Explicit support for acquire_semaphore/release_semaphore in semian re…
Browse files Browse the repository at this point in the history
…sources
  • Loading branch information
kovyrin committed Oct 16, 2024
1 parent 1cf144d commit 8c48b24
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 8 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"files.associations": {
"*.ejson": "jsonc",
"resource.h": "c"
}
}
24 changes: 16 additions & 8 deletions ext/semian/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ID id_timeout;
int system_max_semaphore_count;

static VALUE
cleanup_semian_resource_acquire(VALUE self);
semian_resource_release_semaphore(VALUE self);

static void
check_tickets_xor_quota_arg(VALUE tickets, VALUE quota);
Expand All @@ -33,15 +33,11 @@ static const rb_data_type_t
semian_resource_type;

VALUE
semian_resource_acquire(int argc, VALUE *argv, VALUE self)
semian_resource_acquire_semaphore(int argc, VALUE *argv, VALUE self)
{
semian_resource_t *self_res = NULL;
semian_resource_t res = { 0 };

if (!rb_block_given_p()) {
rb_raise(rb_eArgError, "acquire requires a block");
}

TypedData_Get_Struct(self, semian_resource_t, &semian_resource_type, self_res);
res = *self_res;

Expand Down Expand Up @@ -75,7 +71,19 @@ semian_resource_acquire(int argc, VALUE *argv, VALUE self)
wait_time = LONG2NUM(res.wait_time);
}

return rb_ensure(rb_yield, wait_time, cleanup_semian_resource_acquire, self);
return Qnil;
}

VALUE
semian_resource_acquire(int argc, VALUE *argv, VALUE self)
{
if (!rb_block_given_p()) {
rb_raise(rb_eArgError, "acquire requires a block");
}

semian_resource_acquire_semaphore(argc, argv, self);

return rb_ensure(rb_yield, wait_time, semian_resource_release_semaphore, self);
}

VALUE
Expand Down Expand Up @@ -254,7 +262,7 @@ semian_resource_in_use(VALUE self)
}

static VALUE
cleanup_semian_resource_acquire(VALUE self)
semian_resource_release_semaphore(VALUE self)
{
semian_resource_t *res = NULL;
TypedData_Get_Struct(self, semian_resource_t, &semian_resource_type, res);
Expand Down
29 changes: 29 additions & 0 deletions ext/semian/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,39 @@ semian_resource_initialize(VALUE self, VALUE id, VALUE tickets, VALUE quota, VAL
*
* If no timeout argument is provided, the default timeout passed to Semian.register will be used.
*
* The given block is executed with the semaphore held and, when the block
* exits, the semaphore is automatically released.
*/
VALUE
semian_resource_acquire(int argc, VALUE *argv, VALUE self);

/*
* call-seq:
* resource.acquire_semaphore(timeout: default_timeout) -> nil
*
* Acquires a resource. The call will block for <code>timeout</code> seconds if a ticket
* is not available. If no ticket is available within the timeout period, Semian::TimeoutError
* will be raised.
*
* If no timeout argument is provided, the default timeout passed to Semian.register will be used.
*
* Note: The caller is responsible for releasing the semaphore when done by calling release_semaphore.
*/
VALUE
semian_resource_acquire_semaphore(int argc, VALUE *argv, VALUE self);

/*
* call-seq:
* resource.release_semaphore() -> nil
*
* Releases a resource previously acquired with acquire_semaphore.
*
* Note: The method is NOT idempotent. The caller must ensure that the method is called exactly
* as many times as acquire_semaphore.
*/
VALUE
semian_resource_release_semaphore(VALUE self);

/*
* call-seq:
* resource.destroy() -> true
Expand Down
2 changes: 2 additions & 0 deletions ext/semian/semian.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ void Init_semian()
rb_define_alloc_func(cResource, semian_resource_alloc);
rb_define_method(cResource, "initialize_semaphore", semian_resource_initialize, 5);
rb_define_method(cResource, "acquire", semian_resource_acquire, -1);
rb_define_method(cResource, "acquire_semaphore", semian_resource_acquire_semaphore, 0);
rb_define_method(cResource, "release_semaphore", semian_resource_release_semaphore, 0);
rb_define_method(cResource, "count", semian_resource_count, 0);
rb_define_method(cResource, "semid", semian_resource_id, 0);
rb_define_method(cResource, "key", semian_resource_key, 0);
Expand Down

0 comments on commit 8c48b24

Please sign in to comment.