Skip to content

Commit

Permalink
Merge pull request #11 from x0id/capacity
Browse files Browse the repository at this point in the history
Add capacity functions
  • Loading branch information
saleyn authored Feb 26, 2024
2 parents 1185069 + a83daac commit 44129da
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 15 deletions.
38 changes: 29 additions & 9 deletions c_src/sema_nif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <atomic>
#include <mutex>
#include <map>
#include <cassert>

#ifdef TRACE
#include <iostream>
Expand Down Expand Up @@ -99,6 +100,9 @@ struct sema {
return map_ret;
}

unsigned capacity() const { return max; }
unsigned capacity(unsigned n) { auto old=max; max=n; return old; }

ERL_NIF_TERM try_to_take(ErlNifEnv *env, const ErlNifPid& pid, unsigned n) {
unsigned x = cnt.load(std::memory_order_relaxed);
while (x + n <= max) {
Expand Down Expand Up @@ -272,8 +276,7 @@ create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {

static ERL_NIF_TERM
info(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
if (argc != 1)
return enif_make_badarg(env);
assert(argc == 1);

sema *res = nullptr;
if (!enif_get_resource(env, argv[0], SEMA, (void **)&res))
Expand All @@ -285,6 +288,21 @@ info(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
return res->info(env);
}

static ERL_NIF_TERM
capacity(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
assert(argc >= 1 && argc <= 2);

sema *res = nullptr;
if (!enif_get_resource(env, argv[0], SEMA, (void **)&res) || !res)
return enif_make_badarg(env);

unsigned max = 0;
if (argc == 2 && !enif_get_uint(env, argv[1], &max))
return enif_make_badarg(env);

return enif_make_uint(env, argc == 2 ? res->capacity(max) : res->capacity());
}

static ERL_NIF_TERM
acquire(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
if (argc < 1 || argc > 2)
Expand Down Expand Up @@ -357,13 +375,15 @@ release(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
}

static ErlNifFunc nif_funcs[] = {
{"create", 1, create},
{"info", 1, info},
{"acquire", 1, acquire},
{"acquire", 2, acquire},
{"release", 1, release},
{"release", 2, release},
{"release", 3, release}
{"create", 1, create},
{"info", 1, info},
{"capacity", 1, capacity},
{"capacity", 2, capacity},
{"acquire", 1, acquire},
{"acquire", 2, acquire},
{"release", 1, release},
{"release", 2, release},
{"release", 3, release}
};

ERL_NIF_INIT(sema_nif, nif_funcs, &load, nullptr, nullptr, nullptr);
26 changes: 20 additions & 6 deletions src/sema_nif.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
-export([
create/1,
info/1,
capacity/1,
capacity/2,
acquire/1,
acquire/2,
release/1,
Expand All @@ -13,6 +15,8 @@
-nifs([
create/1,
info/1,
capacity/1,
capacity/2,
acquire/1,
acquire/2,
release/1,
Expand Down Expand Up @@ -41,10 +45,11 @@

-export_type([sema_ref/0, acquire_ret/0, release_ret/0]).

% @doc Create a new semaphore with the given capacity
-spec create(Max :: pos_integer()) -> sema_ref().
create(_) -> not_loaded(?LINE).

% get internal properties of the semaphore resource
% @doc Get internal properties of the semaphore resource
-spec info(Semaphore :: sema_ref()) ->
#{
% number of units acquired
Expand All @@ -56,23 +61,32 @@ create(_) -> not_loaded(?LINE).
}.
info(_) -> not_loaded(?LINE).

% acquire resource unit for calling process, monitor process
% @doc Get semaphore maximum capacity
-spec capacity(Semaphore :: sema_ref()) -> pos_integer().
capacity(_) -> not_loaded(?LINE).

% @doc Set semaphore maximum capacity.
% Return old capacity.
-spec capacity(Semaphore :: sema_ref(), Max :: integer()) -> pos_integer().
capacity(_, _Max) -> not_loaded(?LINE).

% @doc Acquire resource unit for calling process, monitor process
-spec acquire(Semaphore :: sema_ref()) -> Ret :: acquire_ret().
acquire(_) -> not_loaded(?LINE).

% acquire resource Cnt units for calling process, monitor process
% @doc Acquire resource Cnt units for calling process, monitor process
-spec acquire(Semaphore :: sema_ref(), Cnt :: pos_integer()) -> Ret :: acquire_ret().
acquire(_, _) -> not_loaded(?LINE).

% release resource unit acquired by calling process
% @doc Release resource unit acquired by calling process
-spec release(Semaphore :: sema_ref()) -> Ret :: release_ret().
release(_) -> not_loaded(?LINE).

% release resource unit(s) acquired by calling/another process
% @doc Release resource unit(s) acquired by calling/another process
-spec release(Semaphore :: sema_ref(), Arg :: pos_integer() | pid()) -> Ret :: release_ret().
release(_, _) -> not_loaded(?LINE).

% release resource units acquired by another process
% @doc Release resource units acquired by another process
-spec release(Semaphore :: sema_ref(), Cnt :: pos_integer(), Pid :: pid()) -> Ret :: release_ret().
release(_, _, _) -> not_loaded(?LINE).

Expand Down
3 changes: 3 additions & 0 deletions test/sema_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ basic_api_test() ->
?assertError(badarg, sema_nif:create(-1)),

S = sema_nif:create(3),
?assertEqual(3, sema_nif:capacity(S)),
?assertEqual(#{cnt => 0, dead => 0, max => 3}, sema_nif:info(S)),

?assertEqual({ok, 1}, sema_nif:acquire(S)),
Expand Down Expand Up @@ -65,6 +66,8 @@ basic_api_test() ->
?assertEqual({ok, 0}, sema_nif:release(S, 2)),
?assertEqual(#{cnt => 0, dead => 0, max => 3}, sema_nif:info(S)),

?assertEqual(3, sema_nif:capacity(S, 5)),
?assertEqual(5, sema_nif:capacity(S)),
ok.

gc_test() ->
Expand Down

0 comments on commit 44129da

Please sign in to comment.