Skip to content

Commit

Permalink
Add support for unregister/1
Browse files Browse the repository at this point in the history
Closes issue atomvm#358.

Signed-off-by: Winford <dwinford@pm.me>
  • Loading branch information
Winford committed Oct 22, 2022
1 parent 2cb3df3 commit 40cc0dd
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `erlang:is_boolean/1` Bif.
- Added support for `esp:partition_erase_range/2`
- Added support for `i2c:close/1`
- Added `erlang:is_boolean/1` Bif.
- Added support for `esp:partition_erase_range/2`
- Added support for `i2c:close/1`
- Added support for `unregister/1`

### Breaking Changes

Expand Down
22 changes: 22 additions & 0 deletions src/libAtomVM/globalcontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,28 @@ void globalcontext_register_process(GlobalContext *glb, int atom_index, int loca
linkedlist_append(&glb->registered_processes, &registered_process->registered_processes_list_head);
}

bool globalcontext_unregister_process(GlobalContext *glb, int atom_index)
{
if (!glb->registered_processes) {
return false;
}

struct RegisteredProcess *registered_processes = GET_LIST_ENTRY(glb->registered_processes, struct RegisteredProcess, registered_processes_list_head);

struct RegisteredProcess *p = registered_processes;

do {
if (p->atom_index == atom_index) {
linkedlist_remove(&glb->registered_processes, &p->registered_processes_list_head);
free(p);
return true;
}
p = GET_LIST_ENTRY(p->registered_processes_list_head.next, struct RegisteredProcess, registered_processes_list_head);
} while (p != registered_processes);

return false;
}

int globalcontext_get_registered_process(GlobalContext *glb, int atom_index)
{
if (!glb->registered_processes) {
Expand Down
9 changes: 9 additions & 0 deletions src/libAtomVM/globalcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ void globalcontext_register_process(GlobalContext *glb, int atom_index, int loca
*/
int globalcontext_get_registered_process(GlobalContext *glb, int atom_index);

/**
* @brief Unregister a process
*
* @details Unregister a process with a certain name (atom).
* @param glb the global context, each registered process will be globally available for that context.
* @param atom_index the atom table index.
*/
bool globalcontext_unregister_process(GlobalContext *glb, int atom_index);

/**
* @brief equivalent to globalcontext_insert_atom_maybe_copy(glb, atom_string, 0);
*/
Expand Down
35 changes: 28 additions & 7 deletions src/libAtomVM/nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ static term nif_erlang_iolist_size_1(Context *ctx, int argc, term argv[]);
static term nif_erlang_iolist_to_binary_1(Context *ctx, int argc, term argv[]);
static term nif_erlang_open_port_2(Context *ctx, int argc, term argv[]);
static term nif_erlang_register_2(Context *ctx, int argc, term argv[]);
static term nif_erlang_unregister_1(Context *ctx, int argc, term argv[]);
static term nif_erlang_send_2(Context *ctx, int argc, term argv[]);
static term nif_erlang_setelement_3(Context *ctx, int argc, term argv[]);
static term nif_erlang_spawn(Context *ctx, int argc, term argv[]);
Expand Down Expand Up @@ -364,6 +365,12 @@ static const struct Nif register_nif =
.nif_ptr = nif_erlang_register_2
};

static const struct Nif unregister_nif =
{
.base.type = NIFFunctionType,
.nif_ptr = nif_erlang_unregister_1
};

static const struct Nif spawn_nif =
{
.base.type = NIFFunctionType,
Expand Down Expand Up @@ -762,13 +769,10 @@ static term nif_erlang_register_2(Context *ctx, int argc, term argv[])
int atom_index = term_to_atom_index(reg_name_term);
int32_t pid = term_to_local_process_id(pid_or_port_term);

// pid must be existing, not already registered.
if (UNLIKELY(globalcontext_get_process(ctx->global, pid) == NULL)){
RAISE_ERROR(BADARG_ATOM);
} else if (UNLIKELY(globalcontext_get_registered_process(ctx->global, atom_index) != 0)) {
RAISE_ERROR(BADARG_ATOM);
// reg_name_term must not be the atom undefined.
} else if (UNLIKELY(atom_index == UNDEFINED_ATOM_INDEX)) {
// pid must be existing, not already registered, and not the atom undefined.
if (UNLIKELY(globalcontext_get_process(ctx->global, pid) == NULL) ||
globalcontext_get_registered_process(ctx->global, atom_index) != 0 ||
reg_name_term == UNDEFINED_ATOM){
RAISE_ERROR(BADARG_ATOM);
}

Expand All @@ -777,6 +781,23 @@ static term nif_erlang_register_2(Context *ctx, int argc, term argv[])
return TRUE_ATOM;
}

static term nif_erlang_unregister_1(Context *ctx, int argc, term argv[])
{
UNUSED(argc);

term reg_name_term = argv[0];
VALIDATE_VALUE(reg_name_term, term_is_atom);

int atom_index = term_to_atom_index(reg_name_term);

bool unregistered = globalcontext_unregister_process(ctx->global, atom_index);
if (UNLIKELY(!unregistered)) {
RAISE_ERROR(BADARG_ATOM);
}

return TRUE_ATOM;
}

static term nif_erlang_whereis_1(Context *ctx, int argc, term argv[])
{
UNUSED(argc);
Expand Down
1 change: 1 addition & 0 deletions src/libAtomVM/nifs.gperf
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ erlang:monitor/2, &monitor_nif
erlang:demonitor/1, &demonitor_nif
erlang:is_process_alive/1, &is_process_alive_nif
erlang:register/2, &register_nif
erlang:unregister/1, &unregister_nif
erlang:send/2, &send_nif
erlang:setelement/3, &setelement_nif
erlang:spawn/1, &spawn_fun_nif
Expand Down

0 comments on commit 40cc0dd

Please sign in to comment.