Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
namespaces.h File Reference

A namespace is an isolation for names nad technically a compilation unit. More...

#include <stdatomic.h>
#include "serene/rt/context.h"
#include "serene/rt/engine.h"
#include "serene/rt/impl/hashmap.h"
#include "serene/rt/source_manager.h"
#include "serene/utils.h"
Include dependency graph for namespaces.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  srn_namespace_t

Typedefs

typedef struct srn_namespace_t srn_namespace_t

Functions

srn_namespace_t * srn_namespace_get_or_create (srn_engine_t *engine, srn_string_t *name, srn_error_t **err)
 Create a new and empty namespace if it is not already created in the engine, if it exists, return the namespace.
srn_namespace_t * srn_namespace_load (srn_namespace_t *ns)
 Load the namespace's source from the filesystem into src_buffer, parse it, and populate the symbol table.

Detailed Description

A namespace is an isolation for names nad technically a compilation unit.

Typically each namespace will resolve to a single file on the filesystem. Namespaces maintain a sym table that maps global names that the namespace provides to their definition.

Definition in file namespaces.h.

Typedef Documentation

◆ srn_namespace_t

typedef struct srn_namespace_t srn_namespace_t

Function Documentation

◆ srn_namespace_get_or_create()

srn_namespace_t * srn_namespace_get_or_create ( srn_engine_t * engine,
srn_string_t * name,
srn_error_t ** err )

Create a new and empty namespace if it is not already created in the engine, if it exists, return the namespace.

Note that in case of creation, this function will register the new namespace with the engine.

Definition at line 30 of file namespaces.c.

30 {
31 PANIC_IF_NULL(engine);
32 PANIC_IF_NULL(name);
33 // TODO(lxsameer): Return these panics as errors. This is fine for now!
34 UNUSED(err);
35 PANIC_IF(srn_string_is_empty(name), "Empty namespace name is not allowed");
38 "Namespace name exceeds the length limit"
39 );
40 srn_context_t *parent_ctx = engine->root_context;
41
42 // The key is the raw bytes of the namespace name (no struct header,
43 // no null terminator). The map copies the key into its pinned context, so
44 // a stack struct is enough here. Find by C string must use the same byte
45 // range as the key.
46 hmap_key_t k = {.data = (void *)name->buffer, .len = srn_string_length(name)};
47
48 // Readers never take `ns_lock`. Every published head is immutable, so an
49 // acquire load is enough to see a fully built map.
50 auto namespaces = atomic_load_explicit(&engine->namespaces, memory_order_acquire);
51 auto ns_ptr = srn_context_find_namespace(parent_ctx, (const char *)name->buffer);
52
53 if (ns_ptr != nullptr) {
54 // A namespace with the same name is already registered.
55 return (srn_namespace_t *)ns_ptr;
56 }
57
58 srn_namespace_t *ns = nullptr;
59
60 // Writers are serialized by `ns_lock`. Creating and publishing the
61 // namespace both happen while it is held.
62 WITH_LOCK(engine->ns_lock, {
63 // Another fiber may have registered the same name between the unlocked
64 // lookup and taking the lock, so the lookup is repeated here.
65 namespaces = atomic_load_explicit(&engine->namespaces, memory_order_relaxed);
66 ns = hmap_lookup(namespaces, &k, nullptr);
67
68 if (ns == nullptr) {
69 ns = ALLOC_OR_PANIC(parent_ctx, srn_namespace_t);
70 ns->name = srn_string_copy(parent_ctx, name);
71 ns->id = srn_allocate_object_id(engine);
72 ns->root_context = srn_context_make(engine);
73
74 // The symbol table outlives the creating context, so it is pinned to the
75 // namespace's own root context; the table's keys and trie nodes land in
76 // that chain rather than in the creating caller's block. The namespace
77 // is not visible to anyone yet, so the atomic is initialized rather
78 // than stored.
79 hmap_t *sym_table = ALLOC_OR_PANIC(ns->root_context, hmap_t);
80 *sym_table = hmap_empty(ns->root_context);
81 atomic_init(&ns->sym_table, sym_table);
82 // No node to begin with
83 ns->node = nullptr;
84
85 ns->sym_table_lock = ALLOC_OR_PANIC(ns->root_context, srn_fiber_mutex_t);
86 srn_fiber_mutex_init(ns->sym_table_lock);
87
88 // Every head is immutable once published, so the new version gets its
89 // own allocation and the old one stays valid for readers that already
90 // loaded it.
91 hmap_t *next = ALLOC_OR_PANIC(parent_ctx, hmap_t);
92 *next = hmap_insert(namespaces, &k, ns);
93
94 atomic_store_explicit(&engine->namespaces, next, memory_order_release);
95 }
96 });
97
98 return ns;
99}
#define WITH_LOCK(lock, body)
Run body with lock held.
Definition mutex.h:84
size_t srn_string_length(const srn_string_t *s)
Definition strings.c:34
bool srn_string_is_empty(const srn_string_t *s)
Definition strings.c:49
Note: For key equality we use the memcpy function.
Definition hashmap.h:66
srn_limits_config_t limits
srn_configuration_t config
The runtime's tunable knobs, the single source for every configurable value (see configuration....
Definition engine.h:65
size_t ns_name_max_len
Longest namespace name accepted, in bytes.
uint8_t buffer[]
The buffer that holds the WTF8 sequence.
Definition strings.h:66
#define PANIC_IF_NULL(ptr)
Definition utils.h:66
#define PANIC_IF(cond, msg)
Definition utils.h:59
#define UNUSED(x)
Definition utils.h:45
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_namespace_load()

srn_namespace_t * srn_namespace_load ( srn_namespace_t * ns)

Load the namespace's source from the filesystem into src_buffer, parse it, and populate the symbol table.

Not implemented, the current body returns null unconditionally, so callers cannot rely on it yet.

Definition at line 101 of file namespaces.c.

101 {
102 PANIC_IF_NULL(ns);
103 return nullptr;
104}